OD内存断点初步分析

内存断点原理:

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

IDA静态分析:

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

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

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

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

signed int __cdecl Setmembreakpoint(__int16 a1, unsigned int a2, int a3)
{
  _DWORD *v3; // [email protected]
  signed int result; // [email protected]

  if ( !dword_4D8138 && VersionInformation.dwPlatformId != 2 )
  {
    v3 = Findmemory(a2);
    if ( a2 < 0x80000000 )     //判断内存断点地址是否在用户内存中(0x800000~0xffffffff属于系统内核内存区域)
    {
      if ( v3 && *((_BYTE *)v3 + 11) & 1 )   //判断内存断点是否在资源内存区域
      {
        if ( MessageBoxA(
               hWnd,
               "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?",
               "Memory breakpoint on resource",
               0x14u) != 6 )
          return -1;
      }
      else
      {
        if ( v3 && *((_BYTE *)v3 + 11) & 4 )    //判断内存断点地址是否在堆栈内存区域
        {
          MessageBoxA(
            hWnd,
            "You are going to set memory breakpoint on stack. This doesn't work on Win95-based operating systems.",
            "Memory breakpoint on stack",
            0x10u);
          return -1;
        }
      }
    }
    else
    {
      if ( MessageBoxA(
             hWnd,
             "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?",
             "Memory breakpoint in system area",
             0x14u) != 6 )
        return -1;
    }
  }
  if ( sub_418E24() )
  {
    result = -1;
  }
  else
  {
    dword_4D813C = a2;
    dword_4D8140 = a3;
    dword_4D8144 = a2 & 0xFFFFF000;
    dword_4D8148 = (a3 + a2 + 4095) & 0xFFFFF000;
    dword_4D8138 = (HIBYTE(a1) & 0x10) != 0;
    dword_4D8D5C = 1;
    if ( a1 & 3 && a3 )
    {
      if ( (a1 & 3) == 2 )
        dword_4D814C = 32;
      else
        dword_4D814C = 1;
      if ( dword_4D5A5C == 3 )
        sub_419034();
      result = 0;
    }
    else
    {
      result = 0;
    }
  }
  return result;
}

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,即我们的内存断点地址。

分析汇编:

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

}

参考文章:http://bbs.pediy.com/showthread.php?t=65221

时间: 2024-11-06 02:17:29

OD内存断点初步分析的相关文章

U-BOOT-2016.07移植 (第一篇) 初步分析

U-BOOT-2016.07移植 (第一篇) 初步分析 目录 U-BOOT-201607移植 第一篇 初步分析 目录 编译和移植环境 更新交叉编译工具 1 下载arm-linux-gcc 443 2 安装arm-linux-gcc 443 安装环境Ubuntu 910 下载u-boot-201607并解压 分析顶层Makefile 1 找出目标依赖关系 2 总结 初次编译u-boot 1 配置 2 编译 分析u-boot启动流程 1 分析startS 2 分析crt0S 3 总结 1. 编译和移

Android内存泄露案例分析

一款优秀的Android应用,不仅要有完善的功能,也要有良好的体验,而性能是影响体验的一个重要因素.内存泄露是Android开发中常见的性能问题.这篇文章,通过我们曾经遇到的一个真实的案例,来讲述一个内存泄露问题,从发现到分析定位,再到最终解决的全过程. 这里把整个过程分为四个阶段: 第一阶段,现场勘查,分析Bug现象,找出有用线索: 第二阶段,初步推断,根据之前的线索,推断可能导致Bug的原因,并且进一步验证推断是否正确: 第三阶段,探究根源,找出导致Bug的真正原因: 第四阶段,解决方案,研

vector的内存分配机制分析

