选择一个正在运行的进程,已经得到进程 ID 和句柄,请问如何在我的程序中查看其数据段中的数据?

解决方案 »

  1.   

    如果你知道数据的地址,ReadProcessMemory就可以了。全局变量的地址从PE里面很容易知道,局部变量在Stack上,基本没法儿读。
      

  2.   

    很简单, 给你一个根据段名字查找段地址的例子,按你的情况,只需要用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;
    }
      

  3.   

    问题是, 参数 PVOID PE 如何获得呢?
      

  4.   


        根据你这个函数的实现可以看出, PE 是指向 PIMAGE_NT_HEADERS 的, 可 PIMAGE_NT_HEADERS 在进程空间中的位置并不为 0, 该指针该如何定位?
      

  5.   

    EnumProcessModules API可以列出一个Process里面的所有Module,还回来的HModule就是.exe Image Map到内存中的起始点,即PE的入口。把.exe对应那个Module,传到上面Function就可以了。
      

  6.   


    BOOL EnumProcessModules (HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded);EnumProcessModules 只能返回调用模块(DLL)的 HMODULE, 不能得到进程的 HMODULE。
      

  7.   

    这个PE参数就是你ReadProcessMemory获得的内存啊。大致流程如下:
    char buffer[4096];
    SIZE_T sz;
    ....ReadProcessMemory(OtherProcessHandle, 0x00400000, buffer, 4096, &sz);DWORD offset, sectionSize;
    offset = GetSectionOffset(buffer, ".text", &sectionSize);....PVOID data = malloc(sectionSize);
    ReadProcessMemory(OtherProcessHandle, 0x00400000+offset, data, &sz);
    ....data就是你要读取的节的具体内容了
      

  8.   

    ReadProcessMemory(OtherProcessHandle, 0x00400000+offset, data, sectionSize, &sz);
      

  9.   

    我以前就用 GCC 的编译器将 PE 可执行程序的入口设成 0x00500000 过,依然正常执行。
      

  10.   

    楼主给分吧:
    // 读取指定进程的节,以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;
    }
      

  11.   

    多谢 lisunlin0(李林) 老兄,原来你在我另外的哪个帖子中就说明白了,奈何我蠢笨如牛,居然没看明白 :( 不过老兄居然给了个完整的实现,真是个热心人啊,真真是谢谢你了。我先去另外哪个帖子给你分,这个帖子还有个问题问你一下,EnumProcessModules(hProcess, &hModule, sizeof(HMODULE), &cbNeeded)这一句是不是有点问题啊?我看MSDN上的例子用的是
        HMODULE    hModules[1024];
        EnumProcessModules(hProcess, hModules, sizeof(hModules), &cbNeeded);
    还有,EnumProcessModules 函数返回的是一个 Module 数组,你怎么直接把第一个当进程 HMODULE 使用了?这是这个函数本身就规定了的吗?需不需要再判断一下?
      

  12.   

    EnumProcessModules可以取得进程中所有的HMODULE,且HMODULE数组的第一个是正好是进程主模块(exe)的HMODULE。所以可以直接用EnumProcessModules(hProcess, hModules, sizeof(hModules), &cbNeeded);取得,当然,如果楼主要读取进程中其它模块(比如某个Dll)的节,就应该用GetModuleFileNameEx(hProcess, hModule,...);来判断一下是不是目标模块。
    谢谢楼主的巨额馈分,我就不客气啦,嘻嘻