Сделать это довольно просто, т.к. трап фрейм имеет некую метку, по которой его можно опознать в памяти ( ну и дополнительные признаки, чтобы быть полностью уверенным - значение сегментных регистров, eflags/eip и т.д.).
Как известно, при любом прерывании/sysenter, обработчик прерывания/sysenter'a строит трап фрейм - заполняет структуру KTRAP_FRAME в стеке, точнее дополняет, т.к. некоторые члены структуры оказываются в стеке автоматически при прерывании(eflags, cs, eip, error code для без кольцевого переключения например), при этом в поле TsDbgArgMark заносится маска 0BADB0D00h ( макрос SET_DEBUG_DATA в сорцах ).
Таким образом, к примеру:
kd> dds 0xee8a9d64
ee8a9d64 00c0f7dc
ee8a9d68 7c90e514
ee8a9d6c badb0d00 <== та самая метка трапфрейма
ee8a9d70 00c0f7b8
ee8a9d74 00000000
Чтобы убедиться:
kd> dt nt!_KTRAP_FRAME 0xee8a9d64
+0x000 DbgEbp : 0xc0f7dc
+0x004 DbgEip : 0x7c90e514
+0x008 DbgArgMark : 0xbadb0d00<== метка
+0x00c DbgArgPointer : 0xc0f7b8
+0x010 TempSegCs : 0
+0x014 TempEsp : 0
+0x018 Dr0 : 0
+0x01c Dr1 : 0
+0x020 Dr2 : 0
+0x024 Dr3 : 0
+0x028 Dr6 : 0
+0x02c Dr7 : 0
+0x030 SegGs : 0
+0x034 SegEs : 0x23 <=== дополнительный признак
+0x038 SegDs : 0x23 <=== дополнительный признак
+0x03c Edx : 0x15f0002
+0x040 Ecx : 0xc6270
+0x044 Eax : 0xc6270
+0x048 PreviousPreviousMode : 1 <=== дополнительный признак
+0x04c ExceptionList : 0xffffffff <=== дополнительный признак
+0x050 SegFs : 0x3b <=== дополнительный признак
+0x054 Edi : 0
+0x058 Esi : 0
+0x05c Ebx : 0xc0f7f4
+0x060 Ebp : 0xc0f7dc
+0x064 ErrCode : 0
+0x068 Eip : 0x7c90e514 <=== дополнительный признак (валидный адрес)
+0x06c SegCs : 0x1b <=== дополнительный признак
+0x070 EFlags : 0x246 <=== дополнительный признак
+0x074 HardwareEsp : 0xc0f7b0
+0x078 HardwareSegSs : 0x23 <=== дополнительный признак
+0x07c V86Es : 0
+0x080 V86Ds : 0
+0x084 V86Fs : 0
+0x088 V86Gs : 0
Т.к. селекторы известны и постоянны:
#define KGDT_NULL 0
#define KGDT_R0_CODE 8
#define KGDT_R0_DATA 16
#define KGDT_R3_CODE 24
#define KGDT_R3_DATA 32
#define KGDT_TSS 40
#define KGDT_R0_PCR 48
#define KGDT_R3_TEB 56
#define KGDT_VDM_TILE 64
#define KGDT_LDT 72
#define KGDT_DF_TSS 80
#define KGDT_NMI_TSS 88
Это дает нам практически 100%ю гарантию, что найден именно трап фрейм, а не участок памяти с совпавшей TsDbgArgMark.
Метка эта нигде не проверяется(в релизной версии винды) и была введена для отладки.
Для x64 она отсутствует.
Как известно, при любом прерывании/sysenter, обработчик прерывания/sysenter'a строит трап фрейм - заполняет структуру KTRAP_FRAME в стеке, точнее дополняет, т.к. некоторые члены структуры оказываются в стеке автоматически при прерывании(eflags, cs, eip, error code для без кольцевого переключения например), при этом в поле TsDbgArgMark заносится маска 0BADB0D00h ( макрос SET_DEBUG_DATA в сорцах ).
Таким образом, к примеру:
kd> dds 0xee8a9d64
ee8a9d64 00c0f7dc
ee8a9d68 7c90e514
ee8a9d6c badb0d00 <== та самая метка трапфрейма
ee8a9d70 00c0f7b8
ee8a9d74 00000000
Чтобы убедиться:
kd> dt nt!_KTRAP_FRAME 0xee8a9d64
+0x000 DbgEbp : 0xc0f7dc
+0x004 DbgEip : 0x7c90e514
+0x008 DbgArgMark : 0xbadb0d00<== метка
+0x00c DbgArgPointer : 0xc0f7b8
+0x010 TempSegCs : 0
+0x014 TempEsp : 0
+0x018 Dr0 : 0
+0x01c Dr1 : 0
+0x020 Dr2 : 0
+0x024 Dr3 : 0
+0x028 Dr6 : 0
+0x02c Dr7 : 0
+0x030 SegGs : 0
+0x034 SegEs : 0x23 <=== дополнительный признак
+0x038 SegDs : 0x23 <=== дополнительный признак
+0x03c Edx : 0x15f0002
+0x040 Ecx : 0xc6270
+0x044 Eax : 0xc6270
+0x048 PreviousPreviousMode : 1 <=== дополнительный признак
+0x04c ExceptionList : 0xffffffff <=== дополнительный признак
+0x050 SegFs : 0x3b <=== дополнительный признак
+0x054 Edi : 0
+0x058 Esi : 0
+0x05c Ebx : 0xc0f7f4
+0x060 Ebp : 0xc0f7dc
+0x064 ErrCode : 0
+0x068 Eip : 0x7c90e514 <=== дополнительный признак (валидный адрес)
+0x06c SegCs : 0x1b <=== дополнительный признак
+0x070 EFlags : 0x246 <=== дополнительный признак
+0x074 HardwareEsp : 0xc0f7b0
+0x078 HardwareSegSs : 0x23 <=== дополнительный признак
+0x07c V86Es : 0
+0x080 V86Ds : 0
+0x084 V86Fs : 0
+0x088 V86Gs : 0
Т.к. селекторы известны и постоянны:
#define KGDT_NULL 0
#define KGDT_R0_CODE 8
#define KGDT_R0_DATA 16
#define KGDT_R3_CODE 24
#define KGDT_R3_DATA 32
#define KGDT_TSS 40
#define KGDT_R0_PCR 48
#define KGDT_R3_TEB 56
#define KGDT_VDM_TILE 64
#define KGDT_LDT 72
#define KGDT_DF_TSS 80
#define KGDT_NMI_TSS 88
Это дает нам практически 100%ю гарантию, что найден именно трап фрейм, а не участок памяти с совпавшей TsDbgArgMark.
Метка эта нигде не проверяется(в релизной версии винды) и была введена для отладки.
Для x64 она отсутствует.
Комментариев нет:
Отправить комментарий