击败 QueryPerformanceCounter 作为反调试技巧

逆向工程 部件 反调试
2021-06-22 10:22:57

我尝试分析的示例从 PUSHAD 开始。它始于:

   PUSHAD
   MOV ESI, unbr002.0109D000
   LEA EDI, DWORD PTR DS:[ESI+FFEA4000]
   MOV DWORD PTR DS: [EDI+208C04], 8C1FE
   PUSH EDI
   OR EBP, FFFFFFFF
   JMP SHORT unbr002.0117C2EA
   NOP
   NOP
   ....

我做了什么:首先,我尝试了 ESP 技巧(跳过 PUSHAD,双击 ESP -> Follow in Dump 等),但它不起作用。然后,我搜索 PUSHAD 的对应项,即 POPAD 指令并在其上放置一个断点。之后,我点击 F9 运行程序,直到命中 BP。然后我看到了这个:

  POPAD
  LEA EAX, DWORD PTR DS:[ESP-80]
  PUSH 0
  CMP ESP, EAX
  JNZ SHORT unbr002.0117C4BC        a)
  SUB ESP, -80
  JMP unbr002.01048A05              b) 
  JMP SHORT unbr002.0117C4CC
  PUSH ESI
  MOV ESI, unbr002.010961A4
  CLD
  LODS DWORD PTR DS:[ESI]
  TEST EAX, EAX
  JE SHORT unbr002.0117C4E5
  PUSH 3
  POP ECX
  PUSH DWORD PTR SS:[ESP+10]
  LOOPD SHORT unbr002.0117C4D3
  POP ESI
  RETN 0C
  DB 00
  DB 00
  .....
  .....

所以,我知道在 POPAD 之后,所谓的尾跳将把我带到 OEP。当我去 a) 什么都没有发生时,我的意思是没有进行跳转。

当我去B),(我并没有跨过/进入,只点击Enter键),则跳转到以下地方:

 CALL unbr002.01055C47

在这里,我还查看了 01055C47 处的函数,它看起来像这样(因为函数太大,我只会键入其中的相关部分):

 .....
 CALL DWORD PTR DS:[109407C]       kernel32.GetSystemTimeAsFileTime
 MOV ESI, DWORD PTR SS:[EBP-4]
 XOR ESI, DWORD PTR SS:[EBP-8]
 CALL DWORD PTR DS:[10940F4]       kernel32.GetCurrentProcessId
 XOR ESI, EAX
 CALL DWORD PTR DS:[10940E0]       kernel32.GetCurrentThreadId
 XOR ESI, EAX 
 CALL DWORD PTR DS:[10942BC]       kernel32.GetTickCount
 XOR ESI, EAX
 LEA EAX, DWORD PTR SS:[EBP-10]
 PUSH EAX
 CALL DWORD PTR DS:[109442C0]      kernel32.QueryPerformanceCounter
 ...
 ...
 ...

所以,从其他来源我读到 GetTickCount 等上面的这些函数是反调试技巧。但是我找不到打败他们的方法。所以,再看看 b)。现在,当我在 b) 处跳过 JMP 指令时,该过程将终止。

我的问题:我必须怎么做才能解决这个问题?

PS: a) 我有 ollydbg 插件 OllyAdvanced,我在 ollyAdvanced 中勾选了 TerminateProcess 框,但没有成功。b) 我也知道它装有 UPX,但我试图让我自己的学习过程更难一点,因此我尝试手动打开它

最好的祝福,

1个回答
 .....
 CALL DWORD PTR DS:[109407C]       kernel32.GetSystemTimeAsFileTime
 MOV ESI, DWORD PTR SS:[EBP-4]
 XOR ESI, DWORD PTR SS:[EBP-8]
 CALL DWORD PTR DS:[10940F4]       kernel32.GetCurrentProcessId
 XOR ESI, EAX
 CALL DWORD PTR DS:[10940E0]       kernel32.GetCurrentThreadId
 XOR ESI, EAX 
 CALL DWORD PTR DS:[10942BC]       kernel32.GetTickCount
 XOR ESI, EAX
 LEA EAX, DWORD PTR SS:[EBP-10]
 PUSH EAX
 CALL DWORD PTR DS:[109442C0]      kernel32.QueryPerformanceCounter
 ...

所以,从其他来源我读到 GetTickCount 等上面的这些函数是反调试技巧。

上面的代码不是用作反调试技巧,而是用于计算安全 cookie(也称为金丝雀)

有关上述代码的反编译,请参阅https://books.google.com/books?id=aidqstv38G8C&pg=PA167有关在 Microsoft 的 Visual C++ 编译器中实现的安全 cookie 的更多信息,请参阅编译器安全检查深度