Получение EIP потока в Kernel Mode

Aug 09, 2007 15:44

Бля, две недели ебался с получением EIP потока из Kernel Mode. Юзермодные EIP потоков получались нормально через PsGetContextThread(), но еипы потоков процесса System отказывались получаться напрочь.
Пришлось думать... был просмотрен сорс SwapContext, которая, как известно, управляет переключением контекста потоков.
Были выделены интересные строки этой функции:

mov eax, [esi].ThInitialStack ; get initial stack address
sub eax, NPX_FRAME_LENGTH
.errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
test byte ptr [eax] - KTRAP_FRAME_LENGTH + TsEFlags + 2, EFLAGS_V86_MASK / 10000h
jnz short sc24 ; if nz, V86 frame, no adjustment
sub eax, TsV86Gs - TsHardwareSegSs ; bias for missing fields
sc24: mov ecx, [ebx]+PcTssCopy ; get TSS address
mov [ecx]+TssEsp0, eax ; set initial kernel stack address
Что в переводе на си выглядит примерно так:

ULONG TrapFrame;
PKTRAP_FRAME TestFrame;

TrapFrame = (ULONG)NextThread->InitialStack - NPX_FRAME_LENGTH;
TestFrame = (KTRAP_FRAME*)( TrapFrame - KTRAP_FRAME_LENGTH );

if( TrapFrame->EFlags & EFLAGS_V86_MASK == 0 )
{
TrapFrame = TrapFrame - ( FIELD_OFFSET(KTRAP_FRAME,V86Gs) - FIELD_OFFSET(KTRAP_FRAME, HardwareSegSs);
}

Pcr->TssCopy->Esp0 = TrapFrame;

Вообщем оказалось, что стоит копать в сторону ((KTRAP_FRAME*)KeGetPcr()->TSS->Esp0).

Для получения контекста пришлось доставить Kernel APC нужному потоку. Экспериментально оказалось, что ((KTRAP_FRAME*)KeGetPcr()->TSS->Esp0)->DbgEip указывает на EIP потока в момент доставки APC.
При отключенных прерываниях это то, что нужно.

Вывод DbgPrint:

DriverEntry()
Creating system thread 0xfca215d0
APC delivered to KTHREAD:0xff9da020, dumping Tss->Esp0: (=0xfa4d1df0)
... (дамп TrapFrame)

Success: KTHREAD:0xff9da020, its EIP = 0xfca215d0
GetThreadEip() returned 0xfca215d0 for ETHREAD=0xff9da020
DriverUnload()
Как видно, выделенные адреса (реальный и полученный EIP) совпадают... ура =)
Две недели ебли с кернел моде закончились успехом.

Кому интересно, код дам
Previous post Next post
Up