Нужны же нам смещения следующих полей:
- список WaitListHead
- ReadySummary
- массив LIST_ENTRY DispatcherReadyListHead
- список DeferredReadyListHead
DeferredReadyListHead
Обращение к этому полю встречается примерно в 24 функциях, среди которых есть и немало экспортируемых. На мой вкус проще всего посмотреть начало KeAlertThread: mov rbx, gs:20h
xor esi, esi
lea r13d, [rax-1]
lock bts qword ptr [rdi+40h], 0
jb loc_140034F29
mov r8b, r14b
mov rdx, rdi
mov rcx, rbx
call KiAlertThread
mov qword ptr [rdi+40h], 0
cmp qword ptr [rbx+2C88h], 0 ;
KPRCB.DeferredReadyListHead
mov r15b, al
jnz short loc_140034E7B
Если поле DeferredReadyListHead содержит не NULL, то ниже по коду вызывается KiProcessThreadWaitList, из которой можно узнать еще и смещение KTHREAD.WaitListEntry:
mov r15, [rcx+2C88h] ; KPRCB.DeferredReadyListHead
and qword ptr [rcx+2C88h], 0 ; KPRCB.DeferredReadyListHead = NULL
mov r12d, r8d
mov r13, rcx
lea rsi, [r15-0D8h] ; offsetof(KTHREAD.WaitListEntry)
ReadySummary
Проще всего ищется в начале функции NtYieldExecution: sub rsp, 20h
mov eax, gs:5218h ; KPRCB.ReadySummary
test eax, eax
jnz short loc_14004A9EE
Поскольку в данном случае чтение идет не из KPRCB, то нужно вычесть размер KPCR
К сожалению остальные нужные смещения вытаскиваются стат. анализом крайне плохо. Например смещение на DispatcherReadyListHead можно достать из KiSelectReadyThread (которая в свою очередь вызывается из NtYieldExecution):
mov eax, [rbx+5098h] ;
KPRCB.ReadySummary
mov ecx, edi
shr eax, cl
test eax, eax
jnz short loc_1400B9BFD
1400B9BFD:
bsr ecx, eax
add ecx, edi
mov eax, ecx
add rax, 510h
add rax, rax ; * 2
mov r9, [rbx+rax*8] ; * 8. Итого смещение на DispatcherReadyListHead 0x5100
Однако тут уже требуется некоторая эмуляция, а не просто анализ графа codeflow
Поэтому проще всего сделать табличку, описывающую все нужные смещения и искать по ней по паре найденных. Опыты показывают что эти пары уникальны под всеми версиями windows & service packs
Комментариев нет:
Отправить комментарий