目录

句柄 进程 模块 读写

句柄 进程 内存

窗口句柄

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
HWND FindWindow(
  LPCTSTR IpClassName	//窗口的类名
  LPCTSTR IpWindowName	 //窗口的标题
); //返回窗口句柄

HWND FindWindowW(//使用Unicode字符集
  LPCTSTR IpClassName
  LPCTSTR IpWindowName //IpWindowName前要加L,如L”魔兽世界“
); 
HWND FindWindowA(//使用多字节字符集
  LPCTSTR IpClassName
  LPCTSTR IpWindowName
); 

HWND FindWindowEx(	//获得一个窗口的句柄,该窗口的类名和窗口名与给定的字符串相匹配
  HWND hwndParent,			//要查找子窗口的父窗口句柄 可为NULL
  HWND hwndChildAfter,	//子窗口句柄 可为NULL
  LPCTSTR lpszClass,		//窗口的类名 可为NULL
  LPCTSTR lpszWindow	  //窗口的标题 可为NULL
);	

//如果hwndParent为NULL,则函数以桌面窗口为父窗口,查找桌面窗口的所有子窗口。
//如果hwndParent为HWND_MESSAGE,函数仅查找所有消息窗口。
//子窗口必须为hwndPareRt窗口的直接子窗口而非后代窗口。
//如果hwndChildAfter为NULL,查找从hwndParent的第一个子窗口开始。
//如果hwndParent 和 hwndChildAfter同时为NULL,则函数查找所有的顶层窗口及消息窗口。


HWND FindWindowExA(	//使用多字节字符集
  HWND hwndParent,    	             
  HWND hwndChildAfter,
  LPCTSTR lpszClass,
  LPCTSTR lpszWindow
);

通过类名或窗口名查找,返回窗口句

进程ID和线程ID

1
2
3
4
DWORD GetWindowThreadProcessId(
  HWND hWnd,	//被查找窗口的句柄.
  LPDWORD lpdwProcessId	//进程号的存放地址
); //返回线程号

得到窗口句柄后通过GetWindowThreadProcessId这个函数来获得窗口所属进程ID和线程ID

进程句柄

1
HANDLE OpenProcess(DWORD dwDesiredAccess,BOOL bInheritHandle,DWORD dwProcessId);

打开一个已存在的进程对象,并返回进程的句柄

写入内存

