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;_____________________________________________________________ .CODESTART: 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 = NULL00401004 |. 68 00304000 push 00403000 ; |欢迎来到汇编的世界00401009 |. 6A 00 push 0 ; |hOwner = NULL0040100B |. E8 08000000 call; \MessageBoxA00401010 |. 6A 00 push 0 ; /ExitCode = 000401012 \. E8 07000000 call ; \ExitProcess00401017 CC int300401018 $- FF25 08204000 jmp dword ptr [<&user32.MessageBoxA>>; user32.MessageBoxA0040101E .- FF25 00204000 jmp dword ptr [<&kernel32.ExitProces>; kernel32.ExitProcess
修改code段代码为:
.CODESTART: 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 000401008 |? 6A 00 push 00040100A |? 50 push eax0040100B |. 6A 00 push 0 ; \MessageBoxA0040100D |? E8 08000000 call00401012 \. 6A 00 push 0 ; \ExitProcess00401014 ? E8 07000000 call 00401019 ? CC int30040101A ?- FF25 08204000 jmp dword ptr [<&user32.MessageBoxA>>; user32.MessageBoxA00401020 ?- FF25 00204000 jmp dword ptr [<&kernel32.ExitProces>; kernel32.ExitProcess
还有就是使用花指令,花指令不但可以使反汇编工具无法识别出字符串,更会让它们把汇编出错误的代码,花指令一般都是使用一些无用的字节来进行干扰,但是干扰反汇编的字节仍是可以使用的,像这样子:
.data Welcome db "你是不是在搞笑哦!",0;_____________________________________________________________ .CODESTART: 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 0040101500401002 . |75 11 jnz short 0040101500401004 . |BB B6D3ADC0 mov ebx, C0ADD3B600401009 . |B4 B5 mov ah, 0B50040100B . |BD BBE3B1E0 mov ebp, E0B1E3BB00401010 . |CA C0BD retf 0BDC000401013 . |E7 00 out 0, eax00401015 > \8D05 04104000 lea eax, dword ptr [401004]0040101B . 8D1D 00304000 lea ebx, dword ptr [403000]00401021 . 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL00401023 . 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 = NULL00401027 . E8 08000000 call; \MessageBoxA0040102C . 6A 00 push 0 ; /ExitCode = 00040102E . E8 07000000 call ; \ExitProcess00401033 CC int300401034 $- FF25 08204000 jmp dword ptr [<&user32.MessageBoxA>>; user32.MessageBoxA0040103A .- FF25 00204000 jmp dword ptr [<&kernel32.ExitProces>; kernel32.ExitProcess
感觉还是有些明显,我们手动调用API来试试。
.data Welcome db "你是不是在搞笑哦!",0;_____________________________________________________________ .CODESTART: 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 000401008 ? 6A 00 push 00040100A ? 50 push eax0040100B . 6A 00 push 00040100D ? 74 13 je short 004010220040100F ? 75 11 jnz short 0040102200401011 ? BB B6D3ADC0 mov ebx, C0ADD3B600401016 ? B4 B5 mov ah, 0B500401018 ? BD BBE3B1E0 mov ebp, E0B1E3BB0040101D ? CA C0BD retf 0BDC000401020 ? E7 00 out 0, eax00401022 ? E8 07000000 call00401027 . 6A 00 push 0 ; \MessageBoxA00401029 ? E8 06000000 call 0040102E .- FF25 08204000 jmp dword ptr [<&user32.MessageBoxA>>; \ExitProcess00401034 $- 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 .CODESTART: 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 000401002 . 6A 00 push 000401004 . 68 0F104000 push 0040100F00401009 . 6A 00 push 00040100B . 74 0A je short 004010170040100D . 75 08 jnz short 004010170040100F . 57 push edi00401010 . 65:6C ins byte ptr es:[edi], dx00401012 . 636F 6D arpl word ptr [edi+6D], bp00401015 65 db 65 ; CHAR 'e'00401016 00 db 0000401017 . B8 36104000 mov eax, 004010360040101C . 83E8 04 sub eax, 40040101F . 75 08 jnz short 0040102900401021 . 57 push edi00401022 . 65:6C ins byte ptr es:[edi], dx00401024 . 636F 6D arpl word ptr [edi+6D], bp00401027 65 db 65 ; CHAR 'e'00401028 00 db 0000401029 . FFD0 call eax0040102B . 6A 00 push 0 ; /ExitCode = 00040102D . E8 06000000 call; \ExitProcess00401032 .- FF25 08204000 jmp dword ptr [<&user32.MessageBoxA>>; user32.MessageBoxA00401038 .- FF25 00204000 jmp dword ptr [<&kernel32.ExitProces>; kernel32.ExitProcess
惨不忍睹,删除模块分析后
00401000 > 6A 00 push 000401002 6A 00 push 000401004 68 0F104000 push 0040100F ; ASCII "Welcome"00401009 6A 00 push 00040100B 74 0A je short 004010170040100D 75 08 jnz short 004010170040100F 57 push edi00401010 65:6C ins byte ptr es:[edi], dx00401012 636F 6D arpl word ptr [edi+6D], bp00401015 65:00B8 3610400>add byte ptr gs:[eax+401036], bh0040101C 83E8 04 sub eax, 40040101F 75 08 jnz short 0040102900401021 57 push edi00401022 65:6C ins byte ptr es:[edi], dx00401024 636F 6D arpl word ptr [edi+6D], bp00401027 65:00FF add bh, bh0040102A D06A 00 shr byte ptr [edx], 10040102D E8 06000000 call00401032 - FF25 08204000 jmp dword ptr [<&user32.MessageBoxA>>; user32.MessageBoxA00401038 - FF25 00204000 jmp dword ptr [<&kernel32.ExitProces>; kernel32.ExitProcess
感觉没多大变化,看来,花指令会让人发晕的。