C/C++ 定位文件 .text 区段地址

首先声明,.text 区段的起始地址是需要计算的,无论是哪个结构体里都不会直接提供某个区段的直接地址(虚拟内存地址),我就是因为想偷懒所以翻了好久的结构体成员列表,结果头都翻炸了还是没找到, !!!∑(゚Д゚ノ)ノ

计算过程:

1.先看 IMAGE_DOS_HEADER STRUCT 这个结构体,它有一个成员 e_lfanew 指向了 NT 头。(我这里的e_lfanew = 0x100,需要根据实际情况来动态获取)

2.再看 _IMAGE_NT_HEADERS 结构体,FileHeader 成员是文件头结构体对象,所以再加 0x4

3.同理来到 _IMAGE_FILE_HEADER 结构体,SizeOfOptionalHeader 成员为可选头的大小,所以在加 0x14,最后因为可选头大小为 0xE0,所以总体的偏移就是:0x100+0x4+0x14+0xE0 = 0x1F8 = 504

但这仅仅是偏移,如果我们想得到真实的虚拟内存地址,还需要得到模块地址,用模块地址+偏移才能得到 .text 区段的入口地址。那么问题来了,怎么得到模块地址呢?

下面放上代码:

HMODULE GetProcessModuleHandle(DWORD pid, CONST TCHAR* moduleName) {	// 根据 PID 、模块名(需要写后缀,如:".dll"),获取模块入口地址。
	MODULEENTRY32 moduleEntry;
	HANDLE handle = NULL;
	handle = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid); //  获取进程快照中包含在th32ProcessID中指定的进程的所有的模块。
	if (!handle) {
		CloseHandle(handle);
		return NULL;
	}
	ZeroMemory(&moduleEntry, sizeof(MODULEENTRY32));
	moduleEntry.dwSize = sizeof(MODULEENTRY32);
	if (!Module32First(handle, &moduleEntry)) {
		CloseHandle(handle);
		return NULL;
	}
	do {
		if (_tcscmp(moduleEntry.szModule, moduleName) == 0) { return moduleEntry.hModule; }
	} while (Module32Next(handle, &moduleEntry));
	CloseHandle(handle);
	return 0;
}

int main(){
	HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);  // 进程快照句柄
	PROCESSENTRY32 process = { sizeof(PROCESSENTRY32) };	// 存放进程快照的结构体

	//  遍历进程
	while (Process32Next(hProcessSnap, &process)) {
		// 找到进程
		string s_szExeFile = process.szExeFile; // char* 转 string
		if (s_szExeFile == "HEX2ASCII.exe") {
			HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process.th32ProcessID); // 进程句柄
			
			// 打印模块地址
			cout << "HEX2ASCII.exe PE头地址:" << GetProcessModuleHandle(process.th32ProcessID, "HEX2ASCII.exe") << endl;
			
			// 把模块地址转换成 int ,方便后面的计算
			int peAddress = (int)GetProcessModuleHandle(process.th32ProcessID, "HEX2ASCII.exe");
			cout << ".text 区段起始地址:" << hex << peAddress + 504 << endl;
			
			// 读取 .text 区段的前 4 个字节,验证地址是否正确
			DWORD szBuffer; // 内存数组暂存
			ReadProcessMemory(hProcess, (LPVOID)(peAddress + 504), &szBuffer, 4, NULL);
			cout << ".text 前4个字节::" << hex << szBuffer << endl;
		}
	}
}


版权声明: 本博客,文章与代码均为学习时整理的笔记,博客中除去明确标注有参考文献的文章,其他文章【均为原创】作品,转载请务必【添加出处】,您添加出处是我创作的动力!

警告:如果您恶意转载本人文章,则您的整站文章,将会变为我的原创作品,请相互尊重!
原文地址:https://www.cnblogs.com/LyShark/p/15019772.html