三种方式:

  • 函数WriteProcessMemory(远程跨进程
1
2
3
4
5
6
7
BOOL WriteProcessMemory(
  HANDLE hProcess,	//进程句柄
  LPVOID lpBaseAddress,	//内存首地址
  LPVOID lpBuffer,	//指向要写的数据的指针
  DWORD nSize,			//字节数
  LPDWORD lpNumberOfBytesWritten //这个是返回实际写入的字节
); 

能写入某一进程的内存区域。入口区必须可以访问,否则操作将失败

  • 指针读取 (需要注入

    格式: *(读取类型*)地址

    • 封装函数
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    
    BYTE 内存_读字节型(DWORD 内存地址)
    {
      if(IsBadReadPtr((void*)内存地址,sizeof(BYTE))==0)	//验证是否具有读取访问权限
      {
        return *(BYTE*)内存地址;
      }
      return 0;
    }
    
    WORD 内存_读2字节型(DWORD 内存地址)
    {
      if(IsBadReadPtr((void*)内存地址,sizeof(WORD))==0)	//验证是否具有读取访问权限
      {
        return *(WORD*)内存地址;
      }
      return 0;
    }
    
    DWORD 内存_读4字节型(DWORD 内存地址)
    {
      if(IsBadReadPtr((void*)内存地址,sizeof(DWORD))==0)	//验证是否具有读取访问权限
      {
        return *(DWORD*)内存地址;
      }
      return 0;
    }
    
    FLOAT 内存_读浮点型(DWORD 内存地址)
    {
      if(IsBadReadPtr((void*)内存地址,sizeof(FLOAT))==0)	//验证是否具有读取访问权限
      {
        return *(FLOAT*)内存地址;
      }
      return 0;
    }
    
    char* 内存_读字符串(CHAR* 内存地址)
    {
      if(IsBadReadPtr((void*)内存地址,sizeof(char))==0)	//验证是否具有读取访问权限
      {
        return 内存地址;
      }
      return 0;
    }
    

    IsBadReadPtr详情 验证是否具有读取访问权限

  • 内联汇编(需要注入

读取内存

1
2
3
4
5
6
7
BOOL ReadProcessMemory(
  HANDLE hProcess, 				//目标进程句柄
  LPCVOID lpBaseAddress, 	//要读取的起始地址
  LPVOID lpBuffer, 				//存放读取数据的地址
  DWORD nSize, 						//要读取的字节数
  LPDWORD lpNumberOfBytesRead	//存放实际读取字节大小
); //返回值 成功非0,失败0

根据进程句柄读入该进程的某个内存空间lpBaseAddress的nSize字节,并写入缓冲区lpBuffer,多次计算基址和偏移即可

加载模块

GetModuleHandleA 获得应用程序或动指定模块的模块句柄

1
2
3
4
5
6
7
HMODULE GetModuleHandleA(
  [in, optional] LPCSTR lpModuleName	//加载模块的名称(.dll或.exe文件)
);//返回值是指定模块的句柄。
//如果函数失败,返回值为NULL

//实例
DWORD B =(DWORD)GetModuleHandleA("ELEMENTCLIENT.EXE");

遍历模块

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

int 遍历进程模块(DWORD 进程PID)
{
	HMODULE hMods[1024];	//20*sizeof(HMODULE)
	HANDLE 进程句柄;
	DWORD cbNeeded;
	unsigned int i;
	//Print the proess identifier.
	printf("\nprocess ID: %u\n",进程PID);
	//Get a handle to the process.
	进程句柄=OpenProcess(PROCESS_ALL_ACCESS,FALSE,进程PID);

	if (NULL == 进程句柄)
		return 1;

	//Get a list of all the modules in this process.
	BOOL br = EnumProcessModules(进程句柄,hMods,sizeof(hMods),&cbNeeded);
	if (br)
	{
		UINT32 模块数量=cbNeeded/sizeof(HMODULE);
		for ( i = 0; i < 模块数量; i++)
		{
			TCHAR szModName[MAX_PATH];

			//Get the full path to the module file.
			if(GetModuleFileNameEx(进程句柄,hMods[i],szModName,
									sizeof(szModName)/sizeof(TCHAR)))
			{
				//Print the module name and handle value.
				
				//_tprintf(TEXT("模块名[%d]=%s 地址=%08X\n"),i,szModName,hModes[i]);
				printf("模块名[%d]=%s 地址=%p\n",i,szModName,hMods[i]);
			}
		}
	}
	//Release the handle to the process.
	//
	CloseHandle(进程句柄);
	return 0;
}

获取窗口句柄

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18

HWND CFINDCODE::GetGameHwnd(void)
{
	HWND hNext = FindWindowExA(HWND_DESKTOP,0,0,0);
	HWND h2 = FindWindowExA(HWND_DESKTOP,hNext,0,0);
	int i =0;
	while(h2)
	{
		char buf[256]={0};
		GetWindowTextA(h2,buf,256);
		if (strstr(buf,szGameSubCaption))
		{
			break;
		}
		h2 = FindWindowExA(HWND_DESKTOP,h2,0,0);
	}
	return h2;
}

获取进程ID

1
2
3
4
5
6
7
8

DWORD CFINDCODE::GetPID()
{
	HWND h=GetGameHwnd();
	DWORD dwpid=0;
	GetWindowThreadProcessId(h,&dwpid);
	return dwpid;
}

获取进程句柄

1
2
3
4
5
6
7
HANDLE CFINDCODE::GetGameHp()
{
	DWORD dwPid = GetPID();
	HANDLE hp = OpenProcess(PROCESS_ALL_ACCESS,0,dwPid);
	// printf("hp=%hp, pid=%d\r\n",hp,dwPid);
	return hp;
}

获取EXE模块起始地址

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
UINT_PTR CFINDCODE::GetExeBase()
{
	UINT_PTR exeBase64=NULL;
	HMODULE hMods[1024];	//20*sizeof(HMODULE)
	
	DWORD cbNeeded;
	unsigned int i;
	HANDLE 进程句柄=GetGameHp();

	//Get a list of all the modules in this process.
	BOOL br = EnumProcessModules(进程句柄,hMods,sizeof(hMods),&cbNeeded);
	if (br)
	{
		UINT32 模块数量=cbNeeded/sizeof(HMODULE);
		for ( i = 0; i < 模块数量; i++)
		{
			TCHAR szModName[MAX_PATH];

			//Get the full path to the module file.
			if(GetModuleFileNameEx(进程句柄,hMods[i],szModName,
									sizeof(szModName)/sizeof(TCHAR)))
			{
				//如果是“*.exe”的模块,直接返回基址
				if (strstr(szModName,".exe"))
				{
					exeBase64 = (UINT_PTR)hMods[i];
				}
				//Print the module name and handle value.
				
				//_tprintf(TEXT("模块名[%d]=%s 地址=%08X\n"),i,szModName,hModes[i]);
				// printf("模块名[%d]=%s 地址=%p\n",i,szModName,hMods[i]);
			}
		}
	}
	//Release the handle to the process.
	//
	CloseHandle(进程句柄);
	return exeBase64;
}

获取EXE结束地址

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
UINT_PTR CFINDCODE::GetExeEnd()
{
	// HANDLE 进程句柄=GetGameHp();
	// UINT_PTR 模块基址 = GetExeBegin();
	// MEMORY_BASIC_INFORMATION meminfo;

	// //nSize函数写入lpBuffer的字节数,如果不等于sizeof(MEMORY_BASIC_INFORMATION)表示失败
	// SIZE_T nSize /*返回buf大小 */ = VirtualQueryEx(进程句柄,(LPCVOID)模块基址,&meminfo,sizeof(meminfo));
	// UINT_PTR 结束地址=(UINT_PTR)meminfo.AllocationBase+meminfo.RegionSize;
	// printf("GetExeEnd: AllocationBase=%llx,RegionSize=%X 结束地址=%llx \r\n",meminfo.AllocationBase,meminfo.RegionSize,结束地址);
	// return 结束地址;
	return GetExeBase()+GetExeSize();

}

获取EXE模块大小

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19

SIZE_T CFINDCODE::GetExeSize();		
{
	static SIZE_T nSize=0;
	if (nSize)
	{
		/* code */
		return nSize;
	}
	HANDLE 进程句柄=GetGameHp();
	UINT_PTR 模块基址 = GetExeBase();
	MEMORY_BASIC_INFORMATION meminfo;

	//nSize函数写入lpBuffer的字节数,如果不等于sizeof(MEMORY_BASIC_INFORMATION)表示失败
	SIZE_T nSize /*返回buf大小 */ = VirtualQueryEx(进程句柄,(LPCVOID)模块基址,&meminfo,sizeof(meminfo));
	nSize = meminfo.RegionSize;
	CloseHandle(进程句柄);
	return nSize;
}