最近遇到一个问题.我在动态链接库dll中要访问主程序的MEM_MAPPED内存(权限是RW,存有大量数据),插入汇编代码如下:LPVOID pData;
__asm                  
{
mov  eax,[0x77604C]     //0x0077604C位于主程序.data段,可以访问
mov  pData,[eax]        //eax=0x0166eb38位于主程序MEM_PRIVATE内存(权限是RW),
                        //想获取数据指针pData,这时访问出错!
                           //(其中pData指到主程序MEM_MAPPED内存)
}
....
执行第2句mov  pData,[eax]出错(eax=0x0166eb38位于主程序MEM_PRIVATE内存,权限是RW)!
请问,如何访问主程序空间中属性为MEM_PRIVATE和MEM_MAPPED的内存以便解决这个难题?谢谢.

解决方案 »

  1.   

    同一进程内不必考虑MEM_PRIVATE。
    mov  pData,[eax]汇编语言中没有这种内存到内存赋值的指令,是编译出错吧?
      

  2.   

    谢谢回答。
    少写了一句,应该是这样:
    mov  eax,[0x77604C]     //0x0077604C位于主程序.data段,可以访问 
    mov  eax,[eax]          //这里出错
    mov  pData,eax
      
      

  3.   

    mov eax,[eax]出错肯定是eax指向了一个当前进程不可读的地址,与DLL以及MEM_PRIVATE和MEM_MAPPED无关。
    mov eax,[0x77604C]是把0x77604C地址中的数据读到eax里面,接着mov eax,[eax]是取eax指向的地址中的值,换种说法,0x77604C地址应该是一个指针变量,并且储存着一个有效的指针,这样才行。
      

  4.   


    "eax指向了一个当前进程不可读的地址." 这个地址是0x0166eb38位于主程序MEM_PRIVATE内存(权限是RW),位于主程序通过内存分配函数诸如_malloc(...)得到的一块内存中.
      

  5.   

    你在EXE程序中调用DLL这个函数之前加入这几行代码看看是不是一样出错。
      

  6.   

    谢谢楼上!
    在exe中加入测试代码
             int m_i;
    typedef int (*MYPROC)(LPVOID); 
    MYPROC ProcAdd;
    static int* pData; 
    pData=(int*)malloc(0x100);
    *pData=1234;
    HINSTANCE  hinstLib =LoadLibrary("FxjFunc.dll");
    ProcAdd = (MYPROC) GetProcAddress(hinstLib, "_FractalDAY@4");
    m_i=ProcAdd(pData) ;
    UpdateData(false);
    FreeLibrary(hinstLib); 
    在dll中
    __declspec(dllexport) int WINAPI FractalDAY(CALCINFO* pData)
    {
    int i; 
    __asm
    {
    mov  eax,0x0042c040
    mov  eax,[eax]
    mov  eax,[eax]
    mov  i,eax
    }return i;
    }
    经过测试没有出现问题,顺利通过。
    但在dll用相同方法读取他方的exe类似的MEM_PRIVATE内存(权限是RW)时,就出现错误(应该是第三句)。 不知是什么原因?
      

  7.   

    MEM_PRIVATE是说明该内存是进程私有的,只有本进程内才能访问,你是怎么测试他方的exe的?讲详细一点。
    假设你在1.exe中加载DLL并将其注入2.exe的进程中,然后再在1.exe的进程中调用DLL的导出函数读2.exe进程中的内存当然会失败。
      

  8.   

    谢谢楼上!
    是这样的。大智慧新一代股票软件dzh2.exe V3.00.08.0306 ,提供了c语言接口以便于提高公式的灵活性,但是遗憾的是每次只提供当前股票的相关数据,而在这方面公司没有升级解决提供所有数据的功能,我的公式又需要这个功能。为了解决这个问题,我通过分析,dzh2.exe使用了多线程,得知0x77604C处存放数据指针的指针(位于MEM_PRIVATE内存).我就在dll中读取该地址指针以便于得到数据指针(比如day.dat文件映射到MEM_MAPPED内存(权限是RW),结果出现错误。具体代码如下:
    __asm                  
    {
    mov  eax,0X77604C
    mov  eax,[eax] //取指针,取出来是0x0166eb38,地址0x0166eb38位于MEM_PRIVATE内存。
    mov  eax,[eax] //再从0x0166eb38取MEM_MAPPED内存的指针,出错!

    }
    不知问题出在哪里?如何解决?谢谢。
      

  9.   

    你直接OpenProcess用PROCESS_VM_READ权限打开目标进程,然后ReadProcessMemory,这样试试。
      

  10.   

    加入测试代码如下:
    DWORD dwNumberOfBytesRead;
    pM1=(LPCVOID)0x77604C;
    ReadProcessMemory(pr,pM1,&pM2,4,&dwNumberOfBytesRead);
    ReadProcessMemory(pr,pM2,&pM3,4,&dwNumberOfBytesRead);
    __asm                  
    {
    mov eax,pM3
    lea eax,[eax+0x1bc]
    mov pM4,eax
    }
    ReadProcessMemory(pr,pM4,&pM5,4,NULL);
    ReadProcessMemory(pr,pM5,&pM6,4,NULL);
    char  buffer[32];
    sprintf(buffer,"%x",pM2);
    sprintf(buffer,"%x",pM6);
    MessageBox(NULL,buffer,TEXT("fxjfunc.dll"),MB_OKCANCEL);
    用OllyDbg跟踪,没有错误.但是实际测试时,对话框显示"cccccccc",读入失败!
    不知问题出在哪里?如何解决?谢谢。
      

  11.   

    另外注意一下,lea eax,[eax+0x1bc]这条指令相当于add eax, 1BCH。
    其实你现在所用的汇编语言都可以用C语言的强制转换指针类型等操作来代替。
      

  12.   

    用C语言的强制转换指针类型等操作来代替,如下:
    DWORD pM1,pM2,pM3,pM4,pM5,pM6,dwNumberOfBytesRead;
    HANDLE pr=OpenProcess(PROCESS_VM_READ,false,GetCurrentProcessId()); pM1=0x77604C;
    ReadProcessMemory(pr,(LPCVOID)pM1,&pM2,4,&dwNumberOfBytesRead);
    ReadProcessMemory(pr,(LPCVOID)pM2,&pM3,4,&dwNumberOfBytesRead);
    pM3+=0x1bc;
    ReadProcessMemory(pr,(LPCVOID)pM3,&pM5,4,&dwNumberOfBytesRead);
    ReadProcessMemory(pr,(LPCVOID)pM5,&pM6,4,&dwNumberOfBytesRead);
    char  buffer[32];
    sprintf(buffer,"%x",pM6);
    MessageBox(NULL,buffer,TEXT("fxjfunc.dll"),MB_OKCANCEL);
    但是一样出问题.
      

  13.   

    那段内存是Reserved还是Committed? 如果是filemapping, 则可能这段内存还未提交
      

  14.   

    OpenProcess时应该用目标进程的ID而不是GetCurrentProcessId。
      

  15.   

    由dzh2.exe中直接调用该dll的一个输出函数,执行顺序是从dzh2.exe到dll中,使用GetCurrentProcessId会不对吗?纳闷.
      

  16.   

    如果是这样就是同一进程了,直接读就可以,不用ReadProcessMemory了。如果直接读有错,应该是指针不对。
      

  17.   

    我用ollydbg跟踪,能读到正确的指针,且能读需要的数据.但实际调用时出错.纳闷.