table of Contents
Commissioning and abnormal
Termination of treatmentSEH
Terminator: guaranteed during execution of the program, we will execute the code block _finally
- __ try to ensure that regardless of the manner in which exited, eventually executed __finally
- Can not handle the exception, usually only used to perform cleanup
- __ try: Saved usually requires the code detecting
__ finally: a code is stored will perform
__ leave: the block to exit __try
int main()
{
__try
{
printf("__try { ... }\n");
// 推荐使用 __leave 退出代码块,使用跳转语句会产生多余的函数调用
// __leave 对应实际是一条 jmp 语句,执行更加的迅速
__leave;
// 使用跳转指令退出 __try 块,例如 continue break goto return
goto label_exit;
}
__finally
{
// 通常用于执行某一些特定的清理工作,比如关闭句柄或释放内存
printf("__finally { ... }\n");
// 使用 AbnormalTermination 判断是否是正常退出的
if (AbnormalTermination())
printf("异常退出代码块");
else
printf("正常退出代码块");
}
label_exit:
return 0;
}
Exception HandlingSEH
SEH
Two implementations process can not exist simultaneously, but can be nestedSEH
The handler is stored in the stack, so different thread has its own handler
Exception handler SEH
: it can be used to capture the generated exception, and it executes the corresponding handler
__try
: Is to be protected (potential exception) code
__except
: Storing the filter expression and exception handling block
Save abnormal structural abnormalities environmental information and thread
typedef struct _EXCEPTION_POINTERS { PEXECPTION_RECORD ExceptionRecord; //保存了[异常类型]和[产生异常的指令所在的位置] PCONTEXT ContextRecord; //保存的是异常发生时的寄存器环境,通过修改可以恢复异常 } EXCEPTION_POINTERS, * PEXCEPTION_POINTERS;
Filter function: according to different situations, a different type of return value
DWORD FilterHandler(DWORD ExceptionCode, PEXCEPTION_POINTERS ExceptionInfo) { // 假设产生的是一个整数除零异常,尝试对异常进行处理,并返回继续执行 if (ExceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO) { ExceptionInfo->ContextRecord->Ecx = 1; return EXCEPTION_CONTINUE_EXECUTION; } // 否则其它的异常不做处理,向上传递 return EXCEPTION_CONTINUE_SEARCH; }
Content __except () filter expression can be any form, but its value must be one of the following three, usually a function call
- EXCEPTION_EXECUTE_HANDLER (1): indicates capturing the exception, the code needs to perform exception handling block and continue
- EXCEPTION_CONTINUE_SEARCH (0): represents nothing, to other exception handlers, it usually does not return a process.
- EXCEPTION_CONTINUE_EXECUTION (-1): said they did not believe can not be executed, you need to re-run it again, the only exception handling will be used.
Exception filter function typically requires two function calls
GetExceptionCode()
: The type of acquired abnormality generated, only the filter expression and exception handling block in useGetExceptionInformation()
: Gets the exception of environmental information and thread when an exception is generated, only == filter expressions == use
int main()
{
__try
{
printf("__try{ ... }\n");
//可能会产生异常的指令,只有产生了异常才会执行 __except
__asm mov eax, 100
__asm xor edx, edx
__asm xor ecx, ecx
__asm idiv ecx
printf("异常已经被处理了!\n");
//用来触发内存访问异常
//*(DWORD*)0 = 0;
}
__except (FilterHandler(GetExceptionCode(), GetExceptionInformation()))
{
//只有在异常类型为EXCEPTION_EXCUTE_HANDLER才会执行
printf("__except (EXCEPTION_EXECUTE_HANDLER) { ... }");
}
return 0;
Top-level exception ( UEH
)
- Top-level exception handler (
UEH
): is the last line of defense applications, when allSEH
are not able to handle the exception, it will be executedUEH
Error information (type of exception thread context and memory) are commonly used to perform a memory dump operation, the collected submitted to the serverUEH
Within the debugger in 64-bit operating system is never executed == == requires a separate operation.
Top custom exception handler, even if no custom, there will be a default handler, and only one, type, and its return value SEH
are the same, but the lack of EXCEPTION_EXECUTE_HANDLER
LONG WINAPI TopLevelExceptionHandler(EXCEPTION_POINTERS* ExceptionInfo)
{
printf("TopLevelExceptionHandler(): %08X\n", ExceptionInfo->ExceptionRecord->ExceptionCode);
// 假设产生的是一个整数除零异常,尝试对异常进行处理,并返回继续执行
if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO)
{
ExceptionInfo->ContextRecord->Ecx = 1;
return EXCEPTION_CONTINUE_EXECUTION; // -1
}
// 否则其它的异常不做处理,向上传递
return EXCEPTION_CONTINUE_SEARCH; // 0
}
int main()
{
// 顶层异常处理的设置依赖于一个函数
SetUnhandledExceptionFilter(TopLevelExceptionHandler);
__try
{
// 产生除零异常
__asm mov eax, 100
__asm xor edx, edx
__asm xor ecx, ecx
__asm idiv ecx
}
__except (EXCEPTION_CONTINUE_SEARCH)
{
// 这里永远不会执行,因为不是 EXCEPTION_EXECUTE_HANDLER(1)
printf("__except (EXCEPTION_CONTINUE_SEARCH)\n");
}
printf("异常处理成功!");
system("pause");
return 0;
}
Vectored exception handler ( VEH
)
- A mechanism for user-level support in
SEH
the execution before, stored in a global list, the entire process can be accessed. - Custom
VEH
exception handler, its execution is locatedSEH
before, ifVEH
not dealt with successfully, will be calledSEH
LONG WINAPI VectoredExceptionHandler(EXCEPTION_POINTERS* ExceptionInfo)
{
printf("VectoredExceptionHandler(): %08X\n", ExceptionInfo->ExceptionRecord->ExceptionCode);
// 假设产生的是一个整数除零异常,尝试对异常进行处理,并返回继续执行
if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO)
{
ExceptionInfo->ContextRecord->Ecx = 1;
return EXCEPTION_CONTINUE_EXECUTION; // 0
}
// 否则其它的异常不做处理,向上传递
return EXCEPTION_CONTINUE_SEARCH; // 1
}
int main()
{
// 设置一个向量化异常处理函数(VEH),参数一表示添加到异常处理函数链表的位置
AddVectoredExceptionHandler(TRUE, VectoredExceptionHandler);
__try
{
// 产生除零异常
__asm mov eax, 100
__asm xor edx, edx
__asm xor ecx, ecx
__asm idiv ecx
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
// 这里永远不会执行,因为不是 EXCEPTION_EXECUTE_HANDLER(1)
printf("__except (EXCEPTION_EXECUTE_HANDLER)\n");
}
printf("异常处理成功!");
system("pause");
return 0;
}
Vectored exception handlerVCH
Vectored exception handler (
VCH
): User A mechanism support layer, the last to be executed- Stored in a global list, the entire process can access to, and
VEH
at the same table, but different flag VCH
Only in the case of the exception it is handled, the last to be executedVEH
->SEH
->UEH
->VCH
- Stored in a global list, the entire process can access to, and
Custom
UEH
Functions inSEH
after executionLONG WINAPI TopLevelExceptionHandler(EXCEPTION_POINTERS* ExceptionInfo) { printf("TopLevelExceptionHandler(): %08X\n", ExceptionInfo->ExceptionRecord->ExceptionCode); // 假设产生的是一个整数除零异常,尝试对异常进行处理,并返回继续执行 if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO) { ExceptionInfo->ContextRecord->Ecx = 1; return EXCEPTION_CONTINUE_EXECUTION; } // 否则其它的异常不做处理,向上传递 return EXCEPTION_CONTINUE_SEARCH; }
Custom
VEH
exception handler, his execution is locatedSEH
before, ifVEH
not dealt with successfully, will be calledSEH
LONG WINAPI VectoredExceptionHandler(EXCEPTION_POINTERS* ExceptionInfo) { printf("VectoredExceptionHandler(): %08X\n", ExceptionInfo->ExceptionRecord->ExceptionCode); // 否则其它的异常不做处理,向上传递 return EXCEPTION_CONTINUE_SEARCH; }
Custom
VCH
exception handler, the only exception handling in case of success, the final will be calledLONG WINAPI VectoredContinueHandler(EXCEPTION_POINTERS* ExceptionInfo) { printf("VectoredContinueHandler(): %08X\n", ExceptionInfo->ExceptionRecord->ExceptionCode); return EXCEPTION_CONTINUE_SEARCH; }
Filter function: according to different situations, the return value of different types of
DWORD FilterHandler(DWORD ExceptionCode, PEXCEPTION_POINTERS ExceptionInfo) { printf("FilterHandler(): %08X\n", ExceptionInfo->ExceptionRecord->ExceptionCode); // 否则其它的异常不做处理,向上传递 return EXCEPTION_CONTINUE_SEARCH; }
int main()
{
// 设置一个向量化异常处理函数(VEH)
AddVectoredExceptionHandler(TRUE, VectoredExceptionHandler);
// 设置一个向量化异常处理函数(VCH)
AddVectoredContinueHandler(TRUE, VectoredContinueHandler);
// UEH 处理函数
SetUnhandledExceptionFilter(TopLevelExceptionHandler);
__try
{
// 产生除零异常
__asm mov eax, 100
__asm xor edx, edx
__asm xor ecx, ecx
__asm idiv ecx
}
__except (FilterHandler(GetExceptionCode(), GetExceptionInformation()))
{
// 这里永远不会执行,因为不是 EXCEPTION_EXECUTE_HANDLER(1)
printf("__except (EXCEPTION_EXECUTE_HANDLER)\n");
}
printf("异常处理成功!");
system("pause");
return 0;
}
SEH
Principle analysis
SEH
Stored in aTEB
structure where the offset is 0, is a linked list,SEH
the list canFS : [0]
find such an addressTEB
You canFS:[0X18]
find such an address.try except
In principle it isSEH
to add a new node in the list
// 自定义的SEH 函数
EXCEPTION_DISPOSITION NTAPI ExceptionHandler(
struct _EXCEPTION_RECORD* ExceptionRecord,
PVOID EstablisherFrame,
struct _CONTEXT* ContextRecord,
PVOID DispatcherContext)
{
return ExceptionContinueSearch;
}
//遍历当前线程中的所有 SEH函数
void GetThreadList()
{
//1. 获取当前 SEH 链表的头节点
PEXCEPTION_REGISTRATION_RECORD ExceptionList = nullptr;
__asm
{
push FS : [0]
POP ExceptionList
}
//遍历 SEH 中的所有函数
while (ExceptionList != (PEXCEPTION_REGISTRATION_RECORD)-1)
{
//输出当前层,对应的处理函数
printf("0x%08X\n", ExceptionList->Handler);
//将指针指向下一个节点
ExceptionList = ExceptionList->Next;
}
printf("\n");
}
int main()
{
// 0 保存 SEH 头节点,主要用于恢复
PEXCEPTION_REGISTRATION_RECORD ExceptionList = nullptr;
__asm
{
push FS : [0];
pop ExceptionList;
}
// 1 添加自定义 SEH 函数之前的 SEH 链
GetThreadList();
// 2 添加自定义 SEH 函数之前的 SEH 链
__asm
{
push ExceptionHandler
push fs : [0]
mov fs : [0], esp
}
// 3 添加自定义 SEH 函数之后的 SEH 链
GetThreadList();
// 4 恢复旧的 SEH 头节点
__asm
{
add esp, 0x08
mov eax, ExceptionList
mov fs : [0], eax
}
// 5 应该和以前的节点是相同的
GetThreadList();
return 0;
}
Abnormal distribution process
- Processing
int3
function abnormality isKitTrap03
- Exception handling starts at the beginning, the first structure
TRAP_FRAME
when the frame structure of the trap, the trap frame refers to a structure used to save the system calls, interrupts, register on-site when an exception occurs, the user space to facilitate future back / back to the interrupted, recovery the values of those registers continue. - Notes that
KitTrap03
actually callsCommonDispatchException
supplement
IDT:
Interrupt descriptor table Interrupt Descriptor Table
( )
CPU
Privilege Level R0
- R3
a total of three levels, the operating system execution state into the kernel mode and user mode , the CPU is set at the particular stage of kernel mode R0
, in particular for the subscriber station counter stageR3