Created
May 16, 2024 15:16
-
-
Save entdark/4af06048cd237dd31071ffa3aa144c53 to your computer and use it in GitHub Desktop.
Basic Crash Handler for Win32 API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <time.h> | |
#define PSAPI_VERSION 1 | |
#include <Windows.h> | |
#include <Psapi.h> | |
#include <Dbghelp.h> | |
char* GetExceptionName(DWORD code) | |
{ | |
switch(code) | |
{ | |
case EXCEPTION_ACCESS_VIOLATION: return "Access Violation"; | |
case EXCEPTION_DATATYPE_MISALIGNMENT: return "Datatype Misalignment"; | |
case EXCEPTION_BREAKPOINT: return "Breakpoint"; | |
case EXCEPTION_SINGLE_STEP: return "Single Step"; | |
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: return "Array Bounds Exceeded"; | |
case EXCEPTION_FLT_DENORMAL_OPERAND: return "Float Denormal Operand"; | |
case EXCEPTION_FLT_DIVIDE_BY_ZERO: return "Float Divide By Zero"; | |
case EXCEPTION_FLT_INEXACT_RESULT: return "Float Inexact Result"; | |
case EXCEPTION_FLT_INVALID_OPERATION: return "Float Invalid Operation"; | |
case EXCEPTION_FLT_OVERFLOW: return "Float Overflow"; | |
case EXCEPTION_FLT_STACK_CHECK: return "Float Stack Check"; | |
case EXCEPTION_FLT_UNDERFLOW: return "Float Underflow"; | |
case EXCEPTION_INT_DIVIDE_BY_ZERO: return "Integer Divide By Zero"; | |
case EXCEPTION_INT_OVERFLOW: return "Integer Overflow"; | |
case EXCEPTION_PRIV_INSTRUCTION: return "Private Instruction"; | |
case EXCEPTION_IN_PAGE_ERROR: return "In Page Error"; | |
case EXCEPTION_ILLEGAL_INSTRUCTION: return "Illegal Instruction"; | |
case EXCEPTION_NONCONTINUABLE_EXCEPTION: return "Non-continuable Exceptiopn"; | |
case EXCEPTION_STACK_OVERFLOW: return "Stack Overflow"; | |
case EXCEPTION_INVALID_DISPOSITION: return "Invalid Disposition"; | |
case EXCEPTION_GUARD_PAGE: return "Guard Page"; | |
case EXCEPTION_INVALID_HANDLE: return "Invalid Handle"; | |
case 0xE06D7363: return "C++ Exception (using throw)"; | |
default: | |
return "Unknown Exception"; | |
} | |
} | |
void Win_PrintCallStack(FILE *output, HANDLE thread, CONTEXT* pContext) | |
{ | |
BOOL result; | |
HANDLE process; | |
CONTEXT context; | |
STACKFRAME64 stack; | |
ULONG frame; | |
IMAGEHLP_SYMBOL64* symbol; | |
DWORD64 displacement; | |
DWORD64 moduleAddress; | |
DWORD baseOffset; | |
char symbolBuffer[sizeof(IMAGEHLP_SYMBOL64)+256]; | |
char moduleName[128]; | |
static char CrashLogFileName[128]; | |
// redirect to standard output by default | |
if (!output) | |
output = stdout; | |
// trace stack for this thread by default | |
if (!thread) | |
thread = GetCurrentThread(); | |
// use current context by default | |
if (!pContext) | |
{ | |
memset( &context, 0, sizeof( context ) ); | |
RtlCaptureContext( &context ); | |
pContext = &context; | |
} | |
// stack info initialization | |
memset( &symbolBuffer, 0, sizeof( symbolBuffer ) ); | |
symbol = (IMAGEHLP_SYMBOL64*)symbolBuffer; | |
memset( &stack, 0, sizeof( STACKFRAME64 ) ); | |
process = GetCurrentProcess(); | |
displacement = 0; | |
stack.AddrPC.Offset = pContext->Eip; | |
stack.AddrPC.Mode = AddrModeFlat; | |
stack.AddrStack.Offset = pContext->Esp; | |
stack.AddrStack.Mode = AddrModeFlat; | |
stack.AddrFrame.Offset = pContext->Ebp; | |
stack.AddrFrame.Mode = AddrModeFlat; | |
// symbols inicialization (using Dbghelp.dll) | |
SymInitialize( process, NULL, TRUE ); | |
frame = 0; | |
baseOffset = (DWORD)GetModuleHandle(NULL); | |
fprintf(output, "\n-----------------------------------\n"); | |
fprintf(output, " Call Stack Trace \n"); | |
fprintf(output, "-----------------------------------\n"); | |
while( result = StackWalk64( IMAGE_FILE_MACHINE_I386, process, thread, &stack, | |
NULL, NULL, NULL, SymGetModuleBase64, NULL ) ) | |
{ | |
// get module name | |
moduleAddress = SymGetModuleBase64(process, stack.AddrPC.Offset); | |
GetModuleBaseName(process, (HMODULE) moduleAddress, moduleName, sizeof(moduleName)); | |
// attempt to load symbol information (name/offset) | |
symbol->SizeOfStruct = sizeof( IMAGEHLP_SYMBOL64 ); | |
symbol->MaxNameLength = 256; | |
SymGetSymFromAddr64( process, ( ULONG64 )stack.AddrPC.Offset, &displacement, symbol ); | |
// with symbols | |
if ( symbol->Address && (stack.AddrPC.Offset >= symbol->Address) ) | |
{ | |
fprintf( output, "%s(%s+0x%llX) [0x%llX]\n", | |
moduleName, symbol->Name, stack.AddrPC.Offset-symbol->Address, stack.AddrPC.Offset ); | |
} | |
else | |
{ | |
fprintf( output, "%s [0x%llX]\n", | |
moduleName, stack.AddrPC.Offset ); | |
} | |
++frame; | |
} | |
} | |
LONG Win_Handler(LPEXCEPTION_POINTERS p) | |
{ | |
HANDLE process, thread; | |
static char ProcessName[128],ModuleName[128]; | |
static char CrashLogFileName[128]; | |
static char CrashLogFileMiniDumpName[128]; | |
time_t rawtime; | |
struct tm * timeinfo; | |
FILE* CrashLogFile; | |
DWORD64 moduleAddress; | |
HANDLE hDumpFile = NULL; | |
process = GetCurrentProcess(); | |
thread = GetCurrentThread(); | |
// symbols inicialization (using Dbghelp.dll) | |
SymInitialize( process, NULL, TRUE ); | |
// get process name | |
GetModuleFileName(NULL,ProcessName,sizeof(ProcessName)); | |
// get module name | |
moduleAddress = SymGetModuleBase64(process, (DWORD64)p->ExceptionRecord->ExceptionAddress); | |
GetModuleBaseName(GetCurrentProcess(), (HMODULE) moduleAddress, ModuleName, sizeof(ModuleName)); | |
// generate crash log file name | |
time ( &rawtime ); | |
timeinfo = localtime ( &rawtime ); | |
strftime(CrashLogFileName, sizeof(CrashLogFileName), "crash_log_%Y-%m-%d_%H-%M-%S.log", timeinfo); | |
//Before we possibly fuck any of the stack or heap in the middle of a you know - crash - save the state to a minidump | |
// open crash log file | |
CrashLogFile = fopen(CrashLogFileName,"w"); | |
fprintf(CrashLogFile, "Process File Name: %s\n", ProcessName ); | |
fprintf(CrashLogFile, "Exception Code: 0x%08X (%s)\n", | |
p->ExceptionRecord->ExceptionCode, GetExceptionName(p->ExceptionRecord->ExceptionCode)); | |
fprintf(CrashLogFile, "Exception Address: 0x%08X (%s+0x%X)\n", | |
p->ExceptionRecord->ExceptionAddress,ModuleName,(DWORD)p->ExceptionRecord->ExceptionAddress - moduleAddress); | |
fprintf(CrashLogFile, "\n-----------------------------------\n"); | |
fprintf(CrashLogFile, " Register Dump \n"); | |
fprintf(CrashLogFile, "-----------------------------------\n"); | |
fprintf(CrashLogFile, "General Purpose & Control Registers:\n"); | |
fprintf(CrashLogFile, "EAX: 0x%08X, EBX: 0x%08X, ECX: 0x%08X\n", | |
p->ContextRecord->Eax, p->ContextRecord->Ebx, p->ContextRecord->Ecx ); | |
fprintf(CrashLogFile, "EDX: 0x%08X, EBP: 0x%08X, EDI: 0x%08X\n", | |
p->ContextRecord->Edx, p->ContextRecord->Ebp, p->ContextRecord->Edi ); | |
fprintf(CrashLogFile, "EIP: 0x%08X, ESI: 0x%08X, ESP: 0x%08X\n", | |
p->ContextRecord->Eip, p->ContextRecord->Esi, p->ContextRecord->Esp ); | |
fprintf(CrashLogFile, "\nSegment Registers:\n"); | |
fprintf(CrashLogFile, "CS: 0x%08X, DS: 0x%08X, ES: 0x%08X\n", | |
p->ContextRecord->SegCs, p->ContextRecord->SegDs, p->ContextRecord->SegEs ); | |
fprintf(CrashLogFile, "FS: 0x%08X, GS: 0x%08X, SS: 0x%08X\n", | |
p->ContextRecord->SegFs, p->ContextRecord->SegGs, p->ContextRecord->SegSs ); | |
Win_PrintCallStack(CrashLogFile, thread, p->ContextRecord); | |
// close crash log file | |
fclose(CrashLogFile); | |
return EXCEPTION_EXECUTE_HANDLER; | |
} | |
void InitUnhandledExceptionFilter() | |
{ | |
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)&Win_Handler); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment