Windows内存详解(四)OD内存断点初步分析

来源:互联网 发布:mac桌面下方图标怎么加 编辑:程序博客网 时间:2024/04/28 16:26

内存断点原理:

       内存断点原理,通过将内存断点所在内存页的属性修改为内存断点属性(non-access or non-writable),程序执行时,对目标内存页中所有数据的访问或写,都会抛出异常,OD通过截获此异常,然后对比,存储在某一内存的内存断点信息表的地址,判断是否匹配内存断点地址范围,匹配则中断程序执行,否则,继续执行。

IDA静态分析:

本例利用IDA和OD动静结合,分析OD内存断点基本流程,以及内存断点存储在哪儿段内存地址。

首先将OD丢进IDA中,在程序函数列表中搜索breakpoint字符串,如图:


我们仅分析内存断点,通过function name 可知:_setmembreakpoint是我们需要分析的函数。跳到该函数分析,入口点部分截图:



可知,该函数有3个参数,通过F5(hexray),其反编译伪代码:

[cpp] view plaincopy
  1. signed int __cdecl Setmembreakpoint(__int16 a1, unsigned int a2, int a3)  
  2. {  
  3.   _DWORD *v3; // eax@3  
  4.   signed int result; // eax@5  
  5.   
  6.   if ( !dword_4D8138 && VersionInformation.dwPlatformId != 2 )  
  7.   {  
  8.     v3 = Findmemory(a2);  
  9.     if ( a2 < 0x80000000 )     //判断内存断点地址是否在用户内存中(0x800000~0xffffffff属于系统内核内存区域)  
  10.     {  
  11.       if ( v3 && *((_BYTE *)v3 + 11) & 1 )   //判断内存断点是否在资源内存区域  
  12.       {  
  13.         if ( MessageBoxA(  
  14.                hWnd,  
  15.                "You are going to set memory breakpoint on resource. This breakpoint, when hit within system DLL, may freeze Windows or cause system crash. Do you really want to set this breakpoint?",  
  16.                "Memory breakpoint on resource",  
  17.                0x14u) != 6 )  
  18.           return -1;  
  19.       }  
  20.       else  
  21.       {  
  22.         if ( v3 && *((_BYTE *)v3 + 11) & 4 )    //判断内存断点地址是否在堆栈内存区域  
  23.         {  
  24.           MessageBoxA(  
  25.             hWnd,  
  26.             "You are going to set memory breakpoint on stack. This doesn't work on Win95-based operating systems.",  
  27.             "Memory breakpoint on stack",  
  28.             0x10u);  
  29.           return -1;  
  30.         }  
  31.       }  
  32.     }  
  33.     else  
  34.     {  
  35.       if ( MessageBoxA(  
  36.              hWnd,  
  37.              "You are going to set memory breakpoint in system area. This breakpoint may freeze Windows or cause system crash. Do you really want to set this breakpoint?",  
  38.              "Memory breakpoint in system area",  
  39.              0x14u) != 6 )  
  40.         return -1;  
  41.     }  
  42.   }  
  43.   if ( sub_418E24() )  
  44.   {  
  45.     result = -1;  
  46.   }  
  47.   else  
  48.   {  
  49.     dword_4D813C = a2;  
  50.     dword_4D8140 = a3;  
  51.     dword_4D8144 = a2 & 0xFFFFF000;  
  52.     dword_4D8148 = (a3 + a2 + 4095) & 0xFFFFF000;  
  53.     dword_4D8138 = (HIBYTE(a1) & 0x10) != 0;  
  54.     dword_4D8D5C = 1;  
  55.     if ( a1 & 3 && a3 )  
  56.     {  
  57.       if ( (a1 & 3) == 2 )  
  58.         dword_4D814C = 32;  
  59.       else  
  60.         dword_4D814C = 1;  
  61.       if ( dword_4D5A5C == 3 )  
  62.         sub_419034();  
  63.       result = 0;  
  64.     }  
  65.     else  
  66.     {  
  67.       result = 0;  
  68.     }  
  69.   }  
  70.   return result;  
  71. }  

OD调试OD动态分析:

我们通过OD来调试OD,分析setmembreakpoint函数的流程。

将OD丢进OD中,并在setmembreakpoint入口地址下断点(F2),并运行被调试的OD。然后在被调试的OD程序中加载调试一个任意程序,并在某一地址下内存访问断点,如图(被调试的od程序中,在红线0x401377处下了内存断点):


下完该内存断点,调试程序OD立即捕获,并中断在setmembreakpoint的入口地址,然后我们通过单步,查看该函数的三个参数分别是神马:


发现esi中的值即我们在被调试程序中所下的内存断点地址,edi为内存断点的字节长度(0x401377处指令为6bytes)。ebx值其实是内存断点的属性(访问:0x00000003,写:0x00000002),这里我们之前下的是内存访问断点,所以ebx:0x00000003。

继续单步执行,在0x4192fb处跳转到0x41938d。先不管这里为什么会调转。继续单步,发现之后的汇编操作将我们所下的内存断点信息存储到了某段内存中,如图:


当前eax=0x401377,即我们的内存断点地址。

分析汇编:

