前言:
上一周,在52的精華帖中,看到有位大佬用Python制作了鬼泣5的修改器,看完才知道,原來Python也可以對內(nèi)存進(jìn)行操作,出于對技術(shù)的好奇,看完以后,決定自己也嘗試一下。
要用到的工具: CE,Ollybdg,
用Python,讀取這款游戲中,人物的血量。
先打開游戲吧,打開CE,對游戲附加。
輸入199在輸入框中,先進(jìn)行一次掃描
接著去打怪,扣血以后在進(jìn)行一次掃描
等一會,人物會自動回血,然后你會神奇的發(fā)現(xiàn),這兩個數(shù)據(jù)中有一個的數(shù)值會變成199,然后上次數(shù)值哪里顯示198,那就是我們要找的數(shù)據(jù)
26B871F0
打開OD,把地址放在里面搜索,斷點(diǎn),然后使用巴拉拉魔法力量,找出偏移量 [[[[D0DF1C]+1C]+28]+288]
……………………………………………………………………………………………………………………………………………………………
現(xiàn)在開始進(jìn)入Python
要進(jìn)行32位的讀寫,首先了解一下要用到的幾個函數(shù),通過百度找到的,大多都是C/C++的資料。
FindWindowA在Python中為FindWindow
FindWindow這個函數(shù)檢索處理頂級窗口的類名和窗口名稱匹配指定的字符串。這個函數(shù)不搜索子窗口。
HWND FindWindowA(
LPCSTR lpClassName,//窗口類名
LPCSTR lpWindowName//窗口名稱,例如計(jì)算器
);
GetWindowThreadProcessId
在得到窗口句柄后我們可以通過GetWindowThreadProcessId這個函數(shù)來獲得窗口所屬進(jìn)程ID和線程ID,從而判斷創(chuàng)建窗口的進(jìn)程和線程。
DWORD GetWindowThreadProcessId(
HWND hWnd, //傳入的窗口句柄
LPDWORD lpdwProcessId //返回的進(jìn)程ID地址。
);
OpenProcess
OpenProcess 函數(shù)用來打開一個已存在的進(jìn)程對象,并返回進(jìn)程的句柄。
HANDLE OpenProcess(
DWORD dwDesiredAccess, //想擁有的該進(jìn)程訪問權(quán)限
BOOL bInheritHandle,//表示所得到的進(jìn)程句柄是否可以被繼承
DWORD dwProcessId//被打開進(jìn)程的PID
);
ReadProcessMemory
是一個內(nèi)存操作函數(shù), 其作用為根據(jù)進(jìn)程句柄讀入該進(jìn)程的某個內(nèi)存空間;函數(shù)原型為BOOL. 當(dāng)函數(shù)讀取成功時返回1, 失敗則返回0
BOOL ReadProcessMemory(
HANDLE hProcess, //進(jìn)程句柄
LPCVOID lpBaseAddress,//讀出數(shù)據(jù)的地址
LPVOID lpBuffer,//存放讀取數(shù)據(jù)的地址
SIZE_T nSize,//讀出的數(shù)據(jù)大小
SIZE_T *lpNumberOfBytesRead//數(shù)據(jù)的實(shí)際大小
);
首先導(dǎo)入模塊
# -*- coding: utf-8 -*-
import win32process#進(jìn)程模塊
from win32con import PROCESS_ALL_ACCESS #Opencress 權(quán)限
import win32api#調(diào)用系統(tǒng)模塊
import ctypes#C語言類型
from win32gui import FindWindow#界面
?
對游戲的一個讀操作,讀取血量。
?
def GetProcssID(address,bufflength):
pid = ctypes.c_ulong() // 設(shè)置 pid 為 無符號單精度類型
kernel32 = ctypes.windll.LoadLibrary("kernel32.dll")//加載動態(tài)鏈接庫
hwnd = FindWindow("XYElementClient Window", u"口袋西游")//獲取窗口句柄
hpid, pid = win32process.GetWindowThreadProcessId(hwnd)//獲取窗口ID
hProcess = win32api.OpenProcess(PROCESS_ALL_ACCESS, False, pid)//獲取進(jìn)程句柄
ReadProcessMemory = kernel32.ReadProcessMemory
addr = ctypes.c_ulong()
ReadProcessMemory(int(hProcess), address, ctypes.byref(addr), bufflength, None)//讀內(nèi)存
win32api.CloseHandle(hProcess)//關(guān)閉句柄
return addr.value
def main():
addr = GetProcssID(0xD0DF1C, 4)
ret = addr + 0x1C
ret2 = GetProcssID(ret, 4)
ret3 = ret2 + 0x28
ret4 = GetProcssID(ret3, 4)
ret5 = ret4 + 0x288
ret6 = GetProcssID(ret5, 4) // 傳入偏移地址
print ("Hp:%d" % ret6)
?
?
if __name__ == '__main__':
main()
ReadProcessMemory(int(hProcess), address, ctypes.byref(addr), bufflength, None)
參數(shù)解析:1.傳入進(jìn)程句柄 2.地址,就是血量的地址,那幾條偏移. 3. 第三個要傳入指針 。4.長度
運(yùn)行結(jié)果: