вторник, 8 февраля 2011 г.

Как опознать TrapFrame в памяти (х86)

Сделать это довольно просто, т.к. трап фрейм имеет некую метку, по которой его можно опознать в памяти ( ну и дополнительные признаки, чтобы быть полностью уверенным - значение сегментных регистров, 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 она отсутствует.

Комментариев нет:

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