今天发现一个问题,算是细节 如果有知道的请讲解一下   MEMORY_BASIC_INFORMATION mbi;
   BOOL bOk = (VirtualQueryEx(hProcess, pvAddress, &mbi, sizeof(mbi)) 
      == sizeof(mbi));
得到内存信息此时
mbi.State 是MEM_COMMIT并且 mbi.Protect 为 PAGE_EXECUTE_READ
也就是此块的内存是 读取和执行权限  但是我们用WriteProcess 完全可以写此处的内存  虽然核心编程中的操作是失败的话就修改内存属性为PAGE_EXECUTE_READWRITE 然后尝试写操作我的问题就是 为什么没有写权限的内存块却可以执行写操作

解决方案 »

  1.   

    写权限和执行权限没有必然联系吧,正如linux下用rwx表示,w和x是独立的
      

  2.   

    MBI的State域 用于指明所有相邻页面的状态。
      MEM_COMMIT 指明已分配物理内存或者系统页文件。
      MEM_FREE 空闲状态。该区域的虚拟地址不受任何内存的支持。该地址空间没
      有被保留。改状态下AllocationBase、AllocationProtect、Protect
      和Type等成员均未定义。
      MEM_RESERVE 指明页面被保留,但是没有分配任何物理内存。该状态下Protect成
      员未定。这个域跟读写无关,你理解大大的错误。要看可读可写,你应该看AllocationProtect 这个域
      

  3.   

    本帖最后由 Tr0j4n 于 2010-06-02 09:08:25 编辑
      

  4.   

    本帖最后由 Tr0j4n 于 2010-06-02 09:09:00 编辑
      

  5.   

    PAGE_EXECUTE_READ  意味着 只读,并不是 执行与读
      

  6.   

    MSDN:PAGE_EXECUTE_READ 0x20 Enables execute and read access to the committed region of pages. An attempt to write to the committed region results in an access violation.  
      

  7.   

    我也这么怀疑,不过,以前有个用DELPHI的,用WriteProcessMemory直接写代码段成功的,他都没意识到权限的问题。
      

  8.   

    本帖最后由 Tr0j4n 于 2010-06-02 09:10:55 编辑
      

  9.   

    内存保护类型是对本进程中程序操作内存的限制,WriteProcessMemory不受此限制。因为WriteProcessMemory的主要目的是调试程序,所以只要是可执行的内存,都允许改写。
      

  10.   

    晕,楼主不是在看核心编程吗?怎么不知道WriteProcessMemory的问题呢?在DLL注入那章就有说到这个问题的。
      

  11.   

    我有9成把握 书中没有说此问题
    原来WriteProcessMemory不会考虑内存的保护属性,这样说的话估计内存保护属性是为了帮助程序员自己发现失误的操作吧. int *p 指向一个 没有写操作权限的内存的时候确实无法给内容赋值
      

  12.   


    难道Windows核心编程和Programming Applications for Microsoft Windows不是同一本书?
      

  13.   


    是吧  我的是第五版 书名叫 Windows via c/c++   这是核心编程中一个例子中 修改内存的代码               if (!WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, 
                        sizeof(pfnNew), NULL) && (ERROR_NOACCESS == GetLastError())) {
                      DWORD dwOldProtect;
                      if (VirtualProtect(ppfn, sizeof(pfnNew), PAGE_WRITECOPY, 
                         &dwOldProtect)) {                     WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, 
                            sizeof(pfnNew), NULL);
                         VirtualProtect(ppfn, sizeof(pfnNew), dwOldProtect, 
                            &dwOldProtect);
                      }如果“WriteProcessMemory 不受内存保护属性限制” 成立 并且Windows核心编程提到此内容 代码中的
    ERROR_NOACCESS == GetLastError()  就没有必要了,此句话的意思是 判断WriteProcessMemory失败的原因是不是因为拒绝访问,也就是写权限不够
    期待一下写轮兔更深的理解
      

  14.   

    对WriteProcessMemory进行逆向,结果如下.text:7C80220F ; BOOL __stdcall WriteProcessMemory(HANDLE hProcess,LPVOID lpBaseAddress,LPVOID lpBuffer,DWORD nSize,LPDWORD lpNumberOfBytesWritten)
    .text:7C80220F                 public WriteProcessMemory
    .text:7C80220F WriteProcessMemory proc near
    .text:7C80220F
    .text:7C80220F lpPageStartAddress= dword ptr -8
    .text:7C80220F lpPageSize      = dword ptr -4
    .text:7C80220F hProcess        = dword ptr  8
    .text:7C80220F lpBaseAddress   = dword ptr  0Ch
    .text:7C80220F lpBuffer        = dword ptr  10h
    .text:7C80220F nSize           = dword ptr  14h
    .text:7C80220F lpNumberOfBytesWritten= dword ptr  18h
    .text:7C80220F
    .text:7C80220F                 mov     edi, edi        ; 
    .text:7C802211                 push    ebp
    .text:7C802212                 mov     ebp, esp
    .text:7C802214                 push    ecx
    .text:7C802215                 push    ecx
    .text:7C802216                 mov     eax, [ebp+lpBaseAddress]
    .text:7C802219                 push    ebx             ; 
    .text:7C802219                                         ; 
    .text:7C80221A                 mov     ebx, [ebp+nSize]
    .text:7C80221D                 push    esi             ; 
    .text:7C80221E                 mov     esi, ds:NtProtectVirtualMemory
    .text:7C802224                 push    edi             ; 
    .text:7C802225                 mov     edi, [ebp+hProcess]
    .text:7C802228                 mov     [ebp+lpPageStartAddress], eax
    .text:7C80222B                 lea     eax, [ebp+nSize] ; 这里让nSize偏移处保持旧的access值
    .text:7C80222E                 push    eax
    .text:7C80222F                 push    40h             ; PAGE_EXECUTE_READWRITE,亮点
    .text:7C802231                 lea     eax, [ebp+lpPageSize]
    .text:7C802234                 push    eax
    .text:7C802235                 lea     eax, [ebp+lpPageStartAddress]
    .text:7C802238                 push    eax
    .text:7C802239                 push    edi
    .text:7C80223A                 mov     [ebp+lpPageSize], ebx
    .text:7C80223D                 call    esi ; NtProtectVirtualMemory
    .text:7C80223F                 cmp     eax, 0C000004Eh ; STATUS_SECTION_PROTECTION
    .text:7C80223F                                         ;
    .text:7C80223F                                         ; 这里没有执行权限
    .text:7C802244                 jz      short lblDontHaveExecuteRights
    .text:7C802246
    .text:7C802246 lblTestMemoryAccess:                    ; CODE XREF: WriteProcessMemory+A4j
    .text:7C802246                 test    eax, eax
    .text:7C802248                 jl      short lblNoteError
    .text:7C80224A                 mov     eax, [ebp+nSize]
    .text:7C80224D                 test    al, 0CCh        ; 这里做位与判断,和我们判断页权限的代码相同,这里做了实现:
    .text:7C80224D                                         ;
    .text:7C80224D                                         ; PAGE_EXECUTE_READWRITE |
    .text:7C80224D                                         ; PAGE_READWRITE |
    .text:7C80224D                                         ; PAGE_EXECUTE_WRITECOPY |
    .text:7C80224D                                         ; PAGE_WRITECOPY
    .text:7C80224D                                         ;
    .text:7C80224D                                         ; 
    .text:7C80224F                 jz      short lblNotMMF_OrShared ; 判断是否和旧 access值相同
    .text:7C80224F                                         ;
    .text:7C80224F                                         ; PAGE_NOACCESS |
    .text:7C80224F                                         ; PAGE_READONLY
    .text:7C802251                 lea     ecx, [ebp+nSize] ; 恢复旧的 access
    .text:7C802251                                         ; 
    .text:7C802254                 push    ecx
    .text:7C802255                 push    eax
    .text:7C802256                 lea     eax, [ebp+lpPageSize]
    .text:7C802259                 push    eax
    .text:7C80225A                 lea     eax, [ebp+lpPageStartAddress]
    .text:7C80225D                 push    eax
    .text:7C80225E                 push    edi
    .text:7C80225F                 call    esi ; NtProtectVirtualMemory 亮点哦
    .text:7C802261                 lea     eax, [ebp+hProcess]
    .text:7C802264                 push    eax
    .text:7C802265                 push    ebx
    .text:7C802266                 push    [ebp+lpBuffer]
    .text:7C802269                 push    [ebp+lpBaseAddress]
    .text:7C80226C                 push    edi
    .text:7C80226D                 call    ds:NtWriteVirtualMemory ;再写
    .text:7C802273                 mov     ecx, [ebp+lpNumberOfBytesWritten]
    .text:7C802276                 test    ecx, ecx
    .text:7C802278                 jnz     loc_7C80231C
    .text:7C80227E
    .text:7C80227E lblTestIfMMF_OrSharedWriteFailed:       ; CODE XREF: WriteProcessMemory+112j
    .text:7C80227E                 test    eax, eax
    .text:7C802280                 jl      short lblNoteError
    .text:7C802282
    .text:7C802282 lblFlushInstructions:                   ; CODE XREF: WriteProcessMemory+E1j
    .text:7C802282                 push    ebx
    .text:7C802283                 push    [ebp+lpBaseAddress]
    .text:7C802286                 push    edi
    .text:7C802287                 call    ds:NtFlushInstructionCache   这个地方熟悉吧?刷缓存
    .text:7C80228D                 xor     eax, eax
    .text:7C80228F                 inc     eax
    .text:7C802290
    .text:7C802290 lblExitNoError:                         ; CODE XREF: WriteProcessMemory+108j
    .text:7C802290                                         ; WriteProcessMemory+119j
    .text:7C802290                 pop     edi             ; 
    .text:7C802291                 pop     esi
    .text:7C802292                 pop     ebx
    .text:7C802293                 leave
    .text:7C802294                 retn    14h
    .text:7C802297 ; ---------------------------------------------------------------------------
    .text:7C802297
    .text:7C802297 lblNoteError:                           ; CODE XREF: WriteProcessMemory+39j
    .text:7C802297                                         ; WriteProcessMemory+71j
    .text:7C802297                 push    eax
    .text:7C802298                 call    sub_7C80936B    ; 这个函数把错误码转换为系统错误并将其放在TEB里面
    .text:7C802298                                         ; 
    .text:7C802298                                         ; 
    .text:7C80229D                 jmp     lblFail         ; 错误了
    .text:7C8022A2 ; ---------------------------------------------------------------------------
    .text:7C8022A2
    .text:7C8022A2 lblDontHaveExecuteRights:               ; CODE XREF: WriteProcessMemory+35j
    .text:7C8022A2                 lea     eax, [ebp+nSize]
    .text:7C8022A5                 push    eax
    .text:7C8022A6                 push    4               ; PAGE_READWRITE
    .text:7C8022A8                 lea     eax, [ebp+lpPageSize]
    .text:7C8022AB                 push    eax
    .text:7C8022AC                 lea     eax, [ebp+lpPageStartAddress]
    .text:7C8022AF                 push    eax
    .text:7C8022B0                 push    edi
    .text:7C8022B1                 call    esi ; NtProtectVirtualMemory
    .text:7C8022B3                 jmp     short lblTestMemoryAccess
    .text:7C8022B5 ; ---------------------------------------------------------------------------
    .text:7C8022B5
    .text:7C8022B5 lblNotMMF_OrShared:                     ; CODE XREF: WriteProcessMemory+40j
    .text:7C8022B5                 test    al, 3           ; 判断access值:
    .text:7C8022B5                                         ; PAGE_NOACCESS |PAGE_READONLY
    .text:7C8022B7                 jnz     short lblPageNoAccessOrReadOnly ; 跳还是不跳?
    .text:7C8022B9                 lea     eax, [ebp+hProcess]
    .text:7C8022BC                 push    eax
    .text:7C8022BD                 push    ebx             ; nSize
    .text:7C8022BE                 push    [ebp+lpBuffer]
    .text:7C8022C1                 push    [ebp+lpBaseAddress]
    .text:7C8022C4                 push    edi             ; hProcess
    .text:7C8022C5                 call    ds:NtWriteVirtualMemory ; 写
    .text:7C8022CB                 mov     [ebp+lpBuffer], eax
    .text:7C8022CE                 mov     eax, [ebp+lpNumberOfBytesWritten]
    .text:7C8022D1                 test    eax, eax
    .text:7C8022D3                 jz      short lblRestoreOldAccess
    .text:7C8022D5                 mov     ecx, [ebp+hProcess]
    .text:7C8022D8                 mov     [eax], ecx
    .text:7C8022DA
    .text:7C8022DA lblRestoreOldAccess:                    ; CODE XREF: WriteProcessMemory+C4j
    .text:7C8022DA                 lea     eax, [ebp+nSize]
    .text:7C8022DD                 push    eax             ; &nSize
    .text:7C8022DE                 push    [ebp+nSize]     ; 恢复旧的access值
    .text:7C8022E1                 lea     eax, [ebp+lpPageSize]
    .text:7C8022E4                 push    eax
    .text:7C8022E5                 lea     eax, [ebp+lpPageStartAddress]
    .text:7C8022E8                 push    eax
    .text:7C8022E9                 push    edi
    .text:7C8022EA                 call    esi ; NtProtectVirtualMemory
    .text:7C8022EC                 cmp     [ebp+lpBuffer], 0
    .text:7C8022F0                 jge     short lblFlushInstructions
    .text:7C8022F2                 mov     esi, 0C0000005h ; STATUS_ACCESS_VIOLATION
    .text:7C8022F7                 jmp     short lblThrowAccessViolation
      

  15.   

    .text:7C8022F9 ; ---------------------------------------------------------------------------
    .text:7C8022F9
    .text:7C8022F9 lblPageNoAccessOrReadOnly:              ; CODE XREF: WriteProcessMemory+A8j
    .text:7C8022F9                 lea     ecx, [ebp+nSize] ; 恢复旧的 access等级
    .text:7C8022FC                 push    ecx
    .text:7C8022FD                 push    eax
    .text:7C8022FE                 lea     eax, [ebp+lpPageSize]
    .text:7C802301                 push    eax
    .text:7C802302                 lea     eax, [ebp+lpPageStartAddress]
    .text:7C802305                 push    eax
    .text:7C802306                 push    edi
    .text:7C802307                 call    esi             ; NtProtectVirtualMemory
    .text:7C802309                 xor     esi, esi
    .text:7C80230B
    .text:7C80230B lblThrowAccessViolation:                ; CODE XREF: WriteProcessMemory+E8j
    .text:7C80230B                 push    0C0000005h
    .text:7C802310                 call    sub_7C80936B
    .text:7C802315                 mov     eax, esi
    .text:7C802317                 jmp     lblExitNoError  ; 清理现场
    .text:7C80231C ; ---------------------------------------------------------------------------
    .text:7C80231C
    .text:7C80231C loc_7C80231C:                           ; CODE XREF: WriteProcessMemory+69j
    .text:7C80231C                 mov     edx, [ebp+hProcess]
    .text:7C80231F                 mov     [ecx], edx
    .text:7C802321                 jmp     lblTestIfMMF_OrSharedWriteFailed
    .text:7C802326 ; ---------------------------------------------------------------------------
    .text:7C802326
    .text:7C802326 lblFail:                                ; CODE XREF: WriteProcessMemory+8Ej
    .text:7C802326                 xor     eax, eax        ; 错误!
    .text:7C802328                 jmp     lblExitNoError  ; 清理现场
    .text:7C802328 WriteProcessMemory endp在你向一个保护的Section里面写发生错误的时候,WriteProcessMemory会调用NtProcectVirtualMemory尝试修改access为PAGE_READWRITE,因为需要执行。这就是前面cnzdgs大牛所说的类似意思吧。如果NtProtectVirtualMemory的调用也是白,系统在TEB保存一个access验证错误的码,然后函数返回0。最后,假设所有调用都成功了,NtProtectVirtualMemory也没有失败,WriteProcessMemory开始检查原来的access,就是原来存在nSize的那个地方的那个。这个时候一个恶心的系统特性就出来了,如果原来就是PAGE_EXECUTE_READWRITE | PAGE_READWRITE | PAGE_EXECUTE_WRITECOPY | PAGE_WRITECOPY系统也会给你降到PAGE_NOACCESS | PAGE_READONLY!
      

  16.   

    前两天 刚把汇编学了   单独的一句指令看得懂 连起来就完全不知道什么意思了
    这么说 WriteProcessMemory还是会收到 保护属性的影响 但他会自动尝试修改?
    至于 降到PAGE_NOACCESS | PAGE_READONLY 是什么意思int main()
    {
    DWORD flProtect = PAGE_EXECUTE_READ;//此处不能有 WRITECOPY属性 否则VirtualAlloc 将失败
    printf("测试属性 :%x\n",flProtect);
    void *myMemory = VirtualAlloc(NULL,1024*4,MEM_RESERVE|MEM_COMMIT,flProtect); MEMORY_BASIC_INFORMATION mbi;
    BOOL bOk = (VirtualQuery(myMemory,&mbi,sizeof(mbi)) == sizeof(mbi)); printf("初始属性 :%x\n",mbi.Protect); WriteProcessMemory(GetCurrentProcess(),myMemory,"abc",sizeof("abc"),NULL); bOk = (VirtualQuery(myMemory,&mbi,sizeof(mbi)) == sizeof(mbi));
    printf("之后  :%x\n",mbi.Protect);
    return 0;
    }我测试了几种属性 没有改变啊
      

  17.   

    WriteProcessMemory调用完毕,access属性已经恢复了好吧~~~你理解能力真差
      

  18.   

    这要怪你以 降到PAGE_NOACCESS | PAGE_READONLY! 结尾啊  逆向出的代码只看的懂中文你逆向用的软件吗 还是直接反汇编自己写的我正看驱动呢  看完这块 回来好好品品