讨论ollydbg调试程序cpu应用率高达100%的问题
今天终于将ollydgb加载应用程序,运行时cpu应用率高达100%的问题解决了

在跟踪ollydbg加载程序,发现
00439616                         6A 00     push 0-->  这里等待时间居然为0 
上次我分析,kermaker里面的内存注册机时,这里的参数为-1,
当然了,有可以作者是特意将这里设为0的,
但看看下面
00439618                      .  68 14574D>push Ollydbg.004D5714                       ; |pDebugEvent = Ollydbg.004D5714
0043961D                      .  E8 E85B07>call <jmp.&KERNEL32.WaitForDebugEvent>      ; \WaitForDebugEvent
00439622                      .  85C0      test eax,eax
00439624                      .  75 44     jnz short Ollydbg.0043966A
00439626                      .  833D 543B>cmp dword ptr ds:[4E3B54],0
0043962D                      .  74 27     je short Ollydbg.00439656
0043962F                      .  8B0D 583B>mov ecx,dword ptr ds:[4E3B58]
00439635                      .  83C1 64   add ecx,64
00439638                      .  3B4D CC   cmp ecx,dword ptr ss:[ebp-34]
0043963B                      .  73 19     jnb short Ollydbg.00439656
0043963D                      .  6A 00     push 0                                      ; /lParam = 0
0043963F                      .  6A 00     push 0                                      ; |wParam = 0
00439641                      .  6A 00     push 0                                      ; |Message = WM_NULL
00439643                      .  A1 5C3B4E>mov eax,dword ptr ds:[4E3B5C]               ; |
00439648                      .  50        push eax                                    ; |ThreadId => 0
00439649                      .  E8 F25E07>call <jmp.&USER32.PostThreadMessageA>       ; \PostThreadMessageA
0043964E                      .  33D2      xor edx,edx
00439650                      .  8915 543B>mov dword ptr ds:[4E3B54],edx
00439656                      >  6A 00     push 0                                      ; /Arg1 = 00000000
00439658                      .  E8 EFD405>call Ollydbg.00496B4C                       ; \Ollydbg.00496B4C
0043965D                      .  59        pop ecx

在这里居然出现了一个Sleep(0); 加了这条语句不等于没加么? 并且在被调试的程序运行时,不断的在这里断下,
所在我就将这里的0改为了0x10ms ,如果你们决得这等得太久了也可以改为1ms..

0043965E                      .  6A 00     push 0                 ; /Timeout = 0. ms----> 把这个地方改为10,也让cpu休息一下吧!
00439660                      .  E8 575B07>call <jmp.&KERNEL32.Sleep>                  ; \Sleep

文件地址为: 38C5E 
就改这一个地方问题就解决了..
再回想一下,以前用softICE跟trw2000,在win98下面调试程序时程序在中断时,
处理器的应用率就到了100%,当然了我们调试程序,大部分时间都是中断,
我的是笔记本电脑(p4 2.4G),调试程序调半个小的话,整个电脑简直成了火炉,
风扇吹个不停还是没用,特别是夏天,更是利害,后来用了ollydbg,程序在中断的时候
不会出现处理器应用率为100%的现象.尽管程序在运行时处理器应用率为100%还过得去
一直用到现在..相信大家都用过ida跟vc自带的调试工具吧!在调试程序时,
处理器是从不会出现应用率达到100%的..

------->下面介是一个简单的调试器,可做内存注册机,只适用于未加壳的程序
#define BREAKPOINT 0x4086cb

