Каждый процесс представлен структурой EPROCESS (executive process block) в ядре. EPROCESS указывает на число связанных структур, например: у каждого процесса есть 1 или более потоков, которые представляются структурой ETHREAD.
EPROCESS указывает на PEB (process environment block) в адресном пространстве процесса
ETHREAD указывает на TEB (thread environment block) в адресном пространстве процесса
_______________________
| Process environment |
---> | block (PEB) | <---------
| |_______________________| |
| |
| |
| ______________
| | Thread |
| | environment |
| | Block (TEB) |
| |______________|
| ^
| |
User-Mode: Process Address Spase |
----------------------------------------------------------------
Kernel-Mode: System Address Space |
| |
| |
| |
| |
__________________ |
| Process block | |
| EPROCESS | KTHREAD
|__________________| |
| |
| _______________ |
| | Thread block |--->... |
---------->| ETHREAD |------------|
|_______________|
Что есть в PEB и TEB
PEB - Process Environment Block
- базовая информация об образе (базовый адрес, значение версии, список модулей)
- информации о куче в процессе
- переменные среды
- параметры командной строки
- путь для поиска DLL
Чтобы отобразить:
!peb
dt nt!_PEB
Чтобы посмотреть для чужого процесса:
kd> .process /p ffffe20fb340e080; !peb 10f90d5000
предварительно получив список процессов с адресами:
!process 0 0
TEB - Thread Environment Block
- информация о стеке (база стека, лимит стека)
- TLS (thread local storage) массив
Чтобы отобразить:
!teb
dt nt!_TEB
Посмотреть потоки другого процесса:
kd> !process 0 4 processname.exe
kd> dt nt!_KTHREAD ffffe20faeb39080
Получаем руками все процессы:
Общая идея примерно такая:
- Из PsActiveProcessHead получаем адрес, где лежит head списка процессов
- Само значение, которое мы получили, уже является ссылкой на следующий объект списка (то есть FLINK - forward link)
- Адрес, который мы получили - это структура LIST_ENTRY, в которой два поля: на след объект и на предыдущий, сам по себе этот полученный адрес лежит в середине структуры процесса в ActiveProcessLinks
- Получаем начало структуры процесса отнимая от полученного адреса сдвиг до начала
kd> x nt!PsActiveProcessHead
fffff803`5f01df60 nt!PsActiveProcessHead = <no type information>
kd> dq fffff803`5f01df60
fffff803`5f01df60 ffffca86`79a5b488 ffffca86`806b5788
fffff803`5f01df70 00000000`000001f4 00000000`00000000
fffff803`5f01df80 00000000`00000000 00000000`00000000
fffff803`5f01df90 fffff803`5ed07ea0 00000000`00000000
kd> dt nt!_EPROCESS
...
+0x448 ActiveProcessLinks : _LIST_ENTRY
...
kd> ?ffffca86`79a5b488 - 0x448
Evaluate expression: -58796061380544 = ffffca86`79a5b040
kd> dt nt!_EPROCESS ffffca86`79a5b040
(как прувнуть, что всё ок)
...
+0x5a8 ImageFileName : [15] "System"
Как получить следующие в списке процессы?
- Берём значение из ActiveProcessLinks
- Первый адрес - flink, второй - blink
- Отнимаем оффсет
- Дампим структуру
Автоматизация:
dt nt!_EPROCESS -l ActiveProcessLinks.Flink ffffca86`79a5b040
Получаем руками все потоки процесса:
kd> !process 0 0
...
PROCESS ffffca8680630080
SessionId: 1 Cid: 19cc Peb: 002ff000 ParentCid: 0abc
DirBase: 135b3000 ObjectTable: ffffb60d17072980 HandleCount: 57.
Image: threads.exe
...
kd> dt nt!_EPROCESS ffffca8680630080
...
+0x5e0 ThreadListHead : _LIST_ENTRY [ 0xffffca86`818bc9e8 - 0xffffca86`7bf5e9e8 ]
...
kd> dt nt!_ETHREAD
...
+0x4e8 ThreadListEntry : _LIST_ENTRY
...
kd> ?0xffffca86`818bc9e8 - 0x4e8
Evaluate expression: -58795928861440 = ffffca86`818bc500
kd> dt nt!_ETHREAD -l ThreadListEntry.Flink -y Thread ffffca86`818bc500
...
ThreadListEntry.Flink at 0xffffca86`818bc500
+0x4e8 ThreadListEntry : _LIST_ENTRY [ 0xffffca86`851e59e8 - 0xffffca86`80630660 ]
...
ThreadListEntry.Flink at 0xffffca86`851e5500
+0x4e8 ThreadListEntry : _LIST_ENTRY [ 0xffffca86`7e37c9e8 - 0xffffca86`818bc9e8 ]
...
ThreadListEntry.Flink at 0xffffca86`7e37c500
+0x4e8 ThreadListEntry : _LIST_ENTRY [ 0xffffca86`7bf5e9e8 - 0xffffca86`851e59e8 ]
...
ThreadListEntry.Flink at 0xffffca86`7bf5e500
+0x4e8 ThreadListEntry : _LIST_ENTRY [ 0xffffca86`80630660 - 0xffffca86`7e37c9e8 ]
...