MASM的反反汇编技术

reference:http://www.aogosoft.com/downpage.asp?mode=viewtext&id=54

由于汇编语言是与机器语言机器码一一对应的,所以程序的代码非常简洁,编译、链接程序不会在其中加入任何其它代码,所以,用Win32DASM等把汇编工具反汇编汇编语言写的程序,其列出的汇编代码几乎与编写的顺序、过程、代码一模一样,这也是汇编语言简洁的证据。
但是这种过于简洁的代码却给了破解者提供了方便,破解者只需要有一定的Windows SDK编程与汇编的经验,破解就非常简单,根本不需要用SoftICE这些动态工具就可以破解。于是,相应的防止跟踪的技术就出来了,比如花指令、不按规则调用API等等,今天就花指令和大家研究研究。
花指令,其实就是在程序中加入一些字节来干扰静态工具反汇编,毕竟汇编工具没有人的思维,所以这招非常好骗。

我在RadAsm中写入以下代码:

    .386
    .Model Flat, StdCall
    Option Casemap :None
;_____________________________________________________________

    Include windows.inc
    Include user32.inc
    Include kernel32.inc

    IncludeLib user32.lib
    IncludeLib kernel32.lib
;_____________________________________________________________

    .data
    Welcome db "欢迎来到汇编的世界",0
;_____________________________________________________________

    .CODE
START:
    invoke MessageBox,0,offset Welcome,0,0
    invoke ExitProcess,0
    END START

对应的反汇编程序:

00401000 >/$  6A 00         push    0                                ; /(initial cpu selection)
00401002  |.  6A 00         push    0                                ; |Title = NULL
00401004  |.  68 00304000   push    00403000                         ; |欢迎来到汇编的世界
00401009  |.  6A 00         push    0                                ; |hOwner = NULL
0040100B  |.  E8 08000000   call    <jmp.&user32.MessageBoxA>        ; \MessageBoxA
00401010  |.  6A 00         push    0                                ; /ExitCode = 0
00401012  \.  E8 07000000   call    <jmp.&kernel32.ExitProcess>      ; \ExitProcess
00401017      CC            int3
00401018   $- FF25 08204000 jmp     dword ptr [<&user32.MessageBoxA>>;  user32.MessageBoxA
0040101E   .- FF25 00204000 jmp     dword ptr [<&kernel32.ExitProces>;  kernel32.ExitProcess

修改code段代码为:

    .CODE
START:
    lea eax,Welcome
    invoke MessageBox,0,eax,0,0
    invoke ExitProcess,0
    END START

也就是说,我们并没有使用花指令,而是在使用字符串时先把字符串的地址传给eax,然后再把eax做为参数传给MessageBox,这样做,Win23DASM这些反汇编工具就无法识别了,好,用Win32DASM重新打开编译的文件,在[参考]菜单中,[字符串]这一项灰色显示,提示这个程序没有字符串,骗过它了!^_^

反汇编变成了这样:

00401000 >/$  8D05 00304000 lea     eax, dword ptr [403000]          ; /(initial cpu selection)
00401006  |?  6A 00         push    0
00401008  |?  6A 00         push    0
0040100A  |?  50            push    eax
0040100B  |.  6A 00         push    0                                ; \MessageBoxA
0040100D  |?  E8 08000000   call    <jmp.&user32.MessageBoxA>
00401012  \.  6A 00         push    0                                ; \ExitProcess
00401014   ?  E8 07000000   call    <jmp.&kernel32.ExitProcess>
00401019   ?  CC            int3
0040101A   ?- FF25 08204000 jmp     dword ptr [<&user32.MessageBoxA>>;  user32.MessageBoxA
00401020   ?- FF25 00204000 jmp     dword ptr [<&kernel32.ExitProces>;  kernel32.ExitProcess

还有就是使用花指令,花指令不但可以使反汇编工具无法识别出字符串,更会让它们把汇编出错误的代码,花指令一般都是使用一些无用的字节来进行干扰,但是干扰反汇编的字节仍是可以使用的,像这样子:

    .data
    
    Welcome db "你是不是在搞笑哦!",0
;_____________________________________________________________

    .CODE
START:
    jz @F
    jnz @F
    www db "欢迎来到汇编世界",0
  @@:
    lea eax,www
    lea ebx,Welcome
    invoke MessageBox,0,eax,ebx,0
    invoke ExitProcess,0
    END START

反汇编后:

00401000 > $ /74 13         je      short 00401015
00401002   . |75 11         jnz     short 00401015
00401004   . |BB B6D3ADC0   mov     ebx, C0ADD3B6
00401009   . |B4 B5         mov     ah, 0B5
0040100B   . |BD BBE3B1E0   mov     ebp, E0B1E3BB
00401010   . |CA C0BD       retf    0BDC0
00401013   . |E7 00         out     0, eax
00401015   > \8D05 04104000 lea     eax, dword ptr [401004]
0040101B   .  8D1D 00304000 lea     ebx, dword ptr [403000]
00401021   .  6A 00         push    0                                ; /Style = MB_OK|MB_APPLMODAL
00401023   .  53            push    ebx                              ; |Title => "你是",B2,"",BB,"是在",B8,"阈",A6,"?,B6,"?,A1,""
00401024   .  50            push    eax                              ; |Text => ""BB,"",B6,"?,AD,"?,B4,"?,BD,"",BB,"惚嗍?,BD,"?
00401025   .  6A 00         push    0                                ; |hOwner = NULL
00401027   .  E8 08000000   call    <jmp.&user32.MessageBoxA>        ; \MessageBoxA
0040102C   .  6A 00         push    0                                ; /ExitCode = 0
0040102E   .  E8 07000000   call    <jmp.&kernel32.ExitProcess>      ; \ExitProcess
00401033      CC            int3
00401034   $- FF25 08204000 jmp     dword ptr [<&user32.MessageBoxA>>;  user32.MessageBoxA
0040103A   .- FF25 00204000 jmp     dword ptr [<&kernel32.ExitProces>;  kernel32.ExitProcess

感觉还是有些明显,我们手动调用API来试试。

 

    .data
    
    Welcome db "你是不是在搞笑哦!",0
;_____________________________________________________________

    .CODE
START:
    lea eax,Welcome
    push 0
    push 0
    push eax
    push 0
    jz @F
    jnz @F
    www db "欢迎来到汇编世界",0
  @@:
    call [MessageBox]
    invoke ExitProcess,0
    END START

反汇编后:

00401000 > $  8D05 00304000 lea     eax, dword ptr [403000]          ;  (initial cpu selection)
00401006   ?  6A 00         push    0
00401008   ?  6A 00         push    0
0040100A   ?  50            push    eax
0040100B   .  6A 00         push    0
0040100D   ?  74 13         je      short 00401022
0040100F   ?  75 11         jnz     short 00401022
00401011   ?  BB B6D3ADC0   mov     ebx, C0ADD3B6
00401016   ?  B4 B5         mov     ah, 0B5
00401018   ?  BD BBE3B1E0   mov     ebp, E0B1E3BB
0040101D   ?  CA C0BD       retf    0BDC0
00401020   ?  E7 00         out     0, eax
00401022   ?  E8 07000000   call    <jmp.&user32.MessageBoxA>
00401027   .  6A 00         push    0                                ; \MessageBoxA
00401029   ?  E8 06000000   call    <jmp.&kernel32.ExitProcess>
0040102E   .- FF25 08204000 jmp     dword ptr [<&user32.MessageBoxA>>; \ExitProcess
00401034   $- FF25 00204000 jmp     dword ptr [<&kernel32.ExitProces>;  kernel32.ExitProcess

用OD调试的时候感觉到有不习惯的了。

 

 

下面是一个完整的示例:

    ;=================
;完整API花指令示例:
    ;=================
    .386
    .Model Flat, StdCall
    Option Casemap :None   ; 不区分大小写(对API与API常数无效)
    ;_____________________________________________________________
    Include windows.inc
    Include user32.inc
    Include kernel32.inc

    IncludeLib user32.lib
    IncludeLib kernel32.lib
    .CODE
START:
    push 0
    push 0
    push offset Welcome
    push 0
    jz @F
    jnz @F
    Welcome db "Welcome",0   
@@:
    mov eax,[MessageBox+4]
    sub eax,4
    jnz @F
    Welcome1 db "Welcome",0   
@@:
    call eax
    invoke ExitProcess,0
    END START

反汇编代码:

00401000 > $  6A 00         push    0
00401002   .  6A 00         push    0
00401004   .  68 0F104000   push    0040100F
00401009   .  6A 00         push    0
0040100B   .  74 0A         je      short 00401017
0040100D   .  75 08         jnz     short 00401017
0040100F   .  57            push    edi
00401010   .  65:6C         ins     byte ptr es:[edi], dx
00401012   .  636F 6D       arpl    word ptr [edi+6D], bp
00401015      65            db      65                               ;  CHAR 'e'
00401016      00            db      00
00401017   .  B8 36104000   mov     eax, 00401036
0040101C   .  83E8 04       sub     eax, 4
0040101F   .  75 08         jnz     short 00401029
00401021   .  57            push    edi
00401022   .  65:6C         ins     byte ptr es:[edi], dx
00401024   .  636F 6D       arpl    word ptr [edi+6D], bp
00401027      65            db      65                               ;  CHAR 'e'
00401028      00            db      00
00401029   .  FFD0          call    eax
0040102B   .  6A 00         push    0                                ; /ExitCode = 0
0040102D   .  E8 06000000   call    <jmp.&kernel32.ExitProcess>      ; \ExitProcess
00401032   .- FF25 08204000 jmp     dword ptr [<&user32.MessageBoxA>>;  user32.MessageBoxA
00401038   .- FF25 00204000 jmp     dword ptr [<&kernel32.ExitProces>;  kernel32.ExitProcess

惨不忍睹,删除模块分析后

00401000 >  6A 00           push    0
00401002    6A 00           push    0
00401004    68 0F104000     push    0040100F                         ; ASCII "Welcome"
00401009    6A 00           push    0
0040100B    74 0A           je      short 00401017
0040100D    75 08           jnz     short 00401017
0040100F    57              push    edi
00401010    65:6C           ins     byte ptr es:[edi], dx
00401012    636F 6D         arpl    word ptr [edi+6D], bp
00401015    65:00B8 3610400>add     byte ptr gs:[eax+401036], bh
0040101C    83E8 04         sub     eax, 4
0040101F    75 08           jnz     short 00401029
00401021    57              push    edi
00401022    65:6C           ins     byte ptr es:[edi], dx
00401024    636F 6D         arpl    word ptr [edi+6D], bp
00401027    65:00FF         add     bh, bh
0040102A    D06A 00         shr     byte ptr [edx], 1
0040102D    E8 06000000     call    <jmp.&kernel32.ExitProcess>
00401032  - FF25 08204000   jmp     dword ptr [<&user32.MessageBoxA>>; user32.MessageBoxA
00401038  - FF25 00204000   jmp     dword ptr [<&kernel32.ExitProces>; kernel32.ExitProcess

感觉没多大变化,看来,花指令会让人发晕的。

posted @ 2012-09-23 21:53  r3call  阅读(2502)  评论(1编辑  收藏  举报