请问如何定位到指定进程的数据段? 选择一个正在运行的进程,已经得到进程 ID 和句柄,请问如何在我的程序中查看其数据段中的数据? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 如果你知道数据的地址,ReadProcessMemory就可以了。全局变量的地址从PE里面很容易知道,局部变量在Stack上,基本没法儿读。 很简单, 给你一个根据段名字查找段地址的例子,按你的情况,只需要用ReadProcessMemory把对方进程前4096字节读入本地内存然后调用这个函数就可以找到你感兴趣的段在对方内存内的偏移和大小:DWORD GetSectionOffset(PVOID PE, LPSTR SectionName, PDWORD size){ PIMAGE_NT_HEADERS hdr = (PIMAGE_NT_HEADERS)(((PIMAGE_DOS_HEADER)PE)->e_lfanew + (LONG)PE); PIMAGE_SECTION_HEADER sec = (PIMAGE_SECTION_HEADER)((DWORD)hdr + sizeof(IMAGE_NT_HEADERS)); DWORD namelen = strlen(SectionName); for( DWORD i =0; i < hdr->FileHeader.NumberOfSections; i ++ ) { LPSTR name = (LPSTR)(sec[i].Name + (DWORD)PE); if( !strnicmp(name, SectionName, namelen) && (namelen >= 8 || name[namelen] == '\0') ) { if( size ) *size = sec[i].Misc.VirtualSize; return sec[i].VirtualAddress; } } return 0;} 问题是, 参数 PVOID PE 如何获得呢? 根据你这个函数的实现可以看出, PE 是指向 PIMAGE_NT_HEADERS 的, 可 PIMAGE_NT_HEADERS 在进程空间中的位置并不为 0, 该指针该如何定位? EnumProcessModules API可以列出一个Process里面的所有Module,还回来的HModule就是.exe Image Map到内存中的起始点,即PE的入口。把.exe对应那个Module,传到上面Function就可以了。 BOOL EnumProcessModules (HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded);EnumProcessModules 只能返回调用模块(DLL)的 HMODULE, 不能得到进程的 HMODULE。 这个PE参数就是你ReadProcessMemory获得的内存啊。大致流程如下:char buffer[4096];SIZE_T sz;....ReadProcessMemory(OtherProcessHandle, 0x00400000, buffer, 4096, &sz);DWORD offset, sectionSize;offset = GetSectionOffset(buffer, ".text", §ionSize);....PVOID data = malloc(sectionSize);ReadProcessMemory(OtherProcessHandle, 0x00400000+offset, data, &sz);....data就是你要读取的节的具体内容了 ReadProcessMemory(OtherProcessHandle, 0x00400000+offset, data, sectionSize, &sz); 我以前就用 GCC 的编译器将 PE 可执行程序的入口设成 0x00500000 过,依然正常执行。 楼主给分吧:// 读取指定进程的节,以notepad.exe为例,VS2005测试通过.//#include <windows.h>#include <Psapi.h>#pragma comment(lib, "psapi.lib")int main(int argc, char* argv[]){ PROCESS_INFORMATION ProcInfo = {0}; STARTUPINFO StartInfo = {0}; CreateProcess(NULL, "notepad.exe", NULL, NULL, FALSE, 0, NULL, NULL, &StartInfo, &ProcInfo); CloseHandle(ProcInfo.hProcess); CloseHandle(ProcInfo.hThread); HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, NULL, ProcInfo.dwProcessId); if(hProcess) { HMODULE hModule; DWORD cbNeeded; MODULEINFO modinfo; LPVOID lpbuf = NULL; SIZE_T nRead; if(EnumProcessModules(hProcess, &hModule, sizeof(HMODULE), &cbNeeded)) { GetModuleInformation( hProcess, hModule, &modinfo, sizeof(MODULEINFO) ); lpbuf = new BYTE[modinfo.SizeOfImage]; memset(lpbuf, 0, modinfo.SizeOfImage); ReadProcessMemory(hProcess, modinfo.lpBaseOfDll, lpbuf, modinfo.SizeOfImage, &nRead); //取得节数目 PIMAGE_FILE_HEADER pfh; int nSectionCount; pfh = (PIMAGE_FILE_HEADER) ((LPVOID)((BYTE *)(lpbuf)+((PIMAGE_DOS_HEADER)(lpbuf))->e_lfanew+sizeof(DWORD))); nSectionCount = pfh->NumberOfSections; int i; PIMAGE_SECTION_HEADER psh; psh = (PIMAGE_SECTION_HEADER) ((LPVOID)((BYTE *)(lpbuf)+((PIMAGE_DOS_HEADER)(lpbuf))->e_lfanew+sizeof(DWORD)+sizeof(IMAGE_FILE_HEADER)+sizeof(IMAGE_OPTIONAL_HEADER))); // 注意:Pe中节是根据数据的属性来分的,而不管数据之间的逻辑关系 // 所以只根据属性来判断节是否为数据节。这一规则在有节合并的Pe中犹为明显。 // 我这里用名称来判定。 for(i=0; i < nSectionCount; i++) { if(0 == lstrcmp(".data", (char *)psh->Name)) { /* do something you want; */ MessageBox(0, "section .data", "hello", 0); } psh++; } } if(lpbuf) delete[] lpbuf; } return 0;} 多谢 lisunlin0(李林) 老兄,原来你在我另外的哪个帖子中就说明白了,奈何我蠢笨如牛,居然没看明白 :( 不过老兄居然给了个完整的实现,真是个热心人啊,真真是谢谢你了。我先去另外哪个帖子给你分,这个帖子还有个问题问你一下,EnumProcessModules(hProcess, &hModule, sizeof(HMODULE), &cbNeeded)这一句是不是有点问题啊?我看MSDN上的例子用的是 HMODULE hModules[1024]; EnumProcessModules(hProcess, hModules, sizeof(hModules), &cbNeeded);还有,EnumProcessModules 函数返回的是一个 Module 数组,你怎么直接把第一个当进程 HMODULE 使用了?这是这个函数本身就规定了的吗?需不需要再判断一下? EnumProcessModules可以取得进程中所有的HMODULE,且HMODULE数组的第一个是正好是进程主模块(exe)的HMODULE。所以可以直接用EnumProcessModules(hProcess, hModules, sizeof(hModules), &cbNeeded);取得,当然,如果楼主要读取进程中其它模块(比如某个Dll)的节,就应该用GetModuleFileNameEx(hProcess, hModule,...);来判断一下是不是目标模块。谢谢楼主的巨额馈分,我就不客气啦,嘻嘻 CEvent的效率 保存图片上的注释 请问数据库中time类型怎么转换成CString类型 能不能通过程序捕捉到在浏览器中的点击按钮或超链的事件 排序问题 MDI中,能不能实现各个子窗口对应不同的TOOLBAR,(即更改主框架中的TOOLBAR) 控件技巧的问题 紧急求救,如何得到一个CFileDialog对象? 关于程序调试的问题 各位大虾,能不能推荐几个象本站一样的技术论坛(人气枉的), 或者是好的技术网站。 如何提升自己进程的权限? 高手们帮忙,如何给系统的快捷菜单添加自定义的菜单项~~~
{
PIMAGE_NT_HEADERS hdr = (PIMAGE_NT_HEADERS)(((PIMAGE_DOS_HEADER)PE)->e_lfanew + (LONG)PE);
PIMAGE_SECTION_HEADER sec = (PIMAGE_SECTION_HEADER)((DWORD)hdr + sizeof(IMAGE_NT_HEADERS));
DWORD namelen = strlen(SectionName);
for( DWORD i =0; i < hdr->FileHeader.NumberOfSections; i ++ )
{
LPSTR name = (LPSTR)(sec[i].Name + (DWORD)PE);
if( !strnicmp(name, SectionName, namelen) && (namelen >= 8 || name[namelen] == '\0') )
{
if( size )
*size = sec[i].Misc.VirtualSize;
return sec[i].VirtualAddress;
}
}
return 0;
}
根据你这个函数的实现可以看出, PE 是指向 PIMAGE_NT_HEADERS 的, 可 PIMAGE_NT_HEADERS 在进程空间中的位置并不为 0, 该指针该如何定位?
BOOL EnumProcessModules (HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded);EnumProcessModules 只能返回调用模块(DLL)的 HMODULE, 不能得到进程的 HMODULE。
char buffer[4096];
SIZE_T sz;
....ReadProcessMemory(OtherProcessHandle, 0x00400000, buffer, 4096, &sz);DWORD offset, sectionSize;
offset = GetSectionOffset(buffer, ".text", §ionSize);....PVOID data = malloc(sectionSize);
ReadProcessMemory(OtherProcessHandle, 0x00400000+offset, data, &sz);
....data就是你要读取的节的具体内容了
// 读取指定进程的节,以notepad.exe为例,VS2005测试通过.
//
#include <windows.h>
#include <Psapi.h>
#pragma comment(lib, "psapi.lib")int main(int argc, char* argv[])
{
PROCESS_INFORMATION ProcInfo = {0};
STARTUPINFO StartInfo = {0};
CreateProcess(NULL, "notepad.exe", NULL, NULL, FALSE, 0, NULL, NULL, &StartInfo, &ProcInfo);
CloseHandle(ProcInfo.hProcess);
CloseHandle(ProcInfo.hThread);
HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, NULL, ProcInfo.dwProcessId);
if(hProcess)
{
HMODULE hModule;
DWORD cbNeeded;
MODULEINFO modinfo;
LPVOID lpbuf = NULL;
SIZE_T nRead;
if(EnumProcessModules(hProcess, &hModule, sizeof(HMODULE), &cbNeeded))
{
GetModuleInformation( hProcess, hModule, &modinfo, sizeof(MODULEINFO) );
lpbuf = new BYTE[modinfo.SizeOfImage];
memset(lpbuf, 0, modinfo.SizeOfImage);
ReadProcessMemory(hProcess, modinfo.lpBaseOfDll, lpbuf, modinfo.SizeOfImage, &nRead);
//取得节数目
PIMAGE_FILE_HEADER pfh;
int nSectionCount; pfh = (PIMAGE_FILE_HEADER) ((LPVOID)((BYTE *)(lpbuf)+((PIMAGE_DOS_HEADER)(lpbuf))->e_lfanew+sizeof(DWORD)));
nSectionCount = pfh->NumberOfSections;
int i;
PIMAGE_SECTION_HEADER psh; psh = (PIMAGE_SECTION_HEADER) ((LPVOID)((BYTE *)(lpbuf)+((PIMAGE_DOS_HEADER)(lpbuf))->e_lfanew+sizeof(DWORD)+sizeof(IMAGE_FILE_HEADER)+sizeof(IMAGE_OPTIONAL_HEADER)));
// 注意:Pe中节是根据数据的属性来分的,而不管数据之间的逻辑关系
// 所以只根据属性来判断节是否为数据节。这一规则在有节合并的Pe中犹为明显。
// 我这里用名称来判定。
for(i=0; i < nSectionCount; i++)
{
if(0 == lstrcmp(".data", (char *)psh->Name))
{
/*
do something you want;
*/
MessageBox(0, "section .data", "hello", 0);
}
psh++;
}
}
if(lpbuf)
delete[] lpbuf;
} return 0;
}
HMODULE hModules[1024];
EnumProcessModules(hProcess, hModules, sizeof(hModules), &cbNeeded);
还有,EnumProcessModules 函数返回的是一个 Module 数组,你怎么直接把第一个当进程 HMODULE 使用了?这是这个函数本身就规定了的吗?需不需要再判断一下?
谢谢楼主的巨额馈分,我就不客气啦,嘻嘻