Форум программистов, компьютерный форум, киберфорум
_lunar_
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  

Объекты операционной системы. Часть 4: Отладчик уровня ядра WinDbg

Запись от _lunar_ размещена 24.12.2021 в 19:41
Показов 3878 Комментарии 0
Метки c, c++, winapi

Объекты операционной системы. Часть 1: Общие сведения
Объекты операционной системы. Часть 2: Объект ядра
Объекты операционной системы. Часть 3: Уровень целостности

В этой части я решил показать самые интересные, на мой взгляд, возможности ядерного отладчика WinDbg.
Но сначала немного слов о том, как его установить и как им пользоваться.
В этом блоге я буду показывать работу отладчика WinDbg сразу для двух операционных: Windows 7 (x64) и Windows 10/11 (x64).
Почему две ОС? По двум причинам:
1. Windows 7 всё ещё остаётся актуальной;
2. Работа ядер этих ОС имеет большие различия, которые несомненно вызывают интерес, и которые мы увидим на примерах.

Итак, начнём с Windows 7.
Здесь всё просто, идём на MSDN, качаем Windows 11 WDK (прямая ссылка на online установщик) и устанавливаем по умолчанию в папку Program Files (x86).
После установки отладчик WinDbg будет располагаться по пути: Program Files (x86)\Windows Kits\10\Debuggers\x64
Попробуйте запустить windbg.exe, если вылезет вот такая ошибка
Нажмите на изображение для увеличения
Название: 0.png
Просмотров: 374
Размер:	20.9 Кб
ID:	7328
то скачайте эту библиотеку api-ms-win-core-sysinfo-l1-2-0.rar и положите в туже папку, где находится windbg.exe, ещё раз проверьте запускается ли отладчик.
Теперь, чтобы воспользоваться именно KernelMode отладкой необходимо выполнить три шага:
1. В BIOS отключите опцию SecureBoot (должно быть Disabled), если такой опции в BIOS нет, то переходите ко второму шагу.
2. Запустите командную строку (cmd.exe) от имени администратора и введите следующую команду bcdedit -debug on, должна быть надпись об успешном выполнении команды.
3. Перезагрузите компьютер.
Запустите windbg.exe от имени администратора. В меню нажмите File -> Kernel Degug... -> выберите Local и нажмите OK
Нажмите на изображение для увеличения
Название: 0.5.png
Просмотров: 348
Размер:	15.7 Кб
ID:	7330
Дождитесь окончания загрузки символов (в командной строке должна появиться надпись lkd>, что означает, что отладчик готов к принятию команд).

Теперь установка и настройка для Windows 10/11.
В этих ОС можно выбрать какой отладчик устанавливать:
- тот же, что и описанный в Windows 7 из пакета Windows 11 WDK;
- либо из магазина Microsoft Store WinDbg Preview, который также можно найти и в самом магазине.
Лично я предпочитаю WinDbg Preview, у него неплохой интерактивный GUI, да и сам интерфейс куда более приятный и современный.
Настройка аналогична трем шагам из Windows 7: выключить SecureBoot, включить debug on и перезагрузить компьютер.
Из Пуска запустите WinDbg Preview от имени администратора. В меню нажмите File -> Attach to kernel -> выберите Local и нажмите OK
Нажмите на изображение для увеличения
Название: 1.png
Просмотров: 396
Размер:	44.9 Кб
ID:	7327
Дождитесь окончания загрузки символов (в командной строке должна появиться надпись lkd>, что означает, что отладчик готов к принятию команд).

Так как отладчик сейчас работает в режиме ядра ОС, то эксперименты будем ставить над самым главным процессом - ядром операционной системы System.
Итак, первой командой, которой мы воспользуемся, это !process
Она выводит базовую информацию о процессе: сессию в которой он работает, идентификатор, родительский процесс, количество открытых дескрипторов этим процессом.
Давайте введем команду !process 0 0 System
Нажмите на изображение для увеличения
Название: 2.png
Просмотров: 423
Размер:	64.0 Кб
ID:	7331
Отлично! Теперь у нас есть значение объекта процесса System PROCESS fffffa80048d8040
Для того, чтобы понять что находится в этом объекте, необходимо получить заголовок этого объекта (ObjectHeader).
В отладчике WinDbg для этого предусмотрена команда !object
Соответственно введём эту команду и значение того объекта, у которого требуется получить заголовок !object fffffa80048d8040
Нажмите на изображение для увеличения
Название: 3.png
Просмотров: 414
Размер:	60.6 Кб
ID:	7332
Теперь у нас есть значение заголовка объекта процесса System ObjectHeader: fffffa80048d8010 (new version)
Зная это значение, можно посмотреть что содержится в структуре _OBJECT_HEADER
Воспользуемся следующей командой, которой передадим значение заголовка объекта dt nt!_object_header fffffa80048d8010
Нажмите на изображение для увеличения
Название: 4.png
Просмотров: 432
Размер:	45.6 Кб
ID:	7334
Самыми интересными полями этой структуры являются TypeIndex и SecurityDescriptor.
Начнём с SecurityDescriptor : 0xfffff8a0`0000464b.
Это указатель на структуру, содержащую уже знакомые нам ACL (SACL и DACL), а также их ACE, SID группы и владельца и их флаги.
Введем специальную команду, чтобы отобразить содержимое структуры, находящейся по значению SecurityDescriptor: !sd 0xfffff8a0`0000464b & -10
Нажмите на изображение для увеличения
Название: 5.png
Просмотров: 449
Размер:	84.5 Кб
ID:	7335
Заметьте, что KernelExplorer, кроме вывода этой информации, также выводит более детализированную информацию, в частности по структуре ACTRL_ALIST.
Данная структура является недокументированной, и собирать её содержимое достаточно сложно, видимо в Microsoft не стали заморачиваться, а ведь там есть очень ценная и уникальная информация по правам доступа каждого ACE (ACTRL_ACCESS_ENTRY)
Нажмите на изображение для увеличения
Название: 5.5.png
Просмотров: 436
Размер:	36.2 Кб
ID:	7336
Теперь давайте разберемся, что такое TypeIndex : 0x7.
TypeIndex это индекс указателя на структуру _OBJECT_TYPE в таблице ObTypeIndexTable.
Давайте посмотрим что это за таблица ObTypeIndexTable, находящаяся в ядре ОС. Для этого введём команду dps nt!ObTypeIndexTable
Нажмите на изображение для увеличения
Название: 6.png
Просмотров: 400
Размер:	64.7 Кб
ID:	7337
Так как эксперименты проводятся на 64 битной ОС, соответственно значения являются 8-ми байтовыми.
Обратите внимание: второе значение является ошибочным 00000000BAD0B0B0.
Что это такое? Это заплатка (patchGuard) от эксплойта вида
Нажмите на изображение для увеличения
Название: 8.png
Просмотров: 436
Размер:	13.9 Кб
ID:	7339
В Windows 7 существовал способ, позволяющий через shellcode получить контроль на объектами ядра в таблице ObTypeIndexTable.
После patchGuard все обращения ко второму значению приводили к ошибке вида BAD ObjectHeader.
В Windows 8.1 исправили этот баг непосредственно в коде ядра, тем самым представив метаданные следующим образом
Нажмите на изображение для увеличения
Название: 9.png
Просмотров: 426
Размер:	9.9 Кб
ID:	7340
Но давайте вернёмся к TypeIndex и его значению 0x7.
Начав отсчитывать от первого нулевого значения (нулевой индекс) до седьмого индекса (восьмого значения) в таблице ObTypeIndexTable, мы попадаем на значение fffffa80048769b0. Пока запомним его.
Для того, чтобы посмотреть содержимое структуры _OBJECT_TYPE воспользуемся специальной командой, в которой происходит арифметическое действие над таблицей с учетом индекса 7 и размерности значения, находящегося по этому индексу (8 байт)
dt nt!_OBJECT_TYPE poi(nt!ObTypeIndexTable + (7 * 8))
Нажмите на изображение для увеличения
Название: 7.png
Просмотров: 380
Размер:	63.9 Кб
ID:	7338
Первым делом посмотрите на поле Name : _UNICODE_STRING "Process".
Вернитесь в скриншоту, где мы использовали команду !object - поле Type: (fffffa80048769b0) Process: данный объект ядра является Process.
А теперь посмотрите на поле TypeList : _LIST_ENTRY (0xfffffa80`048769b0). Точно такое же значение, которое мы запомнили чуть раньше.
Поздравляю, мы получили валидный индекс процесса System (ядра ОС) в таблице ObTypeIndexTable.

Теперь вернёмся к Windows 10/11 и попробуем определить индекс в таблице ObTypeIndexTable. Вот что мы получим в итоге
Нажмите на изображение для увеличения
Название: 10.png
Просмотров: 462
Размер:	23.6 Кб
ID:	7343
TypeIndex в Windows 10/11 зашифрован.
Кроме того, в Windows 10 21H2 диапазон индексов лежит в промежутке [0...68]
Кликните здесь для просмотра всего текста
Code
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
TypeName                         | TypeIndex
---------------------------------|----------
(null)                           |  0
                                 |  1
Type                             |  2
Directory                        |  3
SymbolicLink                     |  4
Token                            |  5
Job                              |  6
Process                          |  7
Thread                           |  8
Partition                        |  9
UserApcReserve                   | 10
IoCompletionReserve              | 11
ActivityReference                | 12
PsSiloContextPaged               | 13
PsSiloContextNonPaged            | 14
DebugObject                      | 15
Event                            | 16
Mutant                           | 17
Callback                         | 18
Semaphore                        | 19
Timer                            | 20
IRTimer                          | 21
Profile                          | 22
KeyedEvent                       | 23
WindowStation                    | 24
Desktop                          | 25
Composition                      | 26
RawInputManager                  | 27
CoreMessaging                    | 28
ActivationObject                 | 29
TpWorkerFactory                  | 30
Adapter                          | 31
Controller                       | 32
Device                           | 33
Driver                           | 34
IoCompletion                     | 35
WaitCompletionPacket             | 36
File                             | 37
TmTm                             | 38
TmTx                             | 39
TmRm                             | 40
TmEn                             | 41
Section                          | 42
Session                          | 43
Key                              | 44
RegistryTransaction              | 45
ALPC Port                        | 46
EnergyTracker                    | 47
PowerRequest                     | 48
WmiGuid                          | 49
EtwRegistration                  | 50
EtwSessionDemuxEntry             | 51
EtwConsumer                      | 52
CoverageSampler                  | 53
DmaAdapter                       | 54
PcwObject                        | 55
FilterConnectionPort             | 56
FilterCommunicationPort          | 57
NdisCmState                      | 58
DxgkSharedResource               | 59
DxgkSharedKeyedMutexObject       | 60
DxgkSharedSyncObject             | 61
DxgkSharedSwapChainObject        | 62
DxgkDisplayManagerObject         | 63
DxgkCurrentDxgThreadObject       | 64 // Only in Windows 10
DxgkSharedProtectedSessionObject | 65
DxgkSharedBundleObject           | 66
DxgkCompositionObject            | 67
VRegConfigurationContext         | 68

а 0x4E это 78, что уже означает выход за допустимый диапазон.
Кстати в Windows 11 21H2 диапазон индексов был расширен
Кликните здесь для просмотра всего текста
Code
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
TypeName                         | TypeIndex
---------------------------------|----------
(null)                           |  0
                                 |  1
Type                             |  2
Directory                        |  3
SymbolicLink                     |  4
Token                            |  5
Job                              |  6
Process                          |  7
Thread                           |  8
Partition                        |  9
UserApcReserve                   | 10
IoCompletionReserve              | 11
ActivityReference                | 12
ProcessStateChange               | 13  // Only in Windows 11
ThreadStateChange                | 14  // Only in Windows 11
PsSiloContextPaged               | 15
PsSiloContextNonPaged            | 16
DebugObject                      | 17
Event                            | 18
Mutant                           | 19
Callback                         | 20
Semaphore                        | 21
Timer                            | 22
IRTimer                          | 23
Profile                          | 24
KeyedEvent                       | 25
WindowStation                    | 26
Desktop                          | 27
Composition                      | 28
RawInputManager                  | 29
CoreMessaging                    | 30
ActivationObject                 | 31
TpWorkerFactory                  | 32
Adapter                          | 33
Controller                       | 34
Device                           | 35
Driver                           | 36
IoCompletion                     | 37
WaitCompletionPacket             | 38
File                             | 39
IoRing                           | 40  // Only in Windows 11
TmTm                             | 41
TmTx                             | 42
TmRm                             | 43
TmEn                             | 44
Section                          | 45
Session                          | 46
Key                              | 47
RegistryTransaction              | 48
ALPC Port                        | 49
EnergyTracker                    | 50
PowerRequest                     | 51
WmiGuid                          | 52
EtwRegistration                  | 53
EtwSessionDemuxEntry             | 54
EtwConsumer                      | 55
CoverageSampler                  | 56
DmaAdapter                       | 57
PcwObject                        | 58
FilterConnectionPort             | 59
FilterCommunicationPort          | 60
NdisCmState                      | 61
DxgkSharedResource               | 62
DxgkSharedKeyedMutexObject       | 63
DxgkSharedSyncObject             | 64
DxgkSharedSwapChainObject        | 65
DxgkDisplayManagerObject         | 66
DxgkSharedProtectedSessionObject | 67
DxgkSharedBundleObject           | 68
DxgkCompositionObject            | 69
VRegConfigurationContext         | 70

Касаемо новых объектов ядра в Windows 11, могу порекомендовать почитать вот этот материал
ProcessStateChange и ThreadStateChange - Thread and Process State Change
IoRing - I/O Rings – When One I/O Operation is Not Enough

А это таблица индексов объектов ядра Windows 7
Кликните здесь для просмотра всего текста
Code
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
TypeName                         | TypeIndex
---------------------------------|----------
(null)                           |  0
BAD0B0B0                         |  1
Type                             |  2
Directory                        |  3
SymbolicLink                     |  4
Token                            |  5
Job                              |  6
Process                          |  7
Thread                           |  8
UserApcReserve                   |  9
IoCompletionReserve              | 10
DebugObject                      | 11
Event                            | 12
EventPair                        | 13 // Only in Windows 7
Mutant                           | 14
Callback                         | 15
Semaphore                        | 16
Timer                            | 17
Profile                          | 18
KeyedEvent                       | 19
WindowStation                    | 20
Desktop                          | 21
TpWorkerFactory                  | 22
Adapter                          | 23
Controller                       | 24
Device                           | 25
Driver                           | 26
IoCompletion                     | 27
File                             | 28
TmTm                             | 29
TmTx                             | 30
TmRm                             | 31
TmEn                             | 32
Section                          | 33
Session                          | 34
Key                              | 35
ALPC Port                        | 36
PowerRequest                     | 37
WmiGuid                          | 38
EtwRegistration                  | 39
EtwConsumer                      | 40
FilterConnectionPort             | 41
FilterCommunicationPort          | 42
PcwObject                        | 43

В Microsoft посчитали, что такой лёгкий доступ к таблице индексов ObTypeIndexTable недопустим и постарались запутать исследователей.
Но их защита простояла недолго, достаточно быстро был найден способ получения валидного индекса, довольно нетрадиционным способом.

Во-первых, исследователи ядра начали искать фрагменты кода, которые имеют что-то общее со структурой _OBJECT_TYPE
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
lkd> x nt!ob*type*
fffff806`2bc21f8c nt!ObpCreateDefaultObjectTypeSD (void)
fffff806`2bc218d0 nt!ObCreateObjectTypeEx (void)
fffff806`2bd82214 nt!ObEnumerateObjectsByType (ObEnumerateObjectsByType)
fffff806`2c024ef0 nt!ObpTypeObjectType = <no type information>
fffff806`2c024ee0 nt!ObpDirectoryObjectType = <no type information>
fffff806`2c107470 nt!ObTypeIndexTable = <no type information>
fffff806`2bb23b28 nt!ObQueryTypeInfo (ObQueryTypeInfo)
fffff806`2bc21ef8 nt!ObpInitObjectTypeSD (ObpInitObjectTypeSD)
fffff806`2be36038 nt!ObpObjectTypesPathString = <no type information>
fffff806`2bd82a60 nt!ObpDestroyTypeArray (ObpDestroyTypeArray)
fffff806`2bd8295c nt!ObpCreateTypeArray (ObpCreateTypeArray)
fffff806`2bf54aa0 nt!ObpTypeMapping = <no type information>
fffff806`2be36028 nt!ObpObjectTypesNameString = <no type information>
fffff806`2baa3cc0 nt!ObGetObjectType (ObGetObjectType)
fffff806`2c024e20 nt!ObpTypeDirectoryObject = <no type information>
fffff806`2bc218b0 nt!ObCreateObjectType (ObCreateObjectType)
fffff806`2c024ee8 nt!ObpSymbolicLinkObjectType = <no type information>
fffff806`2c024620 nt!ObpObjectTypes = <no type information>
fffff806`2bd82d3c nt!ObQueryTypeName (ObQueryTypeName)
Поиски выявили интересную функцию, которую нельзя было упускать из виду только лишь из-за ее названия nt!ObGetObjectType.
Затем было решено посмотреть на её мнемонику ассемблерного кода
Code
1
2
3
4
5
6
7
8
9
10
11
12
lkd> uf nt!ObGetObjectType
nt!ObGetObjectType:
fffff806`2baa3cc0 488d41d0        lea     rax,[rcx-30h]
fffff806`2baa3cc4 0fb649e8        movzx   ecx,byte ptr [rcx-18h]
fffff806`2baa3cc8 48c1e808        shr     rax,8
fffff806`2baa3ccc 0fb6c0          movzx   eax,al
fffff806`2baa3ccf 4833c1          xor     rax,rcx
fffff806`2baa3cd2 0fb60d2f2f6600  movzx   ecx,byte ptr [nt!ObHeaderCookie (fffff806`2c106c08)]
fffff806`2baa3cd9 4833c1          xor     rax,rcx
fffff806`2baa3cdc 488d0d8d376600  lea     rcx,[nt!ObTypeIndexTable (fffff806`2c107470)]
fffff806`2baa3ce3 488b04c1        mov     rax,qword ptr [rcx+rax*8]
fffff806`2baa3ce7 c3              ret
Функция ObGetObjectType принимает адрес объекта в качестве аргумента и выполняет следующие действия:
1. Код вычисляет адрес структуры _OBJECT_HEADER путем вычитания 0x30 из адреса памяти объекта, переданного в качестве аргумента.
0x30 это смещение от начала объекта до его заголовка в 64 битных ОС. В 32 битных ОС это смещение равняется 0x18.
2. Код выполняет операцию XOR для значения TypeIndex со вторым младшим байтом адреса структуры _OBJECT_HEADER, вычисленного на предыдущем шаге.
3. Затем код выполняет операцию XOR для результата из второго шага с байтом по адресу ObHeaderCookie.
4. Наконец результат операций XOR используется как индекс в ObTypeIndexTable и возвращает указатель на структуру _OBJECT_TYPE по этому индексу.

Теперь более простым языком, чтобы было понятно.
У нас есть объект PROCESS ffffc4052a8df040 процесса System, определенный после выполнения команды !process 0 0 System
От его значения мы отнимаем смещение до начала заголовка объекта: ffffc4052a8df040 - 0x30 = ffffc4052a8df010
Отсчёт байт начинается справа налево. Таким образом второй младший байт это 0xf0 (ffffc4052a8d f0 10).
Затем, необходимо выполнить команду db nt!ObHeaderCookie l1 чтобы определить байт в cookie, он равен 0xb9.
TypeIndex в зашифрованном виде равен 0x4e.
Теперь у нас есть все необходимые данные, они же ключи для расшифровки закодированного индекса методом XOR.
Введём следующую команду: ? f0 ^ 4e ^ b9
В итоге получаем расшифрованный TypeIndex: 0x7 для процесса System как и в случае с Windows 7.

Выведем таблицу ObTypeIndexTable командой dps nt!ObTypeIndexTable (как видите BAD ObjectHeader в Windows 10/11 уже нет).
Остаётся лишь только проверить имя Name : _UNICODE_STRING "Process" и адреса в TypeList : _LIST_ENTRY (0xffffc405`2a8bf380),
командой dt nt!_OBJECT_TYPE poi(nt!ObTypeIndexTable + (7 * 8))
Нажмите на изображение для увеличения
Название: 11.png
Просмотров: 432
Размер:	40.5 Кб
ID:	7345

Ну чтож, на этом я хотел бы поставить точку в изучении объектов операционной системы Windows.
Конечно же это только верхушка айсберга, и внутреннее устройство ОС Windows куда сложнее того, что я показал здесь.
Но главное, мы научились вскрывать то, что Microsoft зашифровала, причём на уровне ядра.
Метки c, c++, winapi
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 0
Комментарии
 
Новые блоги и статьи
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
[EasyBuilder Pro] Памятка по разработке для панелей Weintek
ФедосеевПавел 26.08.2026
Памятка по разработке для панелей Weintek ВВЕДЕНИЕ Ранее, при реализации проектов основное внимание уделял разработке управляющей программы для контроллера, а панели оператора доставалось время. . .
Модель по догадкам
anaschu 25.08.2026
Прошло две недели. Я уже рассказывал, как разговаривал с сотрудниками у сортировки и как понял, что главная ветка — не про приёмку, а про отбор. Но тогда я думал, что понял механику. На этой неделе я. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru