第49章 不正确的反汇编代码

在实际工程中,反编译工程师们经常会遇到一些不正确的反汇编代码。我们来看看如何处理。

49.1 x86环境下的从一开始错误的反汇编

与opcode等长的ARM以及MIPS指令集(它们每个指令的opcode无非就是2个字节或4个字节长)不同,x86构架下的指令长度不尽相同。因此,若从x86程序的中间开始解析指令,无论什么分析工具都会分析出错误的结果。

比如说:

add      [ebp-31F7Bh], cl
dec      dword ptr [ecx-3277Bh]
dec      dword ptr [ebp-2CF7Bh]
inc      dword ptr [ebx-7A76F33Ch]
fdiv     st(4), st
db 0FFh
dec      dword ptr [ecx-21F7Bh]
dec      dword ptr [ecx-22373h]
dec      dword ptr [ecx-2276Bh]
dec      dword ptr [ecx-22B63h]
dec      dword ptr [ecx-22F4Bh]
dec      dword ptr [ecx-23343h]
jmp      dword ptr [esi-74h]
xchg     eax, ebp
clc
std
db 0FFh
db 0FFh
mov      word ptr [ebp-214h], cs ; <- disassembler finally found right track here
mov      word ptr [ebp-238h], ds
mov      word ptr [ebp-23Ch], es
mov      word ptr [ebp-240h], fs
mov      word ptr [ebp-244h], gs
pushf
pop      dword ptr [ebp-210h]
mov      eax, [ebp+4]
mov      [ebp-218h], eax
lea      eax, [ebp+4]
mov      [ebp-20Ch], eax
mov      dword ptr [ebp-2D0h], 10001h
mov      eax, [eax-4]
mov      [ebp-21Ch], eax
mov      eax, [ebp+0Ch]
mov      [ebp-320h], eax
mov      eax, [ebp+10h]
mov      [ebp-31Ch], eax
mov      eax, [ebp+4]
mov      [ebp-314h], eax
call     ds:IsDebuggerPresent
mov      edi, eax
lea      eax, [ebp-328h]
push     eax
call     sub_407663
pop      ecx
test     eax, eax
jnz      short loc_402D7B

这里我们可以看到,解析出来的前几条指令毫无道理。但是后来反汇编工具逐渐走上了正轨。

49.2 随机噪音,怎么看起来像反汇编指令?

一般来说,我们可以从以下三点来判断,一段程序是由随机代码组成的还是正常的程序段:

指令清单49.1 x86模式下的随机数噪声

     mov    bl, 0Ch
     mov    ecx, 0D38558Dh
     mov    eax, ds:2C869A86h
     db     67h
     mov    dl, 0CCh
     insb
     movsb
     push   eax
     xor    [edx-53h], ah
     fcom   qword ptr [edi-45A0EF72h]
     pop    esp
     pop    ss
     in     eax, dx
     dec    ebx
     push   esp
     lds    esp, [esi-41h]
     retf
     rcl    dword ptr [eax], cl
     mov    cl, 9Ch
     mov    ch, 0DFh
     push   cs
     insb
     mov    esi, 0D9C65E4Dh
     imul   ebp, [ecx], 66h
     pushf
     sal    dword ptr [ebp-64h], cl
     sub    eax, 0AC433D64h
     out    8Ch, eax
     pop    ss
     sbb    [eax], ebx
     aas
     xchg   cl, [ebx+ebx*4+14B31Eh]
     jecxz  short near ptr loc_58+1
     xor    al, 0C6h
     inc    edx
     db     36h
     pusha
     stosb
     test   [ebx], ebx
     sub    al, 0D3h ; 'L'
     pop    eax
     stosb

loc_58: ; CODE XREF: seg000:0000004A
     test   [esi], eax
     inc    ebp
     das
     db     64h
     pop    ecx
     das
     hlt

     pop    edx
     out    0B0h, al
     lodsb
     push   ebx
     cdq
     out    dx, al
     sub    al, 0Ah
     sti
     outsd
     add    dword ptr [edx], 96FCBE4Bh
     and    eax, 0E537EE4Fh
     inc    esp
     stosd
     cdq
     push   ecx
     in     al, 0CBh
     mov    ds:0D114C45Ch, al
     mov    esi, 659D1985h

指令清单49.2 x86-64下的随机数噪声

     lea    esi, [rax+rdx*4+43558D29h]

loc_AF3: ; CODE XREF: seg000:0000000000000B46
     rcl    byte ptr [rsi+rax*8+29BB423Ah], 1
     lea    ecx, cs:0FFFFFFFFB2A6780Fh
     mov    al, 96h
     mov    ah, 0CEh
     push   rsp
     lods   byte ptr [esi]

     db 2Fh ; /

     pop    rsp
     db     64h
     retf   0E993h

     cmp    ah, [rax+4Ah]
     movzx  rsi, dword ptr [rbp-25h]
     push   4Ah
     movzx  rdi, dword ptr [rdi+rdx*8]

     db 9Ah

     rcr    byte ptr [rax+1Dh], cl
     lodsd
     xor    [rbp+6CF20173h], edx
     xor    [rbp+66F8B593h], edx
     push   rbx
     sbb    ch, [rbx-0Fh]
     stosd
     int    87h
     db     46h, 4Ch
     out    33h, rax
     xchg   eax, ebp
     test   ecx, ebp
     movsd
     leave
     push   rsp

     db 16h

     xchg   eax, esi
     pop    rdi

loc_B3D: ; CODE XREF: seg000:0000000000000B5F
     mov    ds:93CA685DF98A90F9h, eax
     jnz    short near ptr loc_AF3+6
     out    dx, eax
     cwde
     mov    bh, 5Dh ; ']'
     movsb
     pop    rbp

