ANTICHAT.XYZ    VIDEO.ANTICHAT.XYZ    НОВЫЕ СООБЩЕНИЯ    ФОРУМ  
Баннер 1   Баннер 2
Antichat снова доступен.
Форум Antichat (Античат) возвращается и снова открыт для пользователей. Здесь обсуждаются безопасность, программирование, технологии и многое другое. Сообщество снова собирается вместе.
Новый адрес: forum.antichat.xyz
Вернуться   Форум АНТИЧАТ > ИНФО > Статьи > Авторские статьи
   
 
 
Опции темы Поиск в этой теме Опции просмотра

Структурная обработка BSoD'а
  #1  
Старый 03.03.2007, 02:05
_Great_
Флудер
Регистрация: 27.12.2005
Сообщений: 2,372
Провел на форуме:
5339610

Репутация: 4360


Отправить сообщение для _Great_ с помощью ICQ
По умолчанию Структурная обработка BSoD'а

Article: Структурная обработка BSoD'а
Author: Great
ICQ #: 893-894
Date: 03.03.2007
Lang: C/C++ kernel & user mode

Трудно отлаживать драйвера ядра в Windows отчасти потому, что большинство ошибок ведет к краху системы, и даже отладчик ядра с этим мало что может сделать. Если мы попробуем, например, скопировать одну строку в другую, не выделив места под нее, нас не спасет даже обработка исключений - в любом случае будет синий экран смерти UNEXPECTED_KERNEL_MODE_TRAP из-за возникшей ловушки General Protection Fault.
В одной из предыдущих статей я расписал, как можно заставить систему игнорировать ошибки. Соглашусь, что этот метод весьма "кривой", потому что не позволяет даже обработать ее как-либо. Мы можем только наблюдать окошко с ошибкой.
В этот раз я предложу более удобный метод. Попробуем сделать обработку BSoD такой же, как и, например, обработку исключений. То есть можно поставить свой обработчик на BSoD, который на некотором участке небезопасного кода будет отслеживать возникновение ошибки. Если возникла ошибка, которую он обрабатывает, то он производит соответствующие действия, а если нет - передает управление на другие обработчики. Если никакие обработчики не обработали ошибку, показывается синий экран смерти. Метод в точности копирует структурную обработку исключений (Structured Exception Handling, SEH). Точно так же выбирается участок кода, внутри которого все ошибки будут ловиться нашими обработчиками.

Со стороны программиста-пользователя, это будет выглядеть так:

PBUGCHECK_FILTER SetUnhandledBugCheckFilter(PBUGCHECK_FILTER NewFilter, BOOLEAN bSet)
Эта функция добавляет на вершину стека обработчиков или удаляет из стека указанный обработчик (действие задается флагом bSet). При добавлении она возвращает обработчик, который был на вершине стека до этого. NewFilter указывает на новый обработчик - stdcall-функцию, которая принимает параметр BUGCHECK_INFO* и возвращает ULONG. Структура BUGCHECK_INFO содержит параметры синего экрана и описывается следующим образом:
Код:
	typedef struct _BUGCHECK_INFO
	{
		ULONG BugCheckCode;
		ULONG BugCheckParameters[4];
	} BUGCHECK_INFO, *PBUGCHECK_INFO;
Возвращаемое значение фильтра может быть либо BUGCHECK_CONTINUE_SEARCH (0) для продолжения поиска подходящего фильтра, либо BUGCHECK_EXECUTE_HANDLER (1) для прекращения поиска. Если фильтр возвращает BUGCHECK_EXECUTE_HANDLER, генерируется специальное исключение с кодом STATUS_BUGCHECK (0xC0FF0001), которое может быть обработано обычным образом через SEH. Таким образом, возникновение фатальной ошибки сводится к генерации исключения.

Рассмотрим пример. Напишем два фильтра:
Код:
ULONG NTAPI UnhandledBugcheckFilter2(PBUGCHECK_INFO BugcheckInfo)
{
	DPRINT("In UnhandledBugcheckFilter2()");
	return BUGCHECK_CONTINUE_SEARCH;
}

ULONG NTAPI UnhandledBugcheckFilter(PBUGCHECK_INFO BugcheckInfo)
{
	DPRINT("In UnhandledBugcheckFilter()");
	if( BugcheckInfo->BugCheckCode == MANUALLY_INITIATED_CRASH )
		return BUGCHECK_EXECUTE_HANDLER;
	return BUGCHECK_CONTINUE_SEARCH;
}
UnhandledBugcheckFilter2 всегда возвращает BUGCHECK_CONTINUE_SEARCH, инициируя продолждение поиска фильтра, а UnhandledBugcheckFilter возвращает BUGCHECK_EXECUTE_HANDLER, когда багчек-код равен MANUALLY_INITIATED_CRASH. Таким образом, если мы выполним такой код:
Код:
	SetUnhandledBugCheckFilter( UnhandledBugcheckFilter, TRUE );
	SetUnhandledBugCheckFilter( UnhandledBugcheckFilter2, TRUE );
