#include <stdlib.h> #include <stdio.h> #include <conio.h> #include <string.h> #include <os/os.h> #include <os/pe.h> #include <os/console.h> wchar_t *_getws(wchar_t *buffer) { wchar_t* ch = buffer; while (true) { *ch = _wgetch(); switch (*ch) { case 0: break; case L'\n': *ch = 0; putwchar(L'\n'); return buffer; case L'\b': if (ch > buffer) { _cputws(L"\b \b"); ch--; } break; default: putwchar(*ch); ch++; } } } #if 0 typedef struct exception_pointers_t exception_pointers_t; struct exception_pointers_t { exception_info_t* info; context_t* ctx; }; // Data structure(s) pointed to by Visual C++ extended exception frame struct scopetable_entry { dword previousTryLevel; void* lpfnFilter; void* lpfnHandler; }; typedef struct exception_registration_vc_t exception_registration_vc_t; struct exception_registration_vc_t { exception_registration_t reg; struct scopetable_entry *scopetable; int trylevel; int _ebp; exception_pointers_t* xpointers; }; #define TRYLEVEL_NONE 0xffffffff #define EXCEPTION_CONTINUE_EXECUTION -1 #define EXCEPTION_CONTINUE_SEARCH 0 #define EXCEPTION_EXECUTE_HANDLER 1 // The extended exception frame used by Visual C++ struct VC_EXCEPTION_REGISTRATION { exception_registration_t reg; struct scopetable_entry * scopetable; int trylevel; int _ebp; }; ExceptionDisposition _except_handler3( exception_info_t *ExceptionRecord, void * EstablisherFrame, context_t *ContextRecord, void * DispatcherContext); //---------------------------------------------------------------------------- // Code //---------------------------------------------------------------------------- // // Display the information in one exception frame, along with its scopetable // void ShowSEHFrame( struct VC_EXCEPTION_REGISTRATION * pVCExcRec ) { struct scopetable_entry * pScopeTableEntry = pVCExcRec->scopetable; int i; wprintf( L"Frame: %08X Handler: %08X Prev: %08X Scopetable: %08X\n", pVCExcRec, pVCExcRec->reg.handler, pVCExcRec->reg.prev, pVCExcRec->scopetable ); for (i = 0; i <= pVCExcRec->trylevel; i++ ) { wprintf( L" scopetable[%u] PrevTryLevel: %08X " L"filter: %08X __except: %08X\n", i, pScopeTableEntry->previousTryLevel, pScopeTableEntry->lpfnFilter, pScopeTableEntry->lpfnHandler ); pScopeTableEntry++; } //wprintf( L"\n" ); } // // Walk the linked list of frames, displaying each in turn // void WalkSEHFrames( void ) { struct VC_EXCEPTION_REGISTRATION * pVCExcRec; // Print out the location of the __except_handler3 function wprintf( L"_except_handler3 is at address: %08X\n", _except_handler3 ); //wprintf( L"\n" ); // Get a pointer to the head of the chain at FS:[0] asm("mov %%fs(0), %%eax" : "=a" (pVCExcRec)); // Walk the linked list of frames. 0xFFFFFFFF indicates the end of list while ( NULL != pVCExcRec ) { ShowSEHFrame( pVCExcRec ); pVCExcRec = (struct VC_EXCEPTION_REGISTRATION *)(pVCExcRec->reg.prev); } } ExceptionDisposition _except_handler3( exception_info_t *ExceptionRecord, void * EstablisherFrame, context_t *ContextRecord, void * DispatcherContext) { struct VC_EXCEPTION_REGISTRATION * pVCExcRec; unsigned tryLevel, temp; int val; dword func; exception_pointers_t exceptPtrs; wprintf(L"Exception: %08x at %08x\n", ExceptionRecord->code, ExceptionRecord->address); //WalkSEHFrames(); // Build the EXCEPTION_POINTERS structure on the stack exceptPtrs.info = ExceptionRecord; exceptPtrs.ctx = ContextRecord; // Get a pointer to the head of the chain at FS:[0] //__asm mov eax, FS:[0] //__asm mov [pVCExcRec], EAX pVCExcRec = (struct VC_EXCEPTION_REGISTRATION*) EstablisherFrame; // Put the pointer to the EXCEPTION_POINTERS 4 bytes below the // establisher frame. See ASM code for GetExceptionInformation *(dword*)((byte*)pVCExcRec - 4) = (dword) &exceptPtrs; tryLevel = pVCExcRec->trylevel; while (tryLevel != -1) { temp = pVCExcRec->_ebp; func = (dword) pVCExcRec->scopetable[tryLevel].lpfnFilter; wprintf(L"tryLevel = %d, ebp = %x, filter = %x\n", tryLevel, temp, func); __asm { mov eax, func push ebp mov ebp, temp call eax pop ebp mov val, eax } switch (val) { case EXCEPTION_CONTINUE_SEARCH: wprintf(L"Continue search\n"); break; case EXCEPTION_EXECUTE_HANDLER: func = (dword) pVCExcRec->scopetable[tryLevel].lpfnHandler; wprintf(L"Execute handler = %x, ebp = %x, esp = %x\n", func, temp, ((dword*) temp)[-0x18]); __asm { mov eax, func push ebp mov ebp, temp call eax pop ebp } wprintf(L"Returned\n"); break; case EXCEPTION_CONTINUE_EXECUTION: wprintf(L"Continue execution\n"); return ExceptionContinueExecution; } //pVCExcRec = (struct VC_EXCEPTION_REGISTRATION *)(pVCExcRec->reg.prev); tryLevel = pVCExcRec->scopetable[tryLevel].previousTryLevel; } wprintf(L"Returning\n"); return ExceptionContinueSearch; } #endif int main() { wchar_t buf[256], args[256], *ch; addr_t proc; bool async; if (resLoadString(procBase(), 1, buf, countof(buf))) _cputws(buf); while (true) { wprintf(L"[%s] ", thrGetInfo()->process->cwd); if (*_getws(buf)) { ch = wcschr(buf, ' '); if (ch) { size_t len; wcscpy(args, ch + 1); *ch = '\0'; len = wcslen(args); if (args[len - 1] == '&') { args[len - 1] = 0; async = true; } else async = false; } else { args[0] = '\0'; async = false; } //for (i = 0; i < 800; i++) { //wprintf(L"%3d\t", i); if (wcsicmp(buf, L"exit") == 0) break; else if (wcsicmp(buf, L"cd") == 0) wcscpy(thrGetInfo()->process->cwd, args); else if (wcsicmp(buf, L"break") == 0) asm("int3"); else { if (!(proc = procLoad(buf, args, 16, NULL, NULL))) { wcscat(buf, L".exe"); if (!(proc = procLoad(buf, args, 16, NULL, NULL))) { wprintf(L"%s: not found\n", buf); continue; } } if (!async) thrWaitHandle(&proc, 1, false); } } } } return 0; }