可疑的代码模式

61.1 XOR 指令

像XOR op这样的指令,op为寄存器(比如,xor eax,eax)通常用于将寄存器的值设置为零,但如果操作数不同,“互斥或”运算将被执行。在普通的程序中这种操作较罕见,但在密码学中应用较广,包括业余的。如果第二个操作数是一个很大的数字,那么就更可疑了。可能会指向加密/解密操作或校验和的计算等等。

而这种观察也可能是无意义的,比如“canary”(18.3节)。canary的产生和检测通常使用XOR指令。

下面这个awk脚本可用于处理IDA的.list文件:

  1. gawk -e '$2=="xor" { tmp=substr($3, 0, length($3)-1); if (tmp!=$4) if($4!="esp") if ($4!="ebp")⤦􏰀 {print$1,$2,tmp,",",$4}}'filename.lst

61.2 Hand-written assembly code

现代编译器不会emit LOOP和RCL指令。另一方面,这些指令对于直接用汇编语言编程的程序员来说很熟悉。如果你发现了这些指令,可以猜测这部分代码极有可能是手工编写的。这样的代码在这个指令列表中用(M)标记:A.6节。

同时函数prologue/epilogue通常不会以手工编写的汇编的形式呈现。

通常情况下,手工编写的代码中参数传递给函数没有固定的系统。

Windows 2003 内核(ntoskrnl.exe 文件)的例子:

  1. MultiplyTest proc near ; CODE XREF: Get386Stepping
  2. xor cx, cx
  3. loc_620555: ; CODE XREF: MultiplyTest+E
  4. push cx
  5. call Multiply
  6. pop cx
  7. jb short locret_620563
  8. loop loc_620555
  9. clc
  10. locret_620563: ; CODE XREF:MultiplyTest+C
  11. retn
  12. MultiplyTest endp
  13. Multiply proc near ;CODE XREF:MultiplyTest+5
  14. mov ecx,81h
  15. mov eax,417A000h
  16. mul ecx
  17. cmp edx,2
  18. stc
  19. jnz short locret_62057F
  20. cmp eax,0FE7A000h
  21. stc
  22. jnz short locret_62057F
  23. clc
  24. locret_62057F: ; CODE XREF:Multiply+10
  25. ; Multiply+18
  26. retn
  27. Multiply endp

事实上,如果我们查看WRK v1.2源码,上面的代码在WRK-v1.2386.asm文件中很容易找到。 #第62章

跟踪时使用幻数

通常情况下,我们的主要目标是理解程序从文件读取或从网络中接收的值的用途。手动跟踪某个值常常是个体力活。最简单应对技术之一(尽管不是百分之百靠谱)是使用自定义的幻数。

这在某种程度上类似于X射线计算机断层扫描:造影剂注射到病人的血液中,增强患者的内部结构在X射线下的能见度。例如,健康人的血液在肾脏渗透是众所周知的,如果血液中有介质则可以很容易在断层中看到血液如何渗透的,是否有结石或肿瘤。

我们可以使用一个32比特的数字,比如0x0badf00d,或者某人的生日0x11101979并将这个4字节数字写到我们目标程序使用的文件的某个位置。

然后使用code coverage模式下的tracer的跟踪这个程序,再用grep工具或仅仅是文本搜索(跟踪结果),就可以轻松看到值的位置以及如何被使用。

使用cc模式下tracer的结果,可使用grep:

  1. 0x150bf66 (_kziaia+0x14), e= 1 [MOV EBX, [EBP+8]] [EBP+8]=0xf59c934
  2. 0x150bf69 (_kziaia+0x17), e= 1 [MOV EDX, [69AEB08h]] [69AEB08h]=0
  3. 0x150bf6f (_kziaia+0x1d), e= 1 [FS: MOV EAX, [2Ch]]
  4. 0x150bf75 (_kziaia+0x23), e= 1 [MOV ECX, [EAX+EDX*4]] [EAX+EDX*4]=0xf1ac360
  5. 0x150bf78 (_kziaia+0x26), e= 1 [MOV [EBP-4], ECX] ECX=0xf1ac360

对于网络包中也同样适用。很重要的一点是,幻数必须独特保证没有在该程序中出现过。

除了tracer,heavydebug模式下的DosBox(MS-DOS仿真器)也能将每条指令执行后寄存器状态写入到一个文本文件中,因此,这种技术对于DOS程序也是很有用的。