int Init()
{
  HANDLE hThread; 
  HwndMain = hwnd;
  DWORD dwThreadId, dwThrdParam = 1; 
        //建立线程调试程序
  hThread=CreateThread(NULL,NULL,ThreadFunc,&dwThrdParam,0,&dwThreadId);
  return 0;
}
int ReadMemory(HANDLE hProcess,BYTE *memory)
{
  BYTE p=0xcc;
  //这里保存原来的代码
  ReadProcessMemory(hProcess,(LPVOID)BREAKPOINT,memory,1,NULL);
  //写入int 3 中断
  WriteProcessMemory(hProcess,(LPVOID)BREAKPOINT,&p,1,NULL);
  return 0;
}
DWORD WINAPI ThreadFunc(LPVOID)
{
  STARTUPINFO Info;
  PROCESS_INFORMATION ProInfo;
  DEBUG_EVENT DebugEvent;
  DWORD Status;
  static DWORD IsWrite=0;
  CONTEXT content;
  LPVOID stat;
  content.ContextFlags= 0x10007;
  ZeroMemory(&Info,sizeof(STARTUPINFO));
  ZeroMemory(&ProInfo,sizeof(ProInfo));
  ZeroMemory(&DebugEvent,sizeof(DEBUG_EVENT));
  GetStartupInfo(&Info);
  BYTE MemoryFromProcess;
        //建立调试进程
  CreateProcess(NULL,"test.exe",NULL,NULL,NULL,DEBUG_ONLY_THIS_PROCESS,NULL,NULL,&Info,&ProInfo);
  do
  {
    WaitForDebugEvent(&DebugEvent,-1);
    switch(DebugEvent.dwDebugEventCode)
    {
    case 1:
      if(DebugEvent.u.Exception.ExceptionRecord.ExceptionAddress==(LPVOID)BREAKPOINT && IsWrite==1)
      {
        GetThreadContext(ProInfo.hThread,&content);
        content.Eip--;
        SetThreadContext(ProInfo.hThread,&content);
        //还原原来的代码,eip减1再执行..
        WriteProcessMemory(ProInfo.hProcess,(LPVOID)BREAKPOINT,&MemoryFromProcess,1,NULL);
        //在这里我们就可以读取内存里面的注册码了,
        //当然了,我们还可以进行一些运算,算出注册码来,在这里用对话框显示..
        IsWrite++;
      }
      Status = DBG_CONTINUE;
      break;
    case 6:
      if(IsWrite==0)
      {
        ReadMemory(ProInfo.hProcess,&MemoryFromProcess);
        IsWrite++;
        Status =DBG_EXCEPTION_NOT_HANDLED;
      }
      break;
    default:
      Status =DBG_EXCEPTION_NOT_HANDLED;
    }
    ContinueDebugEvent(DebugEvent.dwProcessId,DebugEvent.dwThreadId,Status);
  }while(DebugEvent.dwDebugEventCode!=5);
  ExitThread(0);
  return 0;
}

  • 标 题: 答复
  • 作 者:FlyToTheSpace
  • 时 间:2006-03-26 14:37

刷新事件总会有等待时间的吧!,
不会一直刷下去吧!消息有那么多么..
  while (GetMessage (&msg, NULL, 0, 0))
  {
    TranslateMessage (&msg) ;
    DispatchMessage (&msg) ;
  }
在这个消息处理里面也是有等待时间的..

  • 标 题: 答复
  • 作 者:stupidass
  • 时 间:2006-03-28 14:59

CPU占用率应该和DEBUG事件的响应速度是一对矛盾吧。使用dbghelp.dll的调试API的调试器一般都有一个while(1)的主循环。里面不断对调试事件进行响应。WaitForDebugEvent等待调试时间发生,sleep用来交出CPU的使用权。如果把延时参数改大,对DEBUG事件的响应肯定有影响(特别是更改那个sleep的参数。)。对普通int3断点可能还好说点,毕竟有SEH在那里挡住了。但是对于硬件断点呢?万一你睡的时间太长了,在两次WaitForDebugEvent之间已经有了DR0-DR3的对应地址的调试事件产生了怎么办?

  • 标 题: 答复
  • 作 者:stupidass
  • 时 间:2006-03-28 15:01

再说了sleep(0)并不等同于没有。只要调用了sleep函数,就有同步信号量被释放,CPU控制权就会有个交接过程,虽然时间参数是0ms,但是并不意味着在sleep语句执行之前的CPU时刻=sleep执行之后的CPU时刻.