“anti-”一詞在E文中是表示“反對, 抵抗”之義的前綴,而“debugger”是泛指各種調(diào)試(出錯)器,包括大家熟悉的softice、TRW2000及DOS下的debug、turbodebug, 還包括一些大家不是很熟悉的監(jiān)測分析工具等等,凡是能夠?qū)?yīng)用程序進行動態(tài)跟蹤分析、調(diào)試、監(jiān)測的軟件都可以稱作“debugger”。所謂“anti-debuggers”技術(shù), 顧名思義就是防止、防范這類工具起作用的技術(shù),簡而言之就是反調(diào)試、反跟蹤技術(shù)。 <BR> 為什么會有“anti-debuggers”技術(shù)的存在?它有什么作用呢?我們知道,世界上的事物總是對立與統(tǒng)一的結(jié)合,就像矛與盾的關(guān)系,有矛就有盾,失去了矛,盾也就沒有存在的必要了。 有人開發(fā)各種軟件,為了防止別人未經(jīng)授權(quán)擅自使用,于是在程序中使用了加密防范技術(shù),使得任何其它人想要使用它都必須得到作者的許可,可是偏偏就有那么一些人(cracker)秉承“share”的理念, 非要靠自己的技術(shù)在特殊工具的幫助下親自動手來揭開“潘多拉盒子”之謎,于是加密者發(fā)現(xiàn)自己的東西被別人“竊取”,所以就要想出對付那些特殊工具、使它們失去作用的技術(shù), 這就是“anti-debuggers”技術(shù)產(chǎn)生的根源?,F(xiàn)在破解早已不是什么隱晦的事情了,各種debuggers為這種技術(shù)的實現(xiàn)奠定了基礎(chǔ),特別是像softice這種大哥級的人物,只要想起它, 加密者心里都會抖一抖,但是任何debugger本身也只不過是一個程序而已,它有自己的運行方式,有自己的弱點,有被別人當(dāng)作漏洞的地方,這就是“anti-debuggers”技術(shù)產(chǎn)生的基礎(chǔ)。 <BR> 講了這么多,是不是覺得有點形而上學(xué)呢?也許你會問,我怎么知道什么樣的程序使用了“anti-debuggers”技術(shù)呢?其實也沒有什么確定的方法來判斷應(yīng)用程序是否使用了“anti-debuggers”技術(shù), 不過我們始終要注意一點,那就是“anti-debuggers”技術(shù)的目的主要是防止debugger的跟蹤、分析及調(diào)試,所以首先是要想辦法發(fā)現(xiàn)系統(tǒng)中存在的debuggers,然后采取行動阻止debuggers起作用, 其表現(xiàn)無非就是出現(xiàn)異常死機、系統(tǒng)異常重啟、異常錯誤、錯誤警告、軟件自毀、更嚴(yán)重的還會破壞文件甚至大肆破壞系統(tǒng)。。。等等非??膳碌男袨椤.?dāng)然,不是說凡是破解中遇到這些情況就一定說明程序使用了“anti-debuggers”技術(shù), 首先你要排除異常的情況是否是由系統(tǒng)不穩(wěn)定或是被跟蹤的程序“正常”拋出的,如果你的調(diào)試器本身不穩(wěn)定而導(dǎo)致系統(tǒng)異常,那就沒辦法了。不過值得慶幸的是如果你使用softice,通常不會有什么問題的, 因為softice真的是穩(wěn)定無比,就像泰山一樣,而其它的調(diào)試器就不敢恭維了^_^!不過正是由于softice實在太強大,因而現(xiàn)在的“anti-debuggers”技術(shù)主要是沖著它來的。在排除“正常”的錯誤之后,如果有條件的話,我們還可以通過改變跟蹤系統(tǒng)、環(huán)境及電腦的方法來重演錯誤事件,如果問題依舊, 應(yīng)該可以肯定是中了“anti-debuggers”技術(shù)的陷井。 <BR> 下面給大家介紹一些常用的“anti-debuggers”技術(shù)(主要是debugger的檢測技術(shù)): <BR>1. 利用softice的后門指令(Back Door commands): <BR> 后門指令通過中斷INT 03來進行,通過softice的后門指令可以獲得softice版本信息、獲得和設(shè)置斷點、執(zhí)行softice中的指令等。。。 <BR>----------------------------------------------------------------------------------------------- <BR>INT 03 子功能:獲取softice版本信息 <BR>入口參數(shù): <BR>-AX = 0000h <BR>-SI = 4647h ('FG') <BR>-DI = 4A4Dh ('JM') <BR>返回值:BCD版本號(如0280h = v2.80) <BR>----------------------------------------------------------------------------------------------- <BR>INT 03 子功能:彈出softice窗口并開始調(diào)試程序 <BR>入口參數(shù): <BR>-AX = 0902h <BR>-SI = 4647h ('FG') <BR>-DI = 4A4Dh ('JM') <BR>-DS:BX -> 寄存器初始化值 <BR>返回值:未知 <BR>寄存器初始化值的格式: <BR>偏移 大小 內(nèi)容 <BR>00h WORD SP初始化值 <BR>02h WORD SS初始化值 <BR>04h WORD IP初始化值 <BR>06h WORD CS初始化值 <BR>08h WORD DS和ES初始化值 <BR>0Ah WORD ??? <BR>0Ch WORD ??? <BR>0Eh WORD ??? <BR>10h WORD AX初始化值 <BR>12h WORD ??? (默認(rèn)為000AH ???) <BR>14h WORD ??? (默認(rèn)為0001H ???) <BR>16h WORD ??? (默認(rèn)為0100H ???) <BR>----------------------------------------------------------------------------------------------- <BR>INT 03 子功能:在softice窗口中顯示字符串 <BR>入口參數(shù): <BR>-AX = 0910h <BR>-SI = 4647h ('FG') <BR>-DI = 4A4Dh ('JM') <BR>-DS:DX -> 需要顯示的ASCIZ字符串(最多100個字節(jié), 0Dh表示OK) <BR>返回值:無 (在softice中顯示的字符串為“Soft-ICE is a debugger by Nu-Mega Technologies, Inc.”) <BR>----------------------------------------------------------------------------------------------- <BR>INT 03 子功能:執(zhí)行softice中的命令 <BR>入口參數(shù): <BR>-AX = 0911h <BR>-SI = 4647h ('FG') <BR>-DI = 4A4Dh ('JM') <BR>-DS:DX -> ASCIZ命令字符串(最多100個字節(jié), 0Dh表示OK,例如:“HBOOT”,ODH,0) <BR>返回值:無 <BR>說明:這里的所說的命令可以是我們在softice中使用的任何一個命令,例如:LDT, IDT, GDT, TSS, RS ... <BR>甚至是HBOOT,總之,通過這個功能調(diào)用,使用“anti-debuggers”技術(shù)的程序能夠完全控制softice的操作, <BR>比如它如果執(zhí)行HBOOT,那么結(jié)果就是重新啟動系統(tǒng)了?。?! <BR>----------------------------------------------------------------------------------------------- <BR>INT 03 子功能:獲取softice斷點信息 <BR>入口參數(shù): <BR>-AX = 0912h <BR>-SI = 4647h ('FG') <BR>-DI = 4A4Dh ('JM') <BR>返回值: <BR>-BH = 上一次斷點設(shè)置的入口序號 <BR>-BL = 上一次斷點設(shè)置的類型 <BR>-DH = 上一次被觸發(fā)的斷點的入口序號 <BR>-DL = 上一次被觸發(fā)的斷點的類型 <BR>斷點類型值: <BR>00h BPM (斷點寄存器類型) <BR>01h I/O <BR>02h INTerrupt <BR>03h BPX (INT 03形式的斷點) <BR>04h reserved <BR>05h range <BR>----------------------------------------------------------------------------------------------- <BR>INT 03 子功能:設(shè)置softice斷點 <BR>入口參數(shù): <BR>-AX = 0913h <BR>-SI = 4647h ('FG') <BR>-DI = 4A4Dh ('JM') <BR>-DS:DX -> 斷點結(jié)構(gòu)(breakpoint structure) <BR>返回值: <BR>-AX = 狀態(tài) <BR>00h 設(shè)置成功,此時BX = 斷點序號 <BR>03h 斷點表已經(jīng)滿 <BR>06h 內(nèi)存限制錯誤 <BR>07h I/O限制錯誤 <BR>09h 范圍限制錯誤 <BR>16h 重復(fù)斷點 <BR>----------------------------------------------------------------------------------------------- <BR>INT 03 子功能:清除softice斷點 <BR>入口參數(shù): <BR>-AX = 0914h <BR>-SI = 4647h ('FG') <BR>-DI = 4A4Dh ('JM') <BR>-BX = 斷點序號(由子功能0913h返回的) <BR>返回值:BX(未知信息) <BR>----------------------------------------------------------------------------------------------- <BR> 我們可以看到,每個子功能的入口參數(shù)都有相同的部分:即SI = 4647h ('FG');DI = 4A4Dh ('JM'),這兩個入口值在softice中叫做“魔法值”(magic values), 凡是softice的后門指令都必須以這兩個數(shù)為標(biāo)志。 <BR> 利用softice的后門指令是非常常用的“anti-debuggers”技術(shù),因為所謂后門指令其實也就是softice自己所使用的,它不僅可以獲取softice的信息, 甚至可以隨意控制softice的操作,威力無比! <BR>2. 搜索由任何系統(tǒng)調(diào)試器所返回的魔法數(shù)-->0F386h(magic number),通過調(diào)用INT 41H的子功能4Fh實現(xiàn),有下面的一些方式: <BR>----------------------------------------------------------------------------------------------- <BR> mov ax,4fh <BR> int 41h <BR> cmp ax, 0F386 <BR> jz SoftICE_detected <BR>----------------------------------------------------------------------------------------------- <BR> mov bx, cs <BR> lea dx, int41handler2 <BR> xchg dx, es:[41h*4] <BR> xchg bx, es:[41h*4+2] <BR> mov ax,4fh <BR> int 41h <BR> xchg dx, es:[41h*4] <BR> xchg bx, es:[41h*4+2] <BR> cmp ax, 0f386h <BR> jz SoftICE_detected <BR>int41handler2 PROC <BR> iret <BR>int41handler2 ENDP <BR>----------------------------------------------------------------------------------------------- <BR> xor ax,ax <BR> mov es,ax <BR> mov bx, cs <BR> lea dx, int41handler <BR> xchg dx, es:[41h*4] <BR> xchg bx, es:[41h*4+2] <BR> in al, 40h <BR> xor cx,cx <BR> int 41h <BR> xchg dx, es:[41h*4] <BR> xchg bx, es:[41h*4+2] <BR> cmp cl,al <BR> jnz SoftICE_detected <BR>int41handler PROC <BR> mov cl,al <BR> iret <BR>int41handler ENDP <BR>----------------------------------------------------------------------------------------------- <BR> 這個方法不只是針對softice,而是所有任意的系統(tǒng)調(diào)試器(debugger),因此效果比較明顯,也比較常用。 <BR>3. 通過中斷INT 68H檢測WinICE句柄: <BR>----------------------------------------------------------------------------------------------- <BR> mov ah,43h <BR> int 68h <BR> cmp ax,0F386h <BR> jz SoftICE_Detected <BR>----------------------------------------------------------------------------------------------- <BR> 注意:在softice中我們是不能通過 BPINT 68 來設(shè)置斷點的,但是可以通過另外一個命令實現(xiàn):BPX exec_int if ax==68, 其中被調(diào)用的函數(shù)位于[ebp+1Dh],客戶EIP(client eip)位于[ebp+48h],這個斷點設(shè)置方法只對32位應(yīng)用程序有效; <BR>4. 利用WINDOWS的API函數(shù)CreateFileA來試圖打開調(diào)試器的驅(qū)動程序句柄,這就是著名的“MeltICE”方法,NuMega公司的人用這個方法來使Symbol Loader檢查softice是否已經(jīng)激活 (這段代碼位于nmtrans.dll中),雖然這個方法最初來源于softice,但是它對其它類型的debugger檢測依然有效,調(diào)試器的驅(qū)動程序句柄有如下一些例子: <BR> SICE, SIWVID (對應(yīng)softice Win9x版) <BR> NTICE (對應(yīng)softice WinNT版) <BR> TRW、TRW2000、TRDEBUG (對應(yīng)TRWIN) <BR> REGVXD (對應(yīng)Registry Monitor) <BR> VKEYPRO (我也不知道這個對應(yīng)什么程序^_^) <BR> FILEVXD (對應(yīng)File Monitor) <BR> 。。。 <BR> 具體檢測方法可以用下面的程序來說明: <BR>BOOL IsSoftIce95Loaded() <BR>{ <BR> HANDLE hFile; <BR> hFile = CreateFile( "\\\\.\\SICE", GENERIC_READ | GENERIC_WRITE, <BR> FILE_SHARE_READ | FILE_SHARE_WRITE, <BR> NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); <BR> if( hFile != INVALID_HANDLE_VALUE ) <BR> { <BR> CloseHandle(hFile); <BR> return TRUE; <BR> } <BR> return FALSE; <BR>} <BR> 對應(yīng)于匯編代碼的檢測程序如下面所示: <BR> push 。。。 ; <BR> push 00402025 ; '\\.\SICE',0 <BR> call CreateFileA <BR> cmp eax,-001 <BR> jnz SoftICE_detected <BR> 對于16位應(yīng)用程序或是兼容16位的應(yīng)用程序來說,它們并不支持API函數(shù)CreateFileA,而使用的是16位的_lopen函數(shù): <BR> push 00 <BR> mov eax,[00656634] ; '\\.\SICE',0 <BR> push eax <BR> call KERNEL32!_lopen <BR> inc eax <BR> jnz SoftICE_detected <BR>為了檢測這些檢測程序,我們可以在softice中通過下面的斷點來攔截它們: <BR> BPX CreateFileA if *(esp->4+4)=='SICE' || *(esp->4+4)=='SIWV' || *(esp->4+4)=='NTIC' <BR> BPINT 30 if eax==002A001F && (*edi=='SICE' || *edi=='SIWV') ; 將會中斷3次 <BR> BPINT 30 if (*edi=='SICE' || *edi=='SIWV') <BR> BPX KERNEL32!ORD_0001 if *edi=='SICE' || *edi=='SIWV' ; 將會中斷3次 <BR> BPX VMM_GetDDBList if eax->3=='SICE' || eax->3=='SIWV' <BR>5. 利用softice的邊界檢查簽名(The signature of BoundsChecker): <BR>----------------------------------------------------------------------------------------------- <BR> mov ebp, 4243484Bh ; 'BCHK' <BR> mov ax, 04h <BR> int 3 <BR> cmp al,4 <BR> jnz SoftICE_Detected <BR>----------------------------------------------------------------------------------------------- <BR> 這個方法被大量地使用在網(wǎng)上各種加殼、加密軟件中; <BR>6. 搜索softice虛擬設(shè)備驅(qū)動程序的ID值(ID of SoftICE VxD),通過調(diào)用INT 2FH的子功能1684h實現(xiàn): <BR>----------------------------------------------------------------------------------------------- <BR> xor di,di <BR> mov es,di <BR> mov ax, 1684h <BR> mov bx, 0202h ; 搜索winice的VxD ID <BR> int 2Fh <BR> mov ax, es ; ES:DI 指向 VxD API 入口點 <BR> add ax, di <BR> test ax,ax <BR> jnz SoftICE_Detected <BR>----------------------------------------------------------------------------------------------- <BR> xor di,di <BR> mov es,di <BR> mov ax, 1684h <BR> mov bx, 7a5Fh ; 搜索SIWVID的VxD ID <BR> int 2fh <BR> mov ax, es ; ES:DI 指向 VxD API 入口點 <BR> add ax, di <BR> test ax,ax <BR> jnz SoftICE_Detected <BR>----------------------------------------------------------------------------------------------- <BR> 這種方法用得較少; <BR>7. 下面的方法同樣也是檢測softice的VxD ID來判斷它是否已經(jīng)裝入系統(tǒng),不過使用的不是中斷: <BR>----------------------------------------------------------------------------------------------- <BR> mov eax, Device_ID ; softice的VxD ID,對應(yīng)SICE等于202h;對應(yīng)SIWVID,等于07a5Fh; <BR> mov edi, Device_Name ; VxD名字,針對于沒有VxD ID的情況,不過對于我們討論的問題老說是沒有意義的; <BR> VMMCall Get_DDB <BR> mov [DDB], ecx ; 如果VXD沒有安裝,ECX返回0,否則返回DDB <BR>----------------------------------------------------------------------------------------------- <BR> VMMCall Test_Debug_Installed <BR> je not_installed <BR>----------------------------------------------------------------------------------------------- <BR> 這種方法只適用于系統(tǒng)0級(ring0),即虛擬設(shè)備驅(qū)動程序VxD或者是使用VxdCall的ring3應(yīng)用程序;Get_DDB服務(wù)功能用來檢查指定的設(shè)備是否安裝,如果安裝,則將設(shè)備描述塊地址返回到ECX中;我們可以很容易的在softice中通過斷點:bpx Get_DDB if ax==0202 || ax==7a5fh 來找到這個檢測程序處; <BR>8. 下面的方法通過VxDCall的后門(backdoor)來檢測系統(tǒng)中是否安裝了任何性質(zhì)的調(diào)試器: <BR>----------------------------------------------------------------------------------------------- <BR> push 0000004fh ; 功能號為4fh <BR> push 002a002ah ; 高位字指定是哪一個VxD (VWIN32) <BR> ; 低位字指定使用什么服務(wù)(VWIN32_Int41Dispatch) <BR> call Kernel32!ORD_001 ; VxdCall <BR> cmp ax, 0f386h ; 系統(tǒng)調(diào)試器返回的魔法數(shù)(magic number) <BR> jz SoftICE_detected <BR>----------------------------------------------------------------------------------------------- <BR> 這種方法因為使用了VxdCall,所以只能在Windows 95/98中使用(NT不支持VxD),為了檢測這種方法,我們可以在softice中通過下面的斷點來攔截它: <BR>BPINT 41 if ax==4f <BR>BPINT 30 if ax==0xF386 ; <BR>BPX Exec_PM_Int if eax==41 && edx->1c==4f && edx->10==002A002A <BR>BPX Kernel32!ord_0001 if esp->4==002A002A && esp->8==4f ; 非常非常慢!??! <BR>9. 通過注冊表中的鍵值來直接檢測是否安裝了softice,不過并不能知道softice是否是激活的(即是否在內(nèi)存中): <BR> -#1: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\SoftICE <BR> -#2: HKEY_LOCAL_MACHINE\Software\NuMega\SoftICE <BR> -#3: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\App Paths\Loader32.Exe <BR> -#4: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\NTice <BR> 某些應(yīng)用程序發(fā)現(xiàn)了注冊表中的softice鍵值后會直接將其刪掉,從而破還已經(jīng)安裝好的softice, 在softice中可以用斷點:BPX _regopenkey if *(esp->8+0x13)=='tICE' || *(esp->8+0x37)=='tICE'來攔截這種檢測; <BR>10. 通過對整個內(nèi)存范圍對softice特征字符串的搜查來判斷softice是否已經(jīng)安裝并激活,下面是個例子: <BR>----------------------------------------------------------------------------------------------- <BR>DATA_SICE DB 67h,66h,8bh,06h,0fh,22h,0d8h,26h,67h,66h <BR> DB 8bh,46h,04h,66h,26h,67h,0fh,01h,10h <BR>DATA_SICE_END <BR>assume cs:code,ds:code <BR> mov si,offset DATA_SICE <BR> mov dx,cs <BR> mov al,26h <BR> xor bp,bp <BR> cld <BR>loop1: <BR> mov es,bp <BR> mov cx,100h <BR> xor di,di <BR>loop2: <BR> repnz scasb <BR> jnz loop3 <BR> push cx <BR> push si <BR> push di <BR> mov cx,offset DATA_SICE_END-offset DATA_SICE <BR> repz cmpsb <BR> jz SoftICE_detected <BR> pop di <BR> pop si <BR> pop cx <BR> jmp short loop2 <BR>loop3: <BR> add bp,10h <BR> cmp bp,dx <BR> jb loop1 <BR>not_found: <BR> 。。。 <BR>----------------------------------------------------------------------------------------------- <BR>11. 通過改變DOS中斷調(diào)用的25H/35H來設(shè)置改變原有的中斷服務(wù)程序(主要是INT 01H和INT 03H),使系統(tǒng)崩潰,這個方法只是搞破壞,防止任何形式的對程序的非正常中斷, 因為程序已經(jīng)改變了INT 01或INT 03中斷服務(wù)程序,使得我們使用調(diào)試器設(shè)置斷點或使用其它任何需要改變這兩個中斷的應(yīng)用程序時系統(tǒng)直接崩潰或死機, 而不管是否這個斷點是如何產(chǎn)生的,甚至是正常程序出于正常需要的使用也不允許: <BR>----------------------------------------------------------------------------------------------- <BR> mov ah, 25h <BR> mov al, Int_Number (主要是INT 01H和INT 03H) <BR> mov dx, offset New_Int_Routine <BR> int 21h <BR>----------------------------------------------------------------------------------------------- <BR> 這種方法本人曾經(jīng)領(lǐng)教過,確實是很厲害,只要一設(shè)置斷點,馬上死機,不過多少顯得有點不道德,為什么這樣說呢? 因為假如中斷并不是由于debugger產(chǎn)生,而是某些應(yīng)用程序出于自身需要而產(chǎn)生的,這也要死機,大家有沒有感覺有些強盜邏輯的味道呢! <BR> 上面介紹了這么多的“anti-debuggers”技術(shù),我想以后再碰到這樣的情況就不會那么頭暈了吧!不過你肯定會問既然有如此多的“anti-debuggers”技術(shù), 那么我們?nèi)绾稳シ婪端鼈兡??一般說來有三種方法可以試一下: <BR> 第一、也是最簡單易行的辦法--采用專門的防止“anti-debuggers”技術(shù)的工具,比較有名的就是FrogsICE, 用它對付大部分含有“anti-debuggers”技術(shù)的應(yīng)用程序是沒有什么問題的,其具體的使用方法請參閱主頁上“破解教學(xué)”中的“FrogsICE使用指南”; <BR> 第二、通過對程序的靜態(tài)分析(如用反編譯工具W32DASM分析程序代碼),找到其中“anti-debuggers”代碼部分,然后用編輯工具(如HIEW)修改程序, 使其“anti-debuggers”代碼失效;不過這種方法對于加殼的程序來說沒有用處,因為加殼的程序是不能進行靜態(tài)分析的,我們可以先脫殼,然后再用反編譯工具進行分析; <BR> 第三、在對程序的動態(tài)跟蹤過程中和程序斗法,動態(tài)發(fā)現(xiàn)、找到“anti-debuggers”代碼的位置,然后將其殲滅,對于斷點的設(shè)置前面針對不同的“anti-debuggers”技術(shù)已經(jīng)分別討論過了。 這種方法難度較大,可有些時候卻是唯一的辦法,需要有很大的耐心(面對無數(shù)次的死機、藍屏。。。)!<BR> 最后,有關(guān)于上面所提到的中斷的更詳細(xì)信息,請參閱主頁上“匯編語言”中的“中斷大全”,里面有更多更詳細(xì)的相關(guān)中斷功能介紹。 <BR> |