[plain] view plaincopy
  1. 004193A2  |.  A3 3C814D00   mov     dword ptr [4D813C], eax   //将内存断点地址存储到0x4d813c处         
  2. 004193A7  |.  8BC8          mov     ecx, eax      //ecx=eax=0x401377 内存断点地址  
  3. 004193A9  |.  03C2          add     eax, edx      //edx为内存断点字节长度,这里是取内存断点结束地址,本例中,eax=0x401377+6=0x40137d  
  4. 004193AB  |.  81E1 00F0FFFF and     ecx, FFFFF000   //相当于去该内存地址所在的内存页起始地址   ecx=0x401000  
  5. 004193B1  |.  05 FF0F0000   add     eax, 0FFF      //将内存断点结束地址加上了一个内存页大小  
  6. 004193B6  |.  8915 40814D00 mov     dword ptr [4D8140], edx  //将内存断点长度存储到0x4d8140  
  7. 004193BC  |.  25 00F0FFFF   and     eax, FFFFF000   //取该内存地址所在的内存页地址  
  8. 004193C1  |.  890D 44814D00 mov     dword ptr [4D8144], ecx   //将内存断点坐在内存也的起始地址存储到0x4d8144处  
  9. 004193C7  |.  F6C7 10       test    bh, 10    //设置zf属性,执行后,zf=1  
  10. 004193CA  |.  A3 48814D00   mov     dword ptr [4D8148], eax   //本例中eax=402000  
  11. 004193CF  |.  0F95C0        setne   al      //if zf=1 then al=0, if zf=0 then al=1  
  12. 004193D2  |.  83E0 01       and     eax, 1        //之后 eax=0x00000000  
  13. 004193D5  |.  83E3 03       and     ebx, 3        //ebx之前存储的是内存断点属性(访问or 写)  
  14. 004193D8  |.  A3 38814D00   mov     dword ptr [4D8138], eax    //存储这个不知道有何用途  
  15. 004193DD  |.  C705 5C8D4D00>mov     dword ptr [4D8D5C], 1    
  16. 004193E7  |.  85DB          test    ebx, ebx  
  17. 004193E9  |.  74 04         je      short 004193EF  
  18. 004193EB  |.  85FF          test    edi, edi       //edi存的是内存断点字节长度  
  19. 004193ED  |.  75 04         jnz     short 004193F3   //跳转成功  
  20. 004193EF  |>  33C0          xor     eax, eax  
  21. 004193F1  |.  EB 2B         jmp     short 0041941E  
  22. 004193F3  |>  83FB 02       cmp     ebx, 2           //ebx与2 比较,判断是否是内存写属性  
  23. 004193F6  |.  75 0C         jnz     short 00419404     //不是则跳转到0x419404(访问属性)  
  24. 004193F8  |.  C705 4C814D00>mov     dword ptr [4D814C], 20   //内存写属性,则将0x20存储在0x4d814c  
  25. 00419402  |.  EB 0A         jmp     short 0041940E  
  26. 00419404  |>  C705 4C814D00>mov     dword ptr [4D814C], 1    //内存访问属性,将0x01存储在0x4d814c  
  27. 0041940E  |>  833D 5C5A4D00>cmp     dword ptr [4D5A5C], 3  
  28. 00419415  |.  75 05         jnz     short 0041941C  
  29. 00419417  |.  E8 18FCFFFF   call    00419034  
  30. 0041941C  |>  33C0          xor     eax, eax  
  31. 0041941E  |>  5F            pop     edi  
  32. 0041941F  |.  5E            pop     esi  
  33. 00419420  |.  5B            pop     ebx  
  34. 00419421  |.  5D            pop     ebp  
  35. 00419422  \.  C3            retn  

通过对上面的汇编代码的分析,我们基本上可以定位内存断点信息的存储地址:0x4d8138~0x4d814f ,本例如图:


0x4d8138~0x40813b:0x00000000 未知

0x4d813c~0x4d813f: 0x00401377 内存断点起始地址

0x4d8140~0x4d8143: 0x00000006 内存断点长度

0x4d8144~0x4d8147: 0x00401000 内存断点地址所在的内存页起始地址

0x4d8148~0x4d814b: 0x00402000 内存断点尾部地址+内存也大小地址后,所在的内存页起始地址(这里有所疑问,为什么要加上0xfff,而不是直接取内存断点尾部地址所在的内存页起始地址,本例中,应该也是0x401000)。

0x4d814c~0x4d814f:0x00000001 内存断点属性(访问:0x00000001,写:0x00000020,与ebx区分开)

对该段内存的赋值其实在初始化一个结构体,该结构体存储内存断点相关信息:

Typedef struct membrakpointinfo

Dword unrecognized;//0x4d8138~0x40813b 未知

Dwordmemaddr;   //0x4d813c~0x4d813f 内存断点起始地址

Dword size;        //0x4d8140~0x4d8143:0x00000006 内存断点长度

Dword base1;      //0x4d8144~0x4d8147内存断点地址所在的内存页起始地址

Dword base2;     //0x4d8148~0x4d814b:0x00402000 内存断点尾部地址+内存也大小地址后,所在的内存页起始地址

Dword memtype;  //0x4d814c~0x4d814f 内存断点属性

}

0 0
原创粉丝点击