Пожалуйста, обратите внимание, что пользователь заблокирован
В общем пришла мне в голову идея с выполнением шеллкода в ядре через IST. По аналогии с модификацией стека в
Тема создана как обсуждение, если кого-то эта технология заинтересует. Итак начнем с некоторых пояснений.
Вкратце мысленный эксперимент заключался в том, чтобы:
1. Получить примитив записи при помощи эксплойта
2. Записать в KUSER_SHARED_DATA полезную нагрузку в виде ROP-цепочки.
3. Найти таблицу IST в ядре.
4. Запатчить адрес возврата в одной из записей в IST для одного из прерываний на адрес ROP-цепочки
5. Вызвать исключение, стригеррив обработчик прерывания в надежде, что тот будет каким-либо образом использовать подмененные данные и передаст управление на ROP.
Как это устроено в Windows? Судя по описанию, таблица IST находится в TSS. Точнее в структуре _KTSS64.
Непосредственно IST.
По описанию все так. 7 записей, нулевая запись не используется. Следующие четыре стека - это стеки для четырех прерываний.
Т.е. эти стеки предопределены. Каждый из этих стеков имеет права на запись, но когда стал умышленно корраптить их и пытаться вызвать исключение, то ничего не происходило. В ntoskrnl.exe я не нашел обращений к полю KPCR.KtssBase и такое чувство, что этот механизм не используется. Но на каком-то этапе KTSS инициализируется же. В общем здесь пока тупик. Может быть у кого есть идеи на этот счет?
P.S. В исходниках Windows XP я также не нашел обращений к полю Ist.
P.P.S. Нашел обращение к KtssBase в KiExceptionDispatch.
Странно, ибо искал по этому паттерну и получил бублик.
1. https://android.googlesource.com/ke...8f4df9/Documentation/x86/x86_64/kernel-stacks
2. Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 3 (3A, 3B, 3C, & 3D): System Programming Guide
4. https://www.kernel.org/doc/Documentation/x86/kernel-stacks
KTHREAD.StackBase.Тема создана как обсуждение, если кого-то эта технология заинтересует. Итак начнем с некоторых пояснений.
x86_64 also has a feature which is not available on i386, the ability to
automatically switch to a new stack for designated events such as double fault
or NMI, which makes it easier to handle these unusual events on x86_64. This
feature is called the Interrupt Stack Table (IST). There can be up to 7 IST
entries per CPU. The IST code is an index into the Task State Segment (TSS). The
IST entries in the TSS point to dedicated stacks; each stack can be a different
size.
An IST is selected by a non-zero value in the IST field of an interrupt-gate
descriptor. When an interrupt occurs and the hardware loads such a descriptor,
the hardware automatically sets the new stack pointer based on the IST value,
then invokes the interrupt handler[1]
Вкратце мысленный эксперимент заключался в том, чтобы:
1. Получить примитив записи при помощи эксплойта
2. Записать в KUSER_SHARED_DATA полезную нагрузку в виде ROP-цепочки.
3. Найти таблицу IST в ядре.
4. Запатчить адрес возврата в одной из записей в IST для одного из прерываний на адрес ROP-цепочки
5. Вызвать исключение, стригеррив обработчик прерывания в надежде, что тот будет каким-либо образом использовать подмененные данные и передаст управление на ROP.
Как это устроено в Windows? Судя по описанию, таблица IST находится в TSS. Точнее в структуре _KTSS64.
Код:
kd> dx -id 0,0,fffff8050cd48f40 -r1 ((ntkrnlmp!_KTSS64 *)0xfffff8050f9e7000)
((ntkrnlmp!_KTSS64 *)0xfffff8050f9e7000) : 0xfffff8050f9e7000 [Type: _KTSS64 *]
[+0x000] Reserved0 : 0x0 [Type: unsigned long]
[+0x004] Rsp0 : 0xfffff8050f9ea200 [Type: unsigned __int64]
[+0x00c] Rsp1 : 0x0 [Type: unsigned __int64]
[+0x014] Rsp2 : 0x0 [Type: unsigned __int64]
[+0x01c] Ist [Type: unsigned __int64 [8]]
[+0x05c] Reserved1 : 0x0 [Type: unsigned __int64]
[+0x064] Reserved2 : 0x0 [Type: unsigned short]
[+0x066] IoMapBase : 0x68 [Type: unsigned short]
Непосредственно IST.
Код:
kd> dx -id 0,0,fffff8050cd48f40 -r1 (*((ntkrnlmp!unsigned __int64 (*)[8])0xfffff8050f9e701c))
(*((ntkrnlmp!unsigned __int64 (*)[8])0xfffff8050f9e701c)) [Type: unsigned __int64 [8]]
[0] : 0x0 [Type: unsigned __int64]
[1] : 0xfffff8050f9ea3d0 [Type: unsigned __int64]
[2] : 0xfffff8050f9ea5d0 [Type: unsigned __int64]
[3] : 0xfffff8050f9ea7d0 [Type: unsigned __int64]
[4] : 0xfffff8050f9ea9d0 [Type: unsigned __int64]
[5] : 0x0 [Type: unsigned __int64]
[6] : 0x0 [Type: unsigned __int64]
[7] : 0x0 [Type: unsigned __int64]
По описанию все так. 7 записей, нулевая запись не используется. Следующие четыре стека - это стеки для четырех прерываний.
Код:
0: kd> !idt
Dumping IDT: fffff8050f9e6000
01: fffff8050cae5180 nt!KiDebugTrapOrFaultShadow Stack = 0xFFFFF8050F9EA9D0
02: fffff8050cae5240 nt!KiNmiInterruptShadow Stack = 0xFFFFF8050F9EA7D0
08: fffff8050cae5540 nt!KiDoubleFaultAbortShadow Stack = 0xFFFFF8050F9EA3D0
12: fffff8050cae59c0 nt!KiMcheckAbortShadow Stack = 0xFFFFF8050F9EA5D0
Т.е. эти стеки предопределены. Каждый из этих стеков имеет права на запись, но когда стал умышленно корраптить их и пытаться вызвать исключение, то ничего не происходило. В ntoskrnl.exe я не нашел обращений к полю KPCR.KtssBase и такое чувство, что этот механизм не используется. Но на каком-то этапе KTSS инициализируется же. В общем здесь пока тупик. Может быть у кого есть идеи на этот счет?
P.S. В исходниках Windows XP я также не нашел обращений к полю Ist.
P.P.S. Нашел обращение к KtssBase в KiExceptionDispatch.
Странно, ибо искал по этому паттерну и получил бублик.
1. https://android.googlesource.com/ke...8f4df9/Documentation/x86/x86_64/kernel-stacks
2. Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 3 (3A, 3B, 3C, & 3D): System Programming Guide
4. https://www.kernel.org/doc/Documentation/x86/kernel-stacks
Последнее редактирование: