
在两种情景下获得指定进程基地址的方法
发布日期:2021-05-19 04:41:12
浏览次数:16
分类:博客文章
本文共 2124 字,大约阅读时间需要 7 分钟。
情景一
最近在写一个简单调试器的时候,需要在CreateProcess()创建调试进程后获得程序的基地址。
一开始我是在CreateProcess()前,利用内存映射文件来加载指定可执行文件,然后从文件的NT文件头中读取程序的加载基地址。但是我忽略了有可能程序发生基址随机化,这样的话就获得的基地址就不准确了。解决方法
可以在CreateProcess()创建进程前利用内存映射文件读NT文件头中的入口地址的RVA(入口地址随基地址变化,但是入口地址的RVA是不变的)。然后在CreateProcess()创建调试进程后,获取调试进程的进程环境块(CONTEXT),context . eax即为其程序的入口地址。然后减去入口地址的RVA即为真正的基地址。
HANDLE hFile; //文件句柄 HANDLE hMapFile; //内存映射文件对象句柄 LPVOID lpMapFile; //内存映射文件指针 hFile = CreateFile(ExeName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); hMapFile = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL); lpMapFile = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0); IMAGE_DOS_HEADER* lpDosMZ = (IMAGE_DOS_HEADER*)lpMapFile; IMAGE_NT_HEADERS* lpNT = (IMAGE_NT_HEADERS*)lpMapFile; lpNT = (IMAGE_NT_HEADERS*)((BYTE*)lpNT + lpDosMZ->e_lfanew); dwEntryPointRVA = lpNT->OptionalHeader.AddressOfEntryPoint; //获得入口地址的RVA UnmapViewOfFile(lpMapFile); //撤销映射 CloseHandle(hMapFile); //关闭内存映射对象句柄 CloseHandle(hFile); //关闭文件 //创建被调试程序进程 CreateProcess( ExeName, NULL, NULL, NULL, FALSE, // 不可继承 DEBUG_ONLY_THIS_PROCESS | DEBUG_PROCESS, // 调试模式启动 (DEBUG_ONLY_THIS_PROCESS标志表示其不能调试进程如果被调试的话,此新进程不会成为其调试进程的调试对象) NULL, NULL, &si, &pi); //获取入口地址 stContext.ContextFlags = CONTEXT_ALL; GetThreadContext(pi.hThread, &stContext); dwEntryPoint = stContext.Eax; //获取基地址 hInstance = dwEntryPoint - dwEntryPointRVA;
情景二
如果要调试一个已运行的进程需要对其进行附加,附加之后需要获得其基地址。(进一步获得其入口地址)
解决方法
可以先创建一个进程快照,获得指定进程的PID之后。在建立一个基于这个进程的模块快照,然后获得此进程第一个模块的基地址,此基地址即为这个进程的基地址。然后在通过基地址调用ReadProcessMemory()读取NT头获得入口地址RVA,在与基地址相加即为此进程的入口地址。
//dwData是指定进程的PID,通过创建进程快照获得 //进程模块快照,(获得已运行进程基地址) hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwData); Module32First(hModuleSnap, &me32); dwInstance = (DWORD)me32.modBaseAddr; //进程基地址 CloseHandle(hModuleSnap); //获取入口地址RVA DWORD lpNT; //指向NT头 ReadProcessMemory(hIsDebuggedProcess, (LPVOID)(dwInstance + 0x3c), &lpNT, 4, NULL); lpNT = lpNT + dwInstance; ReadProcessMemory(hIsDebuggedProcess, (LPVOID)(lpNT + 0x28), &dwEntryPointRVA, 4, NULL); //获取入口地址 dwEntryPoint = dwInstance + dwEntryPointRVA;
发表评论
最新留言
很好
[***.229.124.182]2025年04月22日 20时32分14秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
git远程仓库切换
2019-03-14
带照片捕捉功能的ESP32-CAM PIR运动检测器
2019-03-15
如何使用SSH远程管理Linux服务器
2019-03-15
降级到旧版本macOS的3种方法
2019-03-15
学习Vue.js2.0(国外视频教程)
2019-03-15
wxPython和PyOpenGL视频
2019-03-15
在30分钟内学习PHP
2019-03-15
Python http.server 服务器
2019-03-15
Python svm 支持向量机
2019-03-15
OpenStack 最小化安装配置(一):物理机网桥配置
2019-03-15
PS快速美白照片
2019-03-15
ubuntu 16.04 镜像下载
2019-03-15
CUDA9.1、cuDNN7在Ubuntu16.04上的安装
2019-03-15
微信小程序云开发:怎么删除云函数?已解决
2019-03-15
第一次被黑
2019-03-15
PyCharm配置anaconda环境
2019-03-15