C語言獲取任意Windows程序模塊基地址

我已無力接住你,再也不能抗風雨

函數

這裏主要用到的函數是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進行查看對比:
dump

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章