/
r0-1.html
237 lines (189 loc) · 7.82 KB
/
r0-1.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
<html>
<head>
<title>ВОЙНА В RING-0</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
</head>
<body bgcolor=#B0B0B0 text=#000000 link=#0000EE vlink=#551A8B>
<h1 align=center>ВОЙНА В RING-0</h1>
<h3 align=center>Часть 1</h3>
<p align=right>In your head, in your head<br>they are dyin'...</p>
<p>В этом тексте мы попытаемся кратко изложить текущее
положение вещей по поводу работы вирусов в нулевом кольце под маздаем (Win9X).</p>
<h2 align=center>ПЕРЕХОД В RING-3</h2>
<p>В случае запуска вируса в дос-задаче для дальнейших действий
(по переходу в ring-0) необходимо сначала перейти из V86 в ring-3.
Достигается это при помощи нескольких вызовов DPMI.
После перехода в ring-3 действия такие же как и при запуске PE файлов.</p>
<p>Проблема тут в том, что выход из DPMI-режима возможен только при выходе из
запущенной программы обратно в дос (INT 21H, AH=4CH), а досовой
программе-носителю уже перейдя в ring-3 отдавать управление нельзя.
Поэтому надо либо сбрасывать дроппер, либо получать управление при выходе
из программы, либо программу перезапускать.</p>
<table width=100% border=1 cellspacing=0 cellpadding=0>
<tr>
<td>
<pre>
mov ax, 1687h ; DPMI - проверка установки
int 2fh
or ax, ax
jnz exit
; ES:DI = адрес DPMI процедуры изменения режима
; SI=память(в параграфах.) необходимая для DPMI
push es ; сохраняем адрес DPMI процедуры
push di
pop dpmicall
mov ah, 48h ; выделить память под данные DPMI
mov bx, si
int 21h
jc exit
mov es, ax ; в ES сегмент
xor ax, ax ; флаги: bit0=0 -- 16-bit программа
db 09Ah
dpmicall dd ?
jc exit
; сейчас в 16-bit ring3
exit: mov ax, 4c00h ; выход в DOS
int 21h
</pre>
</table>
<h2 align=center>ПЕРЕХОД В RING-0</h2>
<p>В некоторых случаях работа с ring-0 начинается с перехода в него.
Следует заметить, что описанными здесь способами переход в ring-0
скорее всего не исчерпывается.</p>
<h3 align=center>ЗАГРУЗКА VXD</h3>
<p>Способ состоит в том, чтобы сбросить на диск .VxD-файл
(драйвер работающий в ring-0) и загрузить его.
Такие вирусы содержат в своем теле код откомпилированного .VxD-файла.</p>
<p>Загрузка VxD осуществляется вызовом функции открытия файла (CreateFile),
но имя .VxD-файла идет со специальным префиксом '<code>\\.\</code>'</p>
<h3 align=center>ПАТЧ СИСТЕМНЫХ ТАБЛИЦ</h3>
<p>Идея состоит в изменении таблиц IDT, GDT и LDT, которые в маздае
(в отличие от NT) не защищены от записи.</p>
<p>Проблема в том, что существующие антивирусные программы (например spider.vxd)
в состоянии защищать от записи страницы памяти,
в которых эти таблицы хранятся.</p>
<p>Сегодня они умеют защищать IDT и GDT.
Защита LDT связана с некоторыми (наверное, решаемыми) трудностями --
запись в LDT использует маздайный krnl386.exe, работающий в ring-3.</p>
<h3 align=center>ПАТЧ IDT</h3>
<p>Идея состоит в изменении адреса (оффсета) одного из обработчиков прерываний
(исключений) и вызове этого обработчика.
Очевидно, что атрибуты в дескрипторе такого прерывания должны указывать на
ring-0, иначе следует их таковыми сделать.</p>
<h3 align=center>ПАТЧ LDT</h3>
<p>Идея состоит в создании в LDT дескриптора шлюза вызова (call gate)
процедуры, находящейся в вирусе, но с правами ring-0. При вызове такой
процедуры (через callgate) происходит переход в ring-0.</p>
<h3 align=center>ВЫЗОВ VXD API БЕЗ ПЕРЕХОДА В RING-0</h3>
<p>Так как кернел пользует vxd api не переходя в ring-0,
то те же действия может (находясь в ring3)
выполнять и вирус.</p>
<h3 align=center>ДЕЙСТВИЯ В RING-0</h3>
<p>После перехода в ring-0 хорошо бы:</p>
<ol>
<li>выделить память
<li>создать в этой памяти копию вируса
<li>перехватить системные вызовы и/или создать треаду для поиска файлов
<li>обрабатывать пришедшие имена файлов (инфицировать файлы)
</ol>
<p>...да не тут то было. Присутствующий антивирус не даст сделать
подозрительный vxdcall.
Поэтому после перехода в ring0 но перед инсталляцией в память и перехватом
системных вызовов желательно совершить патч либо отгрузку
возможных антивирусных vxd драйверов. Либо не делать vxdcall-ов напрямую.</p>
<h3 align=center>ВЫДЕЛЕНИЕ ПАМЯТИ</h3>
<p>Выделение памяти особых трудностей не представляет.
Либо это стандартные вызовы VMM_PageAllocate, IFSMGR_GetHeap,
либо что-то еще.
Но в любом случае рекоммендуется защищать страницы вируса от доступа из
ring-3 посредством VMM_PageModifyPermissions.
Также неплохо бы защитить после перехода в ring0 системные таблицы -
от того же ring-3.</p>
<h3 align=center>СОЗДАНИЕ В ПАМЯТИ КОПИИ ВИРУСА</h3>
<p>Здесь вроде-бы проблем быть не должно, однако они есть.</p>
<p>Все VxDcall-ы в только что откомпилированном файле выглядят как
CD 20 xx xx yy yy, где xx xx-номер сервиса, yy yy-номер VxD.
Но после первого вызова такого vxdcall-а, он заменяется обработчиком INT 20h
на CALL [xxxxxxxx] или что-нибудь еще более неприличное,
после чего происходит переход на то же место, откуда был сделан вызов INT 20h.</p>
<p>Отсюда вытекают две проблемы.</p>
<p>Во-первых, раз управление возвращается туда же, то память, откуда произведен
vxdcall должна быть доступна для записи. Иначе все зависнет.
Да, это отнюдь не всегда проблема, ибо в ring-0 можно писать куда угодно.
Кроме shadowram и flashbios.</p>
<p>Во-вторых, наличие в вирусе такой гадости как call <непонятно куда> делает
его неработоспособным после перемещения на другой компьютер или даже после
перезагрузки.
Поэтому следует либо не вызывать vxdcall-ов изнутри тела вируса,
либо создавать дополнительную ("чистую") копию вируса при посадке
в память, либо перед началом работы с использованием vxdcall-ов возвращать
вирус патчем "обратно" в исходное состояние, и т.п.</p>
<h3 align=center>ПЕРЕХВАТ СИСТЕМНЫХ ВЫЗОВОВ</h3>
<p>Тут как правило используют IFSMGR_InstallFileSystemApiHook,
VMM_Hook_V86_Int_Chain и прочие.
Обработчики событий анализируют имена файлов и передают их
процедуре заражения.</p>
<p>Интересным методом при перехвате системных функций является мониторинг
самих функций работы с хуками, и деинсталляция и повторная инсталляция
вируса до и после этих вызовов. В результате вирус будет все время
оказываться самым первым в цепочке обработчиков.</p>
<p>Также интересным способом здесь является тривиальный сплайсинг.
Вызываем vxdcall вида CD 20 xx xx yy yy, и он заменяется на адрес дворда
по которому лежит оффсет на нужную нам функцию. Нагло туда лезем и меняем
либо этот дворд либо в код на который он указывает прописываем jmp на себя.</p>
<h3>ИНФИЦИРОВАНИЕ ФАЙЛОВ</h3>
<p>Работа с файлами осуществляется через IFSMGR_Ring0_FileIO.</p>
<p>Если не быть мудаком и не вызывать каждую функцию по сто раз запушивая ей
кучу параметров, а сделать универсальные процедуры (либо макросы) для работы
с файлами, то заражение не будет практически ни чем отличаться от
аналогичного в ring-3,
за исключением трудностей при работе с датой/временем файлов.</p>
<table width=100% border=1 cellspacing=0 cellpadding=0>
<tr>
<td colspan=2>
<pre>
input:
edx=filename
output:
cf=0, eax=handle
cf=1 error
</pre>
<tr>
<th width=50%>ring-0
<th>ring-3
<tr>
<td>
<pre>
fopen:
pusha
mov eax, R0_OPENCREATFILE
mov esi, edx
mov bx, 2022h
mov cx, 32
mov dx, 01h
VxDcall IFSMGR, Ring0_FileIO
mov [esp].pushad_eax, eax
popa
ret
</pre>
<td>
<pre>
fopen:
pusha
push 0
push FILE_ATTRIBUTE_NORMAL
push OPEN_EXISTING
push 0
push FILE_SHARE_READ
push GENERIC_READ + GENERIC_WRITE
push edx
call CreateFileA
mov [esp].pushad_eax, eax
not eax ; FFFFFFFF --> 0
cmp eax, 1 ; 0: CF=1 !0: CF=0
popa
ret
</pre>
</table>
<hr><br>
<p al