Главная > Программирование > Особенности хуков SSDT

Особенности хуков SSDT


По-моему нет ничего более банального, чем хучить API ядра через патч таблицы сервисов. Все это делали 100 раз, и вот на 101 раз выясняется, что есть особенности.

Захучили мы все API SDDT одним и тем же переходником, который просто логирует вызовы. Т.е. ничего не делает, кроме как логирует аргументы и передает их в оригинальную функцию. Все замечательно, работает. А потом вдруг бац и падает в глубинах NtReadVirtualMemory в Exception:

WARNING: Continuing a non-continuable exception
Access violation - code c0000005 (!!! second chance !!!)
nt!MmProbeAndLockPages+0x67b:

Пересмотрели все что только можно, падает и все. Методом «половинного деления» было выяснено, что если не хучить NtContinue не падает. Что же такого в NtContinue? А вот что:

__stdcall NtContinue(x, x) proc near

Context         = dword ptr  8
TestAlert       = byte ptr  0Ch

                push    ebp
                mov     ebx, large fs:124h
                mov     edx, [ebp+3Ch]
                mov     [ebx+134h], edx
                mov     ebp, esp
                mov     eax, [ebp+0]

ebp+3Ch — это не стековый аргумент, у функции всего два стековых аргумента, это обращение к Trap Frame! Изначально рассчитывается, что NtContinue будет вызываться из KiFastCallEntry. А в пределах KiFastCallEntry EBP — это не указатель на стековый фрейм, он содержит указатель на Trap Frame. То есть пока цепочка вот такая:
KiFastCallEntry -> NtContinue
все хорошо, за счет того, что EBP не меняется.
А если
KiFastCallEntry -> HookCode -> NtContinue
то функция HookCode изменяет EBP, ибо следует конвенции stdcall, а не stdcall + EBP. Таким образом универсальный хук должен еще учитывать тот факт, что есть API, которые обращаются к TrapFrame. NtContinue не одинока, есть еще NtRaiseException:

__stdcall NtRaiseException(x, x, x) proc near 

ExceptionRecord = dword ptr  8
Context         = dword ptr  0Ch
SearchFrames    = dword ptr  10h

                push    ebp
                mov     ebx, large fs:124h
                mov     edx, [ebp+3Ch]
                mov     [ebx+134h], edx
                mov     ebp, esp
                mov     ebx, [ebp+0]

С точно такими же замашками.

Для чего эти API нужен trap frame? Чтобы быстро выходить в ring-3, не возвращаясь в KiFastCallEntry.

  1. Комментариев нет.
  1. No trackbacks yet.

Оставьте комментарий