指令清单49.3 ARM模式下的随机数噪声

BLNE     0xFE16A9D8
BGE      0x1634D0C
SVCCS    0x450685
STRNVT   R5, [PC],#-0x964
LDCGE    p6, c14, [R0],#0x168
STCCSL   p9, c9, [LR],#0x14C
CMNHIP   PC, R10,LSL#22
FLDMIADNV LR!, {D4}
MCR      p5, 2, R2,c15,c6, 4
BLGE     0x1139558
BLGT     0xFF9146E4
STRNEB   R5, [R4],#0xCA2
STMNEIB  R5, {R0,R4,R6,R7,R9-SP,PC}
STMIA    R8, {R0,R2-R4,R7,R8,R10,SP,LR}^
STRB     SP, [R8],PC,ROR#18
LDCCS    p9, c13, [R6,#0x1BC]
LDRGE    R8, [R9,#0x66E]
STRNEB   R5, [R8],#-0x8C3
STCCSL   p15, c9, [R7,#-0x84]
RSBLS    LR, R2, R11,ASR LR
SVCGT    0x9B0362
SVCGT    0xA73173
STMNEDB  R11!, {R0,R1,R4-R6,R8,R10,R11,SP}
STR      R0, [R3],#-0xCE4
LDCGT    p15, c8, [R1,#0x2CC]
LDRCCB   R1, [R11],-R7,ROR#30
BLLT     0xFED9D58C
BL       0x13E60F4
LDMVSIB  R3!, {R1,R4-R7}^
USATNE   R10, #7, SP,LSL#11
LDRGEB   LR, [R1],#0xE56
STRPLT   R9, [LR],#0x567
LDRLT    R11, [R1],#-0x29B
SVCNV    0x12DB29
MVNNVS   R5, SP,LSL#25
LDCL     p8, c14, [R12,#-0x288]
STCNEL   p2, c6, [R6,#-0xBC]!
SVCNV    0x2E5A2F
BLX      0x1A8C97E
TEQGE    R3, #0x1100000
STMLSIA  R6, {R3,R6,R10,R11,SP}
BICPLS   R12, R2, #0x5800
BNE      0x7CC408
TEQGE    R2, R4,LSL#20
SUBS     R1, R11, #0x28C
BICVS    R3, R12, R7,ASR R0
LDRMI    R7, [LR],R3,LSL#21
BLMI     0x1A79234
STMVCDB  R6, {R0-R3,R6,R7,R10,R11}
EORMI    R12, R6, #0xC5
MCRRCS   p1, 0xF, R1,R3,c2

指令清单49.4 ARM的Thumb模式下的随机数噪声

     LSRS   R3, R6, #0x12
     LDRH   R1, [R7,#0x2C]
     SUBS   R0, #0x55 ; 'U'
     ADR    R1, loc_3C
     LDR    R2, [SP,#0x218]
     CMP    R4, #0x86
     SXTB   R7, R4
     LDR    R4, [R1,#0x4C]
     STR    R4, [R4,R2]
     STR    R0, [R6,#0x20]
     BGT    0xFFFFFF72
     LDRH   R7, [R2,#0x34]
     LDRSH  R0, [R2,R4]
     LDRB   R2, [R7,R2]

     DCB 0x17
     DCB 0xED

     STRB   R3, [R1,R1]
     STR    R5, [R0,#0x6C]
     LDMIA  R3, {R0-R5,R7}
     ASRS   R3, R2, #3
     LDR    R4, [SP,#0x2C4]
     SVC    0xB5
     LDR    R6, [R1,#0x40]
     LDR    R5, =0xB2C5CA32
     STMIA  R6, {R1-R4,R6}
     LDR    R1, [R3,#0x3C]
     STR    R1, [R5,#0x60]
     BCC    0xFFFFFF70
     LDR    R4, [SP,#0x1D4]
     STR    R5, [R5,#0x40]
     ORRS   R5, R7

loc_3C ; DATA XREF: ROM:00000006
     B      0xFFFFFF98

指令清单49.5 MIPS(小端)下的随机数噪声

     lw     $t9, 0xCB3($t5)
     sb     $t5, 0x3855($t0)
     sltiu  $a2, $a0, -0x657A
     ldr    $t4, -0x4D99($a2)
     daddi  $s0, $s1, 0x50A4
     lw     $s7, -0x2353($s4)
     bgtzl  $a1, 0x17C5C

     .byte 0x17
     .byte 0xED
     .byte 0x4B # K
     .byte 0x54 # T

     lwc2   $31, 0x66C5($sp)
     lwu    $s1, 0x10D3($a1)
     ldr    $t6, -0x204B($zero)
     lwc1   $f30, 0x4DBE($s2)
     daddiu $t1, $s1, 0x6BD9
     lwu    $s5, -0x2C64($v1)
     cop0   0x13D642D
     bne    $gp, $t4, 0xFFFF9EF0
     lh     $ra, 0x1819($s1)
     sdl    $fp, -0x6474($t8)
     jal    0x78C0050
     ori    $v0, $s2, 0xC634
     blez   $gp, 0xFFFEA9D4
     swl    $t8, -0x2CD4($s2)
     sltiu  $a1, $k0, 0x685
     sdc1   $f15, 0x5964($at)
     sw     $s0, -0x19A6($a1)
     sltiu  $t6, $a3, -0x66AD
     lb     $t7, -0x4F6($t3)
     sd     $fp, 0x4B02($a1)

我们必须注意的一点是:一些编写良好的解压包或者加密程序代码(也包括一些变形代码),从代码来看也很像是随机数指令序列,然而一旦运行起来则是非常正确的。