该程序初步演示了我对vector在分配内存的时候的理解.可能有误差,随着理解的改变,改代码可以被修改. 1 /* 2 功能说明: 3 vector的内存分配机制分析. 4 代码说明: 5 vector所管理的内存地址是连续的.程序在不断的push_back的过程中,如果当前所管理的内存不能装下新的元素的时候,程序会创建更大的地址连续的空间来保存更多的元素. 6 这种机制会引起大量的无用的复制和删除操作.如果vector的元素为类结构的时候,他就会有很多临时变量产生.通过复制构造函数和析构函数,可

DirectUI的初步分析-转

DirectUI的初步分析(一) 最近由于项目的需要学习了一下DirectUI方面的东西,主要借鉴的是一个国外程序员写的代码(见引用一),看了后发现它更多的是探讨一种实现的可能性和思路,和实际应用还是有距离的,不过其实现还是很有意思的.在写此小结的时候又发现国内一个程序员将这个代码部分移植到WINCE下的代码(见引用二),因为平台的差异性要完全开发一个WINCE下的实际代码还是需要时间的. 由于本人GUI开发做得少,工作中有关这方面的东西主要是提供思路和方法,学习DirectUI的主要目的是为了

Irrlicht游戏引擎初步分析与研究

转载出处:http://blog.csdn.net/hellphenix/archive/2008/03/19/2198226.aspx Irrlicht游戏引擎主要是由一个名叫Nikolaus Gebhardt奥地利人所设计,是sourceforge上的一个开源项目,也是著名的开源游戏引擎.Irrlicht是一个德国神话故事中的一种动物的名字,它能够发光和飞翔,可以在大部分的沼泽地附近发现它.单词"Irrlicht"是两个德国单词("irr"意思是疯狂的:而&qu

OD常用断点之CC断点

在做Windows平台软件逆向时,Ollydbg是极其常用的逆向工具,动态调试功能非常强大.在调试过程中,断点的使用有助于确定关键的破解位置,今天讲解的内容是OD常用断点中的CC断点. CC断点有很多名称,比如普通断点.F2断点或者int3断点,每个名称都有它的来源.下面我们以crackme_01.exe为例子讲解一下如何设置CC断点以及其原理. 打开VM虚拟机,虚拟机中运行的操作系统为XP,接着使用OD载入crackme_01.exe.如下所示. 汇编窗口中展示的是crackme_01.exe

记一次内存溢出的分析经历——thrift带给我的痛orz

说在前面的话 朋友,你经历过部署好的服务突然内存溢出吗? 你经历过没有看过Java虚拟机,来解决内存溢出的痛苦吗? 你经历过一个BUG,百思不得其解,头发一根一根脱落的烦恼吗? 我知道,你有过! 但是我还是要来说说我的故事.................. 背景: 有一个项目做一个系统,分客户端和服务端,客户端用c++写的,用来收集信息然后传给服务端(客户端的数量还是比较多的,正常的有几千个), 服务端用Java写的(带管理页面),属于RPC模式,中间的通信框架使用的是thrift. thri

记一次内存溢出的分析经历

背景: 有一个项目做一个系统,分客户端和服务端,客户端用c++写的,用来收集信息然后传给服务端(客户端的数量还是比较多的,正常的有几千个), 服务端用Java写的(带管理页面),属于RPC模式,中间的通信框架使用的是thrift. thrift很多优点就不多说了,它是facebook的开源的rpc框架,主要是它能够跨语言,序列化速度快,但是他有个不讨喜的地方就是它必须用自己IDL来定义接口 thrift版本:0.9.2. 问题定位与分析 步骤一.初步分析 客户端无法连接服务端,查看服务器的端口开

06 内存断点

[太多事情要做了,这部分难度对我来说又很大,先写一下大体框架,到时候具体函数逆向分析过程给写出来] 问题: 1. 内存断点的实现思路是什么? 2. 操作系统检测的流程是什么? 3. 如何设置与恢复内存断点? 1. 内存断点的设置 内存断点分为两类:访问断点与写入断点. 其本质是调用 VirtualProtected 来修改页(PTE)属性. 1)访问断点,则将页的属性设置为 PAGE_NOACCESS. 2)写入断点,PAGE_EXECUTE_READ. 2. 内存断点的处理流程 3. 设置与恢