第61章
可疑的代码模式
61.1 XOR 指令
像XOR op这样的指令,op为寄存器(比如,xor eax,eax)通常用于将寄存器的值设置为零,但如果操作数不同,“互斥或”运算将被执行。在普通的程序中这种操作较罕见,但在密码学中应用较广,包括业余的。如果第二个操作数是一个很大的数字,那么就更可疑了。可能会指向加密/解密操作或校验和的计算等等。
而这种观察也可能是无意义的,比如“canary”(18.3节)。canary的产生和检测通常使用XOR指令。
下面这个awk脚本可用于处理IDA的.list文件:
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 文件)的例子:
MultiplyTest proc near ; CODE XREF: Get386Stepping
xor cx, cx
loc_620555: ; CODE XREF: MultiplyTest+E
push cx
call Multiply
pop cx
jb short locret_620563
loop loc_620555
clc
locret_620563: ; CODE XREF:MultiplyTest+C
retn
MultiplyTest endp
Multiply proc near ;CODE XREF:MultiplyTest+5
mov ecx,81h
mov eax,417A000h
mul ecx
cmp edx,2
stc
jnz short locret_62057F
cmp eax,0FE7A000h
stc
jnz short locret_62057F
clc
locret_62057F: ; CODE XREF:Multiply+10
; Multiply+18
retn
Multiply endp
事实上,如果我们查看WRK v1.2源码,上面的代码在WRK-v1.2386.asm文件中很容易找到。 #第62章
跟踪时使用幻数
通常情况下,我们的主要目标是理解程序从文件读取或从网络中接收的值的用途。手动跟踪某个值常常是个体力活。最简单应对技术之一(尽管不是百分之百靠谱)是使用自定义的幻数。
这在某种程度上类似于X射线计算机断层扫描:造影剂注射到病人的血液中,增强患者的内部结构在X射线下的能见度。例如,健康人的血液在肾脏渗透是众所周知的,如果血液中有介质则可以很容易在断层中看到血液如何渗透的,是否有结石或肿瘤。
我们可以使用一个32比特的数字,比如0x0badf00d,或者某人的生日0x11101979并将这个4字节数字写到我们目标程序使用的文件的某个位置。
然后使用code coverage模式下的tracer的跟踪这个程序,再用grep工具或仅仅是文本搜索(跟踪结果),就可以轻松看到值的位置以及如何被使用。
使用cc模式下tracer的结果,可使用grep:
0x150bf66 (_kziaia+0x14), e= 1 [MOV EBX, [EBP+8]] [EBP+8]=0xf59c934
0x150bf69 (_kziaia+0x17), e= 1 [MOV EDX, [69AEB08h]] [69AEB08h]=0
0x150bf6f (_kziaia+0x1d), e= 1 [FS: MOV EAX, [2Ch]]
0x150bf75 (_kziaia+0x23), e= 1 [MOV ECX, [EAX+EDX*4]] [EAX+EDX*4]=0xf1ac360
0x150bf78 (_kziaia+0x26), e= 1 [MOV [EBP-4], ECX] ECX=0xf1ac360
对于网络包中也同样适用。很重要的一点是,幻数必须独特保证没有在该程序中出现过。
除了tracer,heavydebug模式下的DosBox(MS-DOS仿真器)也能将每条指令执行后寄存器状态写入到一个文本文件中,因此,这种技术对于DOS程序也是很有用的。