По идее конечно, но теоритически все таки возможно его убрать (точнее не саму процедуру обработчика, а элемент в списке, который кажет на процедуру).Mark Russinovich писал(а):И, по идее, он должен работать всегда.
Ничего относящегося к SEH в ядре вроде как и нет
Сто процентов даю, что эта самая бегалка (RtlUnwind) проходит через шлюз int 2E прямо в ядро...бегалка по списку обработчиков лежит в ntdll
hCORe писал(а):Я не про юзермод, а насчет Твистера не уверен
Twister писал(а):Про ring 3 ни кто и не говорил...
Matt Pietrek писал(а):в Intel-архитектуре возникновение исключения вызывает передачу управления по вектору в обработчик находящийся в нулевом кольце защиты, т.е. в обработчик режима ядра (kernel mode). Обработчик определен соответствующим исключению элементом таблицы дескрипторов прерываний (она же - Interrupt Descriptor Table, или просто - IDT).
Twister писал(а):hCORe писал(а):Я не про юзермод, а насчет Твистера не уверенTwister писал(а):Про ring 3 ни кто и не говорил...
Тогда почему всё это в форуме про VB?
Это если файл открыть через обычный Open? А если через АПИ?Оказывается, указатель на таблицу открытых файлов рантаймом хранится в кадре SEH
Twister писал(а):Тогда почему всё это в форуме про VB?
Потому что это мой любимый форум, хотя на WASMе я уже задал этот вопрос.
В принципе да, согласен...Специально для таких случаев предусмотрен Трёп
Twister писал(а):Кстати, основываясь на статье Мэта Питрека и на коментариях к ней, я делаю вывод, что код, который управляет SEH лежит именно в ядре... Да и чисто по логике вещей он там и должен находиться...Сто процентов даю, что эта самая бегалка (RtlUnwind) проходит через шлюз int 2E прямо в ядро...бегалка по списку обработчиков лежит в ntdll
void _RtlUnwind( PEXCEPTION_REGISTRATION pRegistrationFrame,
PVOID returnAddr, // Not used! (At least on i386)
PEXCEPTION_RECORD pExcptRec,
DWORD _eax_value )
{
DWORD stackUserBase;
DWORD stackUserTop;
PEXCEPTION_RECORD pExcptRec;
EXCEPTION_RECORD exceptRec;
CONTEXT context;
// Get stack boundaries from FS:[4] and FS:[8]
RtlpGetStackLimits( &stackUserBase, &stackUserTop );
if ( 0 == pExcptRec ) // The normal case
{
pExcptRec = &excptRec;
pExcptRec->ExceptionFlags = 0;
pExcptRec->ExceptionCode = STATUS_UNWIND;
pExcptRec->ExceptionRecord = 0;
// Get return address off the stack
pExcptRec->ExceptionAddress = RtlpGetReturnAddress();
pExcptRec->ExceptionInformation[0] = 0;
}
if ( pRegistrationFrame )
pExcptRec->ExceptionFlags |= EXCEPTION_UNWINDING;
else
pExcptRec->ExceptionFlags|=(EXCEPTION_UNWINDING|EXCEPTION_EXIT_UNWIND);
context.ContextFlags =
(CONTEXT_i486 | CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS);
RtlpCaptureContext( &context );
context.Esp += 0x10;
context.Eax = _eax_value;
PEXCEPTION_REGISTRATION pExcptRegHead;
pExcptRegHead = RtlpGetRegistrationHead(); // Retrieve FS:[0]
// Begin traversing the list of EXCEPTION_REGISTRATION
while ( -1 != pExcptRegHead )
{
EXCEPTION_RECORD excptRec2;
if ( pExcptRegHead == pRegistrationFrame )
{
_NtContinue( &context, 0 );
}
else
{
// If there's an exception frame, but it's lower on the stack
// then the head of the exception list, something's wrong!
if ( pRegistrationFrame && (pRegistrationFrame <= pExcptRegHead) )
{
// Generate an exception to bail out
excptRec2.ExceptionRecord = pExcptRec;
excptRec2.NumberParameters = 0;
excptRec2.ExceptionCode = STATUS_INVALID_UNWIND_TARGET;
excptRec2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
_RtlRaiseException( &exceptRec2 );
}
}
PVOID pStack = pExcptRegHead + 8; // 8==sizeof(EXCEPTION_REGISTRATION)
if ( (stackUserBase <= pExcptRegHead ) // Make sure that
&& (stackUserTop >= pStack ) // pExcptRegHead is in
&& (0 == (pExcptRegHead & 3)) ) // range, and a multiple
{ // of 4 (i.e., sane)
DWORD pNewRegistHead;
DWORD retValue;
retValue = RtlpExecutehandlerForUnwind(
pExcptRec, pExcptRegHead, &context,
&pNewRegistHead, pExceptRegHead->handler );
if ( retValue != DISPOSITION_CONTINUE_SEARCH )
{
if ( retValue != DISPOSITION_COLLIDED_UNWIND )
{
excptRec2.ExceptionRecord = pExcptRec;
excptRec2.NumberParameters = 0;
excptRec2.ExceptionCode = STATUS_INVALID_DISPOSITION;
excptRec2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
RtlRaiseException( &excptRec2 );
}
else
pExcptRegHead = pNewRegistHead;
}
PEXCEPTION_REGISTRATION pCurrExcptReg = pExcptRegHead;
pExcptRegHead = pExcptRegHead->prev;
RtlpUnlinkHandler( pCurrExcptReg );
}
else // The stack looks goofy! Raise an exception to bail out
{
excptRec2.ExceptionRecord = pExcptRec;
excptRec2.NumberParameters = 0;
excptRec2.ExceptionCode = STATUS_BAD_STACK;
excptRec2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
RtlRaiseException( &excptRec2 );
}
}
// If we get here, we reached the end of the EXCEPTION_REGISTRATION list.
// This shouldn't happen normally.
if ( -1 == pRegistrationFrame )
NtContinue( &context, 0 );
else
NtRaiseException( pExcptRec, &context, 0 );
}
Matt Pietrek писал(а):в Intel-архитектуре возникновение исключения вызывает передачу управления по вектору в обработчик находящийся в нулевом кольце защиты, т.е. в обработчик режима ядра (kernel mode). Обработчик определен соответствующим исключению элементом таблицы дескрипторов прерываний (она же - Interrupt Descriptor Table, или просто - IDT).
Если исключение произошло в пользовательском режиме
Вызвать KeUserExceptionDispatcher
' Происходит переход в юзермод, и выполняется ntdll!KiUserExceptionDispatcher.
' Он сам пройдётся по обработчикам и сделает, что ему надо.
Иначе
Вызвать RtlDispatchException
' Он сам пройдётся по обработчикам и сделает, что ему надо.
' Если никто не согласится обработать исключение, управление вернётся сюда
KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED)
ms-rem писал(а):Последний из обработчиков (который ставит система) прибивает процесс. Если не один обработчик вобще не будет найден, то снова возникнет исключениие, и опять будет поиск обработчика... Процесс войдет в бесконечный цикл и будет 100% грузить процессор.
Twister писал(а):А вот и правильный ответ (надеюсь).ms-rem писал(а):Последний из обработчиков (который ставит система) прибивает процесс. Если не один обработчик вобще не будет найден, то снова возникнет исключениие, и опять будет поиск обработчика... Процесс войдет в бесконечный цикл и будет 100% грузить процессор.
Twister писал(а):Нет, не такой уж авторитет, но человек, к которому лично я прислушиваюсь (так же как к GSerg-у или к тебе). Насколько я понял - он имел ввиду юзермод.
xor eax,eax
mov dword ptr fs:[eax], -1
mov byte ptr [eax], 0
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 103