我已無力接住你,再也不能抗風雨
函數
這裏主要用到的函數是EnumProcessModulesEx
:
BOOL EnumProcessModulesEx(
HANDLE hProcess,
HMODULE *lphModule,
DWORD cb,
LPDWORD lpcbNeeded,
DWORD dwFilterFlag
);
hProcess
表示處理的句柄;
lphModule
表示接收模塊句柄列表的數組;
cb
表示lphModule數組的大小,以字節爲單位;
lpcbNeeded
表示在lphModule數組中存儲所有模塊句柄所需的字節數;
dwFilterFlag
表示過濾條件,下列值之一:
值 | 含義 |
---|---|
LIST_MODULES_32BIT 0x01 |
列出32位模塊 |
LLIST_MODULES_64BIT 0x02 |
列出64位模塊 |
LIST_MODULES_ALL 0x03 |
列出所有模塊 |
LIST_MODULES_DEFAULT 0x00 |
使用默認行爲 |
所以我們在用這個函數時需要先利用函數FindWindow()
找到程序的窗口句柄,然後利用函數GetWindowThreadProcessId()
找到程序的進程ID,最後調用函數OpenProcess()
找到程序進程的打開句柄,最後可以調用EnumProcessModulesEx()
函數獲取模塊的基地址;
實例
這裏直接以獲取植物大戰殭屍的基地址來演示:
#include<stdio.h>
#include<windows.h>
#include<psapi.h>
int main(){
HWND hWnd = FindWindow(NULL,"植物大戰殭屍中文版");
if (hWnd == NULL){ //如果無法獲取句柄則報錯
printf("無法獲取窗口句柄,請檢查進程是否存在!\n");
system("pause");
return -1;
}
DWORD pro_id;
GetWindowThreadProcessId(hWnd, &pro_id); //獲取進程ID
if(pro_id == 0){
printf("無法獲取進程ID\n");
system("pause");
return 0;
}
printf("進程id: %d\n",pro_id);
//打開進程對象,並獲取進程句柄
HANDLE hpro = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, pro_id);
if (hpro == 0){
printf("無法獲取進程句柄");
}
printf("進程句柄id: %d\n",hpro);
// 獲取每一個模塊加載基址
DWORD pro_base = NULL;
HMODULE hModule[100] = {0};
DWORD dwRet = 0;
int num = 0;
int bRet = EnumProcessModulesEx(hpro, (HMODULE *)(hModule), sizeof(hModule),&dwRet,NULL);
if (bRet == 0){
printf("EnumProcessModules");
}
// 總模塊個數
num = dwRet/sizeof(HMODULE);
printf("總模塊個數: %d\n",num);
// 打印每一個模塊加載基址
char lpBaseName[100];
for(int i = 0;i<num;i++){
GetModuleBaseNameA(hpro,hModule[i],lpBaseName,sizeof(lpBaseName));
printf("%-2d %-25s基址: 0x%p\n",i,lpBaseName,hModule[i]);
}
pro_base = (DWORD)hModule[0];
printf("程序基址: 0x%p\n",pro_base);
DWORD sun_addr = pro_base + 0x002A9EC0;
printf("陽光基址: 0x%p\n",sun_addr);
DWORD sun_value;
DWORD new_sun_value = 2000;
DWORD kill_1 = pro_base + 0x0013130F; //0x0053130F
DWORD code_1 = 0x9090ff29; //0x20247c2b
DWORD kill_2 = pro_base + 0x00131044; //0x00531044
WORD code_2 = 0xC929; //0xc82b
// 0x0048728C
ReadProcessMemory(hpro,(PVOID)sun_addr,&sun_addr,4,0);
sun_addr = sun_addr + 0x768;
ReadProcessMemory(hpro,(PVOID)sun_addr,&sun_addr,4,0);
sun_addr = sun_addr + 0x5560;
ReadProcessMemory(hpro,(PVOID)sun_addr,&sun_value,4,0);
printf("陽光地址: %p\n當前陽光值: %d\n",sun_addr,sun_value);
printf("修改的陽光值: 2000\n");
//scanf("%d",&new_sun_value);
WriteProcessMemory(hpro, (LPVOID)sun_addr, &new_sun_value, 4, 0); //修改陽光
WriteProcessMemory(hpro, (LPVOID)kill_1, (LPVOID)&code_1, 4, 0); //普通殭屍秒殺
WriteProcessMemory(hpro, (LPVOID)kill_2, (LPVOID)&code_2, 2, 0); //帽子殭屍秒殺
system("pause");
return 0;
}
可以通過CE進行查看對比: