逆向分析windows用户层异常分发源码
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了逆向分析windows用户层异常分发源码相关的知识,希望对你有一定的参考价值。
#define DISPOSITION_DISMISS 0
#define DISPOSITION_CONTINUE_SEARCH 1
#define DISPOSITION_NESTED_EXCEPTION 2
#define DISPOSITION_COLLIDED_UNWIND 3
#define EH_NONCONTINUABLE 0x01
#define EH_UNWINDING 0x02
#define EH_EXIT_UNWIND 0x04
#define EH_STACK_INVALID 0x08
#define EH_NESTED_CALL 0x10
#define STATUS_NONCONTINUABLE_EXCEPTION 0xC0000025
#define STATUS_INVALID_DISPOSITION 0xC0000026
#define EXCEPTION_CONTINUE_EXECUTION -1
#define PAGE_EXEC_MASK (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY)
typedef struct _EXCEPTION_RECORD {
DWORD ExceptionCode;
DWORD ExceptionFlags;
struct _EXCEPTION_RECORD *ExceptionRecord; // var_CW
PVOID ExceptionAddress;
DWORD NumberParameters;
ULONG_PTR ExceptionInformation[15];
} EXCEPTION_RECORD, *PEXCEPTION_RECORD;
typedef struct _EXCEPTION_REGISTRATION
{
struct _EXCEPTION_REGISTRATION* pNext;
PEXCEPTION_HANDLER handler;
} EXCEPTION_REGISTRATION, *PEXCEPTION_REGISTRATION;
typedef struct _VECTORED_EXCEPTION_NODE {
LIST_ENTRY ListEntry;
PVECTORED_EXCEPTION_HANDLER handler;
} VECTORED_EXCEPTION_NODE, *PVECTORED_EXCEPTION_NODE;
typedef enum _EXCEPTION_DISPOSITION
{
ExceptionContinueExecution,
ExceptionContinueSearch,
ExceptionNestedException,
ExceptionCollidedUnwind
} EXCEPTION_DISPOSITION;
/* 7C97E3FA */
UCHAR LogExceptions = 0;
/* 7C97E3C0 */
LIST_ENTRY RtlpCalloutEntryList;
/* 7C9805E0 */
RTL_CRITICAL_SECTION RtlpCalloutEntryLock;
RTL_CRITICAL_SECTION LdrpLoaderLock;
/* 7C90E47C */
/*
* 用户层的异常派发源头
*/
VOID KiUserExceptionDispatcher(__in PCONTEXT ContextRecord,
__in PEXCEPTION_RECORD ExceptionRecord)
{
NTSTATUS Status;
// 调用RtlDispatchException函数去派发异常.
if (RtlDispatchException(ContextRecord, ExceptionRecord)) {
/* 7C90E48E modify the execution context of the current thread to whatever the chosen exception handler gives us */
// 结束异常分发
Status = ZwContinue(ContextRecord, 0);
}
else {
/* 7C90E49A no exception handler found so re-raise the exception for a debugger or the NT exception handler */
// 在此触发一个异常, 并触发时最后一个参数传FALSE,表明这是一个第二次触发的异常.
Status = ZwRaiseException(ExceptionRecord, ContextRecord, FALSE);
}
/* 7C90E4A5 build an exception record with 20 bytes on the stack, second chance exception? */
PEXCEPTION_RECORD exception = (PEXCEPTION_RECORD) alloca(0x14);
exception->ExceptionCode = Status;
exception->ExceptionFlags = 1;
exception->ExceptionRecord = ContextRecord;
exception->NumberParameters = 1;
return RtlRaiseException(exception);
}
LPVOID RtlpGetRegistrationHead()
{
_asm mov eax , fs:[0]
_asm ret
}
/* 7C92A970 如果异常被处理返回TRUE */
BOOLEAN RtlDispatchException(PCONTEXT ContextRecord, PEXCEPTION_RECORD ExceptionRecord) {
BOOLEAN ret = 0;
LPVOID StackBase, StackLimit;
PEXCEPTION_REGISTRATION head;
DWORD kProcess_Flags;
DWORD dispatch, highest;
EXCEPTION_RECORD exRec;
// 先将异常交给VEH处理. 如果能够处理,则结束异常分发
if (RtlCallVectoredExceptionHandlers(ExceptionRecord, ContextRecord)) {
/* 7C95010A */
ret = 1;
}
else { /* 否则交给SEH处理 */
/* 7C92A991 */
RtlpGetStackLimits(&StackLimit, &StackBase);
// 获取SEH链表头节点
/* 7C92A99F */
head = (PEXCEPTION_REGISTRATION)RtlpGetRegistrationHead();
highest = 0;
while (head != (PEXCEPTION_REGISTRATION) -1) {
// 判断获取出来的节点的地址是否正确
if (head < StackLimit || head + sizeof(EXCEPTION_REGISTRATION) > StackBase || head & 3) {
ExceptionRecord->ExceptionFlags |= EH_STACK_INVALID;
goto exit;
}
// 判断异常处理函数的地址是否正确
if (head->handler >= StackLimit && head->handler < StackBase) {
ExceptionRecord->ExceptionFlags |= EH_STACK_INVALID;
goto exit;
}
// 判断异常处理函数是否为有效处理函数
if (!RtlIsValidHandler(head->handler)) {
/* 7C92A336 */
ExceptionRecord->ExceptionFlags |= EH_STACK_INVALID;
goto exit;
}
else if (LogExceptions) {
/* 7C950113 */
RtlpLogExceptionHandler(ContextRecord, ExceptionRecord, 0, head, 0x10);
}
// 执行SEH的 _except_handler4()
hret = RtlpExecuteHandlerForException(ContextRecord,
head,
ExceptionRecord,
&dispatch,
head->handler);
if (LogExceptions) {
/* 7C950129 there is a second parameter to this function that I don‘t understand yet */
RtlpLogLastExceptionDisposition(highest, hret);
}
/* 7C92AA1E */
if (head == NULL) {
ExceptionRecord->ExceptionFlags &= ~EH_NESTED_CALL;
}
/* 7C92AA27 */
if (hret == DISPOSITION_DISMISS) {
if (ExceptionRecord->ExceptionFlags & EH_NONCONTINUABLE) {
/* 7C950181 */
exRec.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION;
exRec.ExceptionFlags = EH_NONCONTINUABLE;
exRec.ExceptionRecord = ExceptionRecord;
exRec.NumberParameters = 0;
RtlRaiseException(&exRec);
/* 7C92A31C a little fudging with this block */
if (ExceptionRecord->ExceptionFlags & EH_STACK_INVALID) {
goto exit;
}
}
else {
/* 77EDBD64 */
ret = 1;
break;
}
}
// 如果SEH过滤函数返回的是搜索其它过滤函数处理
else if (hret == DISPOSITION_CONTINUE_SEARCH) {
/* 7C92A31C a little fudging with this block */
if (ExceptionRecord->ExceptionFlags & EH_STACK_INVALID) {
goto exit;
}
}
else if (hret == DISPOSITION_NESTED_EXCEPTION) {
/* 7C950169 */
ExceptionRecord->ExceptionFlags |= EH_NESTED_CALL;
if (dispatch > highest) {
highest = dispatch;
}
}
else {
/* 7C950147 */
exRec.ExceptionCode = STATUS_INVALID_DISPOSITION;
exRec.ExceptionFlags = EH_NONCONTINUABLE;
exRec.ExceptionRecord = ExceptionRecord;
exRec.NumberParameters = 0;
RtlRaiseException(&exRec);
}
/* 7C92A326 */
head = head->pNext;
}
}
exit:
/* 7C92AA43 */
return ret;
}
/* 7C92A934 */
// 调用VEH函数
BOOLEAN RtlCallVectoredExceptionHandlers(PEXCEPTION_RECORD ExceptionRecord, PCONTEXT ContextRecord) {
BOOLEAN ret = FALSE;
struct {
PEXCEPTION_RECORD eRec;
PCONTEXT cRec;
} Rec;
PVECTORED_EXCEPTION_NODE veh;
PVECTORED_EXCEPTION_HANDLER handler;
DWORD disposition
if (RtlpCalloutEntryList.Flink == &RtlpCalloutEntryList) {
return FALSE;
}
eRec = ExceptionRecord;
cRec = ExceptionRecord;
// 进入临界区
RtlEnterCriticalSection(&RtlpCalloutEntryLock);
// 开始遍历VEH的双向链表
for (veh = (PVECTORED_EXCEPTION_NODE) RtlpCalloutEntryList.Flink);
veh != (PVECTORED_EXCEPTION_NODE) RtlpCalloutEntryList;
veh = (PVECTORED_EXCEPTION_NODE) veh->ListEntry.Flink) {
// 解密处理函数地址
handler = RtlDecodePointer(veh->handler);
// 调用处理函数
disposition = handler(&Rec);
// 判断处理函数是否处理了异常.如果是则结束循环.
// 如果没有,则继续找到下一个处理函数.
if (disposition == EXCEPTION_CONTINUE_EXECUTION) {
// 将返回值设置为TRUE.
ret = 1;
break;
}
}
// 离开临界区
RtlLeaveCriticalSection(&RtlpCalloutEntryLock);
return ret;
}
/* 7C9033DC */
VOID RtlpGetStackLimits(LPVOID **StackLimit, LPVOID **StackBase) {
PTEB teb = _TEB; // fs:18h
*StackLimit = teb->NtTib->StackLimit;
*StackBase = teb->NtTib->StackBase;
return;
}
/* 7C92AA50 */
BOOLEAN RtlIsValidHandler(PEXCEPTION_HANDLER handler) {
DWORD table_sz;
LPVOID safeseh_table, base_addr;
DWORD ret, result_len, exec_flags, high, low;
MEMORY_BASIC_INFORMATION mbi;
safeseh_table = RtlLookupFunctionTable(handler, &base_addr, &table_sz);
if (safeseh_table == NULL || table_sz == 0) {
/* 7C9500D1 ProcessExecuteFlags*/
if (ZwQueryInformationProcess(INVALID_HANDLE_VALUE, 22, &exec_flags, 4, NULL) >= 0) {
/* 7C92CF94 0x10 = ExecuteDispatchEnable */
if (!(exec_flags & 0x10)) {
return 1;
}
}
/* 7C935E8E */
if (NtQueryVirtualMemory(INVALID_HANDLE_VALUE, handler, NULL, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &result_len) < 0) {
return 1;
}
/* 7C935EA9 */
if (!(mbi.Protect & PAGE_EXEC_MASK)) {
RtlInvalidHandlerDetected(handler, -1, -1);
return 0;
}
else if (mbi.Type != SEC_IMAGE) {
return 1;
}
RtlCaptureImageExceptionValues(mbi.AllocationBase, &safeseh_table, &table_sz);
/* 7C935ED0 */
if (var_10 == NULL || table_sz == 0) {
return 1;
}
return 0;
}
else if (safeseh_table == (LPVOID) -1 && table_sz == -1) {
return 0;
}
/* 7C9500A6 */
if (table_sz < 0) {
RtlInvalidHandlerDetected(handler, safeseh_table, table_sz);
return 0;
}
rel_addr = handler - base_addr;
high = table_sz;
low = 0;
/* 7C9500B1 binary search through SafeSEH table */
do {
idx = (high + low) / 2;
if (rel_addr < safeseh_table[idx]) {
if (idx == 0) {
RtlInvalidHandlerDetected(handler, safeseh_table, table_sz);
return 0;
}
high = idx - 1;
if (high < low) {
RtlInvalidHandlerDetected(handler, safeseh_table, table_sz);
return 0;
}
}
else if (rel_addr > safeseh_table[idx]) {
low = idx + 1;
if (high < low) {
RtlInvalidHandlerDetected(handler, safeseh_table, table_sz);
return 0;
}
}
else {
break;
}
} while(1);
return 1;
}
/* 7C92AAA4 */
LPVOID RtlLookupFunctionTable(PEXCEPTION_HANDLER handler, DWORD *base_addr, DWORD *table_sz) {
MEMORY_BASIC_INFORMATION mbi;
LPVOID safeseh_table, base;
if (LdrpInLdrInit && RtlTryEnterCriticalSection(&LdrpLoaderLock) == 0) {
/* 7C92DD29 3 = MemoryBasicVlmInformation */
if (NtQueryVirtualMemory((HANDLE) -1, handler, 3, &mbi, sizeof(MEMORY_BASIC_INFORMATION), NULL) < 0) {
return NULL;
}
else if (mbi.Type != SEC_IMAGE) {
return NULL;
}
base = mbi.BaseAddress;
/* 7C92DD51 */
RtlCaptureImageExceptionValues(base, &safeseh_table, table_sz);
}
else {
if (_TEB != NULL) {
/* 7C92AAD9 */
PLDR_MODULE node = _PEB->Ldr->InLoadOrderModuleList.Flink
if (_PEB->Ldr != 0 && node != NULL) {
while (node != &_PEB->Ldr->InLoadOrderModuleList) {
/* 7C92AB00 */
if (handler < node->BaseAddr) {
node = node->InLoadOrderModuleList.Flink;
continue;
}
if (handler >= node->BaseAddr + node->SizeOfImage) {
node = node->InLoadOrderModuleList.Flink;
continue;
}
/* 7C92AB14 */
base = node->BaseAddr;
RtlCaptureImageExceptionValues(base, &safeseh_table, table_sz);
if (safeseh_table == NULL && NtDllBase != NULL && (base = RtlNtImageHeader(NtDllBase)) != NULL) {
if (header > base && header < base + ((PIMAGE_NT_HEADER) base)->OptionalHeaders.SizeOfImage) {
/* 7C950D7D */
RtlCaptureImageExceptionValues(base, &safeseh_table, table_sz);
}
}
break;
}
}
}
/* 7C92AB2C */
if (LdrpInLdrInit) {
RtlLeaveCriticalSection(&LdrpLoaderLock);
}
}
*base_addr = base;
return safeseh_table;
}
以上是关于逆向分析windows用户层异常分发源码的主要内容,如果未能解决你的问题,请参考以下文章
Windows 逆向使用 CE 工具挖掘关键数据内存真实地址 ( 逐层分析分析 静态地址 到 动态地址 的寻址 + 偏移 过程 ) ★
Android 逆向整体加固脱壳 ( 脱壳起点 : 整体加固脱壳 | Dalvik 脱壳机制 : 利用 DexClassLoader 加载过程进行脱壳 | 相关源码分析 )