home *** CD-ROM | disk | FTP | other *** search
/ Hacks & Cracks / Hacks_and_Cracks.iso / hackersguides-&-software / 40hex-12.zip / 40HEX-12.003 < prev    next >
Text File  |  1993-11-25  |  10KB  |  289 lines

  1. 40Hex Number 12 Volume 3 Issue 3                                     File 003
  2.  
  3.                 Self Checking Executable Files
  4.                                         Demogorgon  Phalcon/Skism
  5.  
  6.  
  7.      In this article I will explain a method that will allow .COM files
  8. to be immune to simple viruses.  In order to infect a .COM file, a virus
  9. must change several bytes at the beginning of the code.  Before the
  10. virus returns control to the original program, it will 'disinfect' it
  11. into memory, so that the program runs as it did before infection.  This
  12. disinfection process is crucial, because it means that the image on the
  13. disk will not be the same as the memory image of the program.  This
  14. article describes a method by which a .COM file can perform a self-check
  15. by reading its disk image and comparing it to its memory image.
  16.  
  17.      The full pathname of the program that is being executed by DOS is
  18. located in the environment block.  The segment of the environment block
  19. can be read from the PSP.  It is located at offset [2Ch].
  20.  
  21.      The name of the program is the last entry in the environment block,
  22. and can be located by searching for two zeros.  The next byte after the
  23. two zeros contains the length of the string that follows it.  After the
  24. length is an ASCIIZ string containing the pathname of the current
  25. process.  The following code opens the file being executed:
  26.  
  27. nish:   mov     es, word ptr ds:[2Ch]   ; segment of environment
  28.         xor     ax, ax
  29.         mov     di, 1
  30. loop_0: dec     di
  31.         scasw
  32.         jne     loop_0
  33.  
  34.         mov     dx, di
  35.         add     dx, 2                   ; start of pathname
  36.         push    es
  37.         pop     ds
  38.         mov     ax, 3D02h               ; open, read/write access
  39.         int     21h
  40.  
  41.      Next, we must read in the file (using dos services function 3Fh,
  42. read file or device).  We can read the file into the heap space after
  43. the program, as long as we are sure we will not overwrite the stack. The
  44. sample program in this file reads itself in entirely, but remember, it
  45. is not necessary to do so. It is only necessary to read and compare the
  46. first few bytes.  Also, the program could read itself in blocks instead
  47. of all at once.
  48.  
  49.      If a file finds itself to be infected, it should report this to the
  50. user.  Remember, even though the file knows it is infected, the virus
  51. has already executed.  Memory resident viruses will already have loaded
  52. themselves into memory, and direct action viruses will already have
  53. infected other files on the drive.  Thus, any virus that employs
  54. disinfection on the fly will be able to avoid detection and removal.
  55. Here is the full source to the self checking program:
  56.  
  57.  
  58. ;();();();();();();();();();();();();();();();();();();();();()
  59.  
  60. .model tiny
  61. .code
  62. org 100h
  63.  
  64. start:  mov     es, word ptr ds:[2Ch]   ; dos environment block
  65.         xor     ax, ax
  66.         mov     di, 1
  67. loop_0: dec     di
  68.         scasw
  69.         jne     loop_0
  70.  
  71.         mov     dx, di
  72.         add     dx, 2                   ; <- point to current
  73.         push    es                      ;    process name
  74.         pop     ds
  75.         mov     ah, 3Dh                 ; open file with handle
  76.         int     21h
  77.         jc      bad                     ; error opening file ?
  78.         mov     bx, ax
  79.  
  80.         push    cs
  81.         push    cs
  82.         pop     es
  83.         pop     ds                      ; I am a com file.
  84.  
  85.         mov     cx, heap - start        ; length
  86.         lea     dx, heap                ; where to read file into
  87.         mov     ah, 3Fh                 ; read file or device
  88.         int     21h
  89.         jc      bad                     ; error reading file ?
  90.  
  91.         ; here, do a byte for byte compare
  92.         lea     si, start
  93.         lea     di, heap
  94.  
  95.         repe    cmpsb                   ; compare 'em
  96.         jne     bad
  97.  
  98.         lea     dx, clean
  99.         mov     ah, 9
  100.         int     21h
  101.         jmp     quit_
  102.  
  103. bad:    mov     ah, 9
  104.         lea     dx, infected
  105.         int     21h
  106.  
  107. quit_:  mov     ax, 4C00h
  108.         int     21h
  109.  
  110. clean    db 'Self check passed.$'
  111. infected db 'Self check failed.  Program is probably infected.$'
  112.  
  113. heap:
  114.  
  115. end start
  116.  
  117. ;();();();();();();();();();();();();();();();();();();();();()
  118.  
  119.  
  120.      While some self checking routines opt to use a crc or checksum
  121. error detection method, the byte for byte method is both faster and more
  122. accurate.
  123.  
  124.      Weak points: This routine will not work against a stealth virus
  125. which employs disinfection on the fly.  Such viruses take over the dos
  126. interrupt (int 21) and disinfect all files that are opened and read
  127. from.  As the routine in this article attempts to read itself into
  128. memory, the stealth virus would disinfect it and write an uninfected
  129. copy to ram.  Of course, there are ways to defeat this.  If this program
  130. were to use some sort of tunneling, it could bypass the stealth virus
  131. and call DOS directly.  That way, infections by even the most
  132. sophisticated viruses would be detectable.
  133.  
  134.  
  135. Disinfection:
  136.  
  137.      So, now you can write programs that will detect if they have been
  138. infected.  How about disinfection?  This too is possible.  Most viruses
  139. simply replace the first three bytes of the executable file with a jump
  140. or a call, which transfers control to the virus code. Since only the
  141. first three bytes are going to be changed (in almost all cases), it will
  142. usually be possible for a program to disinfect itself by replacing the
  143. first three bytes with what is supposed to be there, and then truncating
  144. itself to the correct size.  The next program writes the entire memory
  145. image to disk, rather than just the first three bytes.  That way, it can
  146. be used to disinfect itself from all nonstealth viruses.
  147.  
  148.      The steps to disinfect are simple.  First of all, you must move the
  149. file pointer back to the beginning of the file.  Use interrupt 21,
  150. ah=42h for this.  The AL register holds the move mode, which must be 00
  151. in this case (move from beginning of file).  CX:DX holds the 32bit
  152. number for how many bytes to move.  Naturally, this should be 0:0.
  153.  
  154.      The second step is to write back the memory image to the file.
  155. Since the virus has already restored the first few bytes of our program
  156. in memory, we must simply write back to the original file, starting from
  157. 100h in the current code segment.  i.e.:
  158.  
  159.         mov     ah, 40h
  160.         mov     cx, heap - start ; bytes to write
  161.         lea     dx, start
  162.         int     21h              ; write file or device
  163.  
  164.      Finally, we must truncate the file back to its original size.  To
  165. truncate a file, we must move the file pointer to the end and call the
  166. 'write file or device' function with cx, the bytes to write, equal to
  167. zero. To move the pointer, do this:
  168.  
  169.         mov     ax, 4200h
  170.         mov     cx, (heap - start) SHR 16     ; high word of file ptr
  171.         mov     dx, (heap - start)            ; low word of file ptr
  172.         int     21h                           ; move file pointer
  173.  
  174.  
  175.      Since we are dealing with .COM files here, it is safe to assume
  176. that cx, the most significant word of the file ptr, can be set to zero,
  177. because our entire file must fit into one segment.  We do not need to
  178. calculate it as above.
  179.  
  180.      To truncate:
  181.  
  182.         xor     cx, cx
  183.         mov     ah, 40h
  184.         int     21h             ; truncate file
  185.  
  186.      The full code for the self disinfecting program follows.
  187.  
  188.  
  189. ;();();();();();();();();();();();();();();();();();();();();()
  190.  
  191. .model tiny
  192. .code
  193. org 100h
  194.  
  195. start:  mov     es, word ptr ds:[2Ch]   ; segment of environment
  196.         xor     ax, ax
  197.         mov     di, 1
  198. loop_0: dec     di
  199.         scasw
  200.         jne     loop_0
  201.  
  202.         mov     dx, di
  203.         add     dx, 2
  204.         push    es
  205.         pop     ds
  206.         mov     ax, 3D02h               ; open, read/write access
  207.         int     21h
  208.         mov     bx, ax                  ; handle into bx
  209.         push    cs
  210.         push    cs
  211.         pop     es
  212.         pop     ds
  213.         mov     cx, heap - start
  214.         lea     dx, heap
  215.         mov     ah, 3Fh                 ; read file or device
  216.         int     21h
  217.         jc      quit_                   ; can't read ?
  218.  
  219.         lea     si, start
  220.         lea     di, heap
  221.  
  222.         repe    cmpsb                   ; byte for byte compare
  223.         jne     bad
  224.  
  225.         lea     dx, clean               ; we are golden
  226.         mov     ah, 9                   ; print string
  227.         int     21h
  228.         jmp     main_program
  229.  
  230. bad:    mov     ah, 9                   ; we are infected
  231.         lea     dx, infected
  232.         int     21h
  233.  
  234.         lea     dx, disinfection
  235.         int     21h
  236.  
  237.         ; now, disinfect.  File handle is still in bx
  238.         ; we must move the file pointer to the beginning
  239.         xor     cx, cx
  240.         xor     dx, dx
  241.         mov     ax, 4200h
  242.         int     21h             ; move file pointer
  243.  
  244.         mov     ah, 40h         ; 40hex!
  245.         mov     cx, heap - start
  246.         lea     dx, start
  247.         int     21h             ; write file or device
  248.         jnc     success
  249.  
  250.         lea     dx, not__
  251.         mov     ah, 9
  252.         int     21h
  253. success:mov     ah, 9
  254.         lea     dx, successful
  255.         int     21h
  256.  
  257.         xor     cx, cx
  258.         mov     ah, 40h         ; 40hex!
  259.         int     21h             ; truncate file
  260.  
  261. main_program:
  262.  
  263. quit_:  mov     ax, 4C00h
  264.         int     21h
  265.  
  266. disinfection  db 0Dh, 0Ah, 'Disinfection $'
  267. not__         db 'not '
  268. successful    db 'successful.$'
  269.  
  270. clean         db 'Self check passed.$'
  271. infected      db 'Self check failed.  Program is probably '
  272.               db 'infected.$'
  273.  
  274. heap:
  275.  
  276. end start
  277.  
  278. ;();();();();();();();();();();();();();();();();();();();();()
  279.  
  280. Weak points: The same weak points that apply above also apply here.
  281. Additionally, the program may, by writing itself back to disk, give the
  282. virus the opportunity to reinfect.  Remember, any memory resident
  283. viruses will already have loaded into memory by the time the program
  284. disinfects itself.  When the program tries to disinfect itself, any
  285. virus that intercepts the 'write file or device' interrupt will
  286. intercept this write and re-infect.  Again, tunneling is the clear
  287. solution.
  288.  
  289.