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

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

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

计算过程:

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

image.png

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

image.png

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

image.png

但这仅仅是偏移,如果我们想得到真实的虚拟内存地址,还需要得到模块地址,用模块地址+偏移才能得到 .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;
        }
    }
}

image.png

相关文章
|
1月前
|
Linux C++
Linux c/c++文件的基本操作
在Linux环境下使用C/C++进行文件的基本操作,包括文件的创建、写入、读取、关闭以及文件描述符的定位。
19 0
Linux c/c++文件的基本操作
|
5月前
|
存储 分布式数据库 API
技术好文:VisualC++查看文件被哪个进程占用
技术好文:VisualC++查看文件被哪个进程占用
|
2月前
|
C++ 内存技术
[转]Visual C++内嵌swf文件并播放
[转]Visual C++内嵌swf文件并播放
|
1月前
|
Linux C++
Linux c/c++文件虚拟内存映射
这篇文章介绍了在Linux环境下,如何使用虚拟内存映射技术来提高文件读写的速度,并通过C/C++代码示例展示了文件映射的整个流程。
45 0
|
1月前
|
Linux C++
Linux c/c++文件移动
这篇文章介绍了在Linux环境下,使用C/C++语言通过命令方式和文件操作方式实现文件移动的方法。
64 0
|
2月前
|
Linux API C++
超级好用的C++实用库之文件目录操作
超级好用的C++实用库之文件目录操作
30 0
|
2月前
|
JavaScript 前端开发 测试技术
一个google Test文件C++语言案例
这篇文章我们来介绍一下真正的C++语言如何用GTest来实现单元测试。
19 0
|
4月前
|
NoSQL API Redis
c++开发redis module问题之为什么在使用RedisModule_GetApi之前要通过((void**)ctx)[0]这种方式获取其地址
c++开发redis module问题之为什么在使用RedisModule_GetApi之前要通过((void**)ctx)[0]这种方式获取其地址
|
3月前
|
存储 算法 C++
【C++】C++ QT实现Huffman编码器与解码器(源码+课程论文+文件)【独一无二】
【C++】C++ QT实现Huffman编码器与解码器(源码+课程论文+文件)【独一无二】
|
3月前
|
存储 数据挖掘 C语言
【C/C++】C/C++车辆交通违章管理系统(源码+数据文件)【独一无二】
【C/C++】C/C++车辆交通违章管理系统(源码+数据文件)【独一无二】