C++ 定位文件 .text 区段地址
2023-09-11 14:14:03 时间
首先声明,.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;
}
}
}
最后上效果图:
明天又周一了,好气啊,抓紧再打两把自走棋吧 。
相关文章
- C++ 读取 txt 文件件中某一行
- 在VS2010上使用C#调用非托管C++生成的DLL文件(图文讲解)
- C++ opencv高速样例学习——读图显示
- C/C++下载文件_上传文件
- C/C++glob函数遍历文件夹所有文件
- C/C++中从文件末尾反向读取N行文件记录(末尾读取文件)
- 在Ubuntu环境下使用c++ vcpkg包管理 安装sqlite_orm包文件
- c++ vector实例
- c++ template函数的声明和实现需要在同一个文件中
- C/C++的“文件包含”处理时头文件被重复包含的问题探究及解决方法(用最简单的例子进行说明)
- C++中TCP socket传输文件
- C++ Learning 4
- 使用c++filt命令还原C++编译后的函数名
- 结合C++和GDAL实现shapefile(shp)文件的创建和写入
- 《C++ 开发从入门到精通》——2.2 分析C++的程序结构
- 《C++并发编程实战》——1.3 在C++中使用并发和多线程
- C++读取numpy数据二进制文件
- 基于C++实现图书推荐与评论系统【100010534】
- 基于C++实现文件的哈夫曼编码与解码【100010226】
- 基于QT(C++)+CSV文件存储开发(WinForm)图书管理系统【100010008】
- Ubuntu16.04下Tensorflow C++编译并调用pb文件(一)
- Devc++读取不了当前目录下的文件的解决方法
- 【C++】文件操作
- C++编程——文件操作
- C/C++读写csv文件
- 【华为OD机试真题 java、python、c++、JsNode】最大利润、贪心的商人(100%通过+复盘思路)
- C++算法学习资料整理
- C++STL粗浅认识
- C++创建类的对象(类的初始化)的方法
- C/C++教程 第四章 —— 理解文件操作
- C++ STL 仿函数使用