主题:Od中F2断点深入解析
语言:C,内联asm
平台:win32
工具:vc6.0  od  计算器
哈哈,自我申明,没有什么高深的技术,只是想逼自己做什么都需要动手,高手请过。。(纸上谈来终觉浅,绝知此事要躬行)。。
首先我们知道,在od中下 F2(或vc中F9)断点通常是在运行前编译器,将断点的位置写入int 3(机器码即0xcc),.当被调试的进程执行int3 指令时导致一个异常时,调试器会捕捉这个异常从而停在断点处,然后将断点处的指令恢复原来的指令。就是这样么?我们接下来具体操作操作,由于实际在od中下断处,我们观察内存根本看不见有cc出现(对像我这样的新手来说,其实通过其他方法是可以看到的),让我用小code来证明一下:两个问题
1.是否0xcc被插入。。
2.插入后是否一直恢复了原指令?答案:不是,它还有一个执行完后,继续写回的操作。

证1:code
#include "windows.h"
void Sample()
{  
  int sum=0;
  sum+=2;
  MessageBox(NULL,"SampleSelf!","Sample",MB_OK);
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)

  byte *PointA;
  PointA=(byte *)Sample;    //Sample处下断
  if (*PointA==0xcc)      //检测
    MessageBoxA(0,"CC exist!","Debugger",0);
  Sample();  
  if (*PointA==0xcc)
    MessageBoxA(0,"CC exist!","Debugger",0);


代码很简单,呵呵。。。我们来看看载入od的结果





1证明成立确实是int 3 插入,这个来论坛没人不知道呵呵。。。

第二条证明,可能有很多像我这样的新手会认为F2断点的原理早已掌握,其实不然。。我可能是个特殊。。

证2代码:
#include<windows.h>
#include<stdio.h>
DWORD  Calculation(DWORD StartAddr,DWORD dwCodeLength)
{
  _asm
  {
      xor eax,eax
      xor ebx,ebx
      mov esi,StartAddr
      mov ecx,dwCodeLength
Label1:
      mov bl,byte ptr [esi]
      add eax,ebx
      inc esi
      loop Label1      
  }
  
}


DWORD CheckSelf(DWORD StartAddr,DWORD dwCodeLength)
{
  _asm
  {
      xor eax,eax
      xor ebx,ebx
      mov esi,StartAddr
      mov ecx,dwCodeLength
Label1:
      mov bl,byte ptr [esi]
      add eax,ebx  
      inc esi
      loop Label1
      sub eax, 3763//3763是由dwSumbyte提前提供
  }
}


int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)

{
  DWORD dwStartAddr=0;
  DWORD dwEndAddr=0;
  DWORD dwCodeLength=0;
  DWORD dwChecksum=0;
  DWORD dwSumbyte=0;
  DWORD dwOdd=0;
  char  temp[200]={0};
  _asm
  {
Start:
    xor eax,eax
    xor ebx,ebx
    xor ecx,ecx
    xor edx,edx
    add ebx,ecx
    add edx,ebx
    add ebx,eax
    add eax,ebx
    mov dwStartAddr,offset Start
    mov dwEndAddr,offset End  
End:
  }

dwCodeLength=dwEndAddr-dwStartAddr;
dwSumbyte=Calculation(dwStartAddr,dwCodeLength);
dwOdd = CheckSelf(dwStartAddr,dwCodeLength);
wsprintf(temp,"the Deviation is %d",dwOdd);
MessageBox(NULL,temp,"OK",MB_OK);                   //显示差值,od是否作用过。。。
}

代码也很简单,了解代码校验的估计都会。。所以也不多说。。
我测试的断点是 Start和End标签直接。。。
好我们来看结果:
1.不下断点:

结果正常!

2.下断点:




------1,下在此处:


为什么是这个值呢?
答:应该是0xcc,代替了图中的0x33,算算就知道 0xcc-0x33=153 正确

------2.那你来猜猜第二次应该是多少呢?
0xcc+0xcc-0x33-0x03应该等于354.。。


哈哈都对了。。。
确实是机器码cc起了作用。。
但==,看看我的代码2,发现了什么异常吗?不是说过它执行完了就回把源代码还原吗,
我的Start和End 之间的代码可在计算函数之前执行的哦!!为什么它还会存在int 3(0xcc),
我想,它在之后又还是将int 3 写入进程text一次,只要不结束,它就存在,是这样吗,实际确实是这样滴!(想想我们在断F2时,如果你不清除,断点是始终存在的,恩就是这个道理!)

我来实际操作看看,还是执行code1,Sample处下F2断点:
操作结果是:依次显示3副图