произойдет следующее - при возникновении ошибки с кодом MANUALLY_INITIATED_CRASH сгенерируется исключение STATUS_BUGCHECK, при всех остальных ошибках вызовется синий экран как обычно. Попробуем перехватить это исключение:
Код:
	__try
	{
		DPRINT("Trying...");
		KeBugCheckEx( MANUALLY_INITIATED_CRASH, 0, 0, 0, 0 );
		DPRINT("Unsuccessful =(");
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
		// We should catch STATUS_BUGCHECK
		DPRINT("Catch: %08x", GetExceptionCode());
	}
Таким образом, при вызове KeBugCheckEx( MANUALLY_INITIATED_CRASH, 0, 0, 0, 0 ) на самом деле не будет никакого бсода, сработают установленные фильтры, сгенерируется исключение STATUS_BUGCHECK и сработает обработчик __except.
Цитата:
Trying...[*] KiProcessBugCheck call - FATAL SYSTEM ERROR. BugCheck code 000000e2
In UnhandledBugcheckFilter2()
In UnhandledBugcheckFilter()
Catch: c0ff0001
Как видно из отладочного вывода DbgPrint, все успешно сработало. Фильтр UnhandledBugcheckFilter2 пропустил бсод, а UnhandledBugcheckFilter заблокировал его.
Таким образом, получается удобный механизм для отладки и выполнения заведомо небезопасных частей кода, которые могут повлечь генерацию BSoD'а.

Реализация. С технической точки зрения, тут все просто. Ставим сплайсингом хук на KeBugCheckEx (Windows 2000) или KeBugCheck2 (Windows XP/2k3), а в обработчике перебираем стек фильтров. Примерная реализация выглядит так:
Код:
typedef struct _BUGCHECK_INFO
{
	ULONG BugCheckCode;
	ULONG BugCheckParameters[4];

} BUGCHECK_INFO, *PBUGCHECK_INFO;

#define BUGCHECK_CONTINUE_SEARCH 0
#define BUGCHECK_EXECUTE_HANDLER 1
#define MAX_BUGCHECK_FILTERS 1024
#define STATUS_BUGCHECK 0xC0FF0001L

typedef ULONG (NTAPI *PBUGCHECK_FILTER)(PBUGCHECK_INFO);

PBUGCHECK_FILTER BugCheckFilters[MAX_BUGCHECK_FILTERS] = {0};
ULONG CurrentBugCheckFilter = 0;

//
// Main bug check processing routine
//

void KiProcessBugCheck(
					 IN DWORD iBugCheckCode,
					 IN DWORD iBugCheckParameter1,
					 IN DWORD iBugCheckParameter2,
					 IN DWORD iBugCheckParameter3,
					 IN DWORD iBugCheckParameter4,
					 IN PVOID iTrapFrame
					 )
{
	// Log error
	DPRINT("[*] KiProcessBugCheck call - FATAL SYSTEM ERROR. BugCheck code %08x", iBugCheckCode);

	if(CurrentBugCheckFilter > 0)
	{
		__try
		{
			// Заполняем структуру
			BUGCHECK_INFO BugCheckInfo = {
				iBugCheckCode,
				{
					iBugCheckParameter1,
					iBugCheckParameter2,
					iBugCheckParameter3,
					iBugCheckParameter4
				}
			};

			// Перебираем обработчики
			for(int i=CurrentBugCheckFilter-1;i>=0;i--)
			{
				if(!BugCheckFilters[i])
					continue;

				ULONG status = BugCheckFilters[i]( &BugCheckInfo ); // вызов

				if( status == BUGCHECK_CONTINUE_SEARCH )
					continue;
				if( status == BUGCHECK_EXECUTE_HANDLER )
					ExRaiseStatus( STATUS_BUGCHECK ); // выбрасываем исключение STATUS_BUGCHECK
			}
		}
		__except( (GetExceptionCode()==STATUS_BUGCHECK)?EXCEPTION_CONTINUE_SEARCH:EXCEPTION_EXECUTE_HANDLER )
		{
			DPRINT("Exception while enumerating handlers: %08x", GetExceptionCode());
		}
	}

	// Если мы все-таки сюда добрались, значит все фильтры пропустили багчек. Уроним систему
	NTSTATUS UnsetHooks();
	if( UnsetHooks() == STATUS_SUCCESS )
		KeBugCheckEx(
			iBugCheckCode,
			iBugCheckParameter1,
			iBugCheckParameter2,
			iBugCheckParameter3,
			iBugCheckParameter4
			);
	
	// Что-то пошло не так и уронить систему не вышло. Просто завесим
	DPRINT("Cannot unset hooks, hang system");
	
	KfRaiseIrql( HIGH_LEVEL );
	
	for(;;) {
	}
}
Полный код тестового драйвера можно обнаружить тут: http://gr8.cih.ms/bsodhandling.cpp
(Большая часть кода взята из моей статьи "Жизнь после смерти" и должна быть уже знакома )

Вот, собственно, и все. Пока)
 
Ответить с цитированием
 



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
[Статья] Обработка ошибок в Php Ch3ck PHP, PERL, MySQL, JavaScript 4 09.07.2006 21:50
обработка нового поста в форуме Дикс PHP, PERL, MySQL, JavaScript 18 21.05.2006 21:11
Некорректная обработка в Ie форм с полями, содержащими экзотические символы k00p3r Чужие Статьи 0 10.06.2005 09:18



Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT.XYZ