1. 程式人生 > >逆向分析用戶層異常分發源碼

逆向分析用戶層異常分發源碼

win

#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; }

逆向分析用戶層異常分發源碼