void CALLBACK DebugExtensionUninitialize(void) { EXIT_API(); return; }
/* A built-in help for the extension dll */ HRESULT CALLBACK help(PDEBUG_CLIENT4 Client, PCSTR args) { INIT_API(); UNREFERENCED_PARAMETER(args); dprintf("Help for dbgexts.dll\n" " cmdsample - This does stacktrace and lists\n" " help = Shows this help\n" " structsample <addr> - This dumps a struct at given address\n" ); EXIT_API(); return S_OK; }
/* Sample extension to demonstrate executing debugger command */ HRESULT CALLBACK cmdsample(PDEBUG_CLIENT4 Client, PCSTR args) { CHAR Input[256]; INIT_API(); UNREFERENCED_PARAMETER(args); // // Output a 10 frame stack // g_ExtControl->OutputStackTrace(DEBUG_OUTCTL_ALL_CLIENTS | // Flags on what to do with output DEBUG_OUTCTL_OVERRIDE_MASK | DEBUG_OUTCTL_NOT_LOGGED, NULL, 10, // number of frames to display DEBUG_STACK_FUNCTION_INFO | DEBUG_STACK_COLUMN_NAMES | DEBUG_STACK_ARGUMENTS | DEBUG_STACK_FRAME_ADDRESSES); // // Engine interface for print // g_ExtControl->Output(DEBUG_OUTCTL_ALL_CLIENTS, "\n\nDebugger module list\n"); // // list all the modules by executing lm command // g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS | DEBUG_OUTCTL_OVERRIDE_MASK | DEBUG_OUTCTL_NOT_LOGGED, "lm", // Command to be executed DEBUG_EXECUTE_DEFAULT ); // // Ask for user input // g_ExtControl->Output(DEBUG_OUTCTL_ALL_CLIENTS, "\n\n***User Input sample\n\nEnter Command to run : "); GetInputLine(NULL, &Input[0], sizeof(Input)); Input[ARRAYSIZE(Input) - 1] = 0; // Ensure null termination g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS | DEBUG_OUTCTL_OVERRIDE_MASK | DEBUG_OUTCTL_NOT_LOGGED, Input, // Command to be executed DEBUG_EXECUTE_DEFAULT ); EXIT_API(); return S_OK; }
void CALLBACK DebugExtensionUninitialize(void) { dprintf("[sync] DebugExtensionUninitialize\n"); ReleasePollTimer(); DeleteCriticalSection(&g_CritSectPollRelease); TunnelClose(); if(g_ExtConfFile) { free(g_DefaultHost); free(g_DefaultPort); } EXIT_API(); return; }
/* Sample extension to read and dump a struct on target This reads the struct _EXCEPTION_RECORD which is defined as: typedef struct _EXCEPTION_RECORD { NTSTATUS ExceptionCode; ULONG ExceptionFlags; struct _EXCEPTION_RECORD *ExceptionRecord; PVOID ExceptionAddress; ULONG NumberParameters; ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; } EXCEPTION_RECORD; */ HRESULT CALLBACK structsample(PDEBUG_CLIENT4 Client, PCSTR args) { ULONG64 Address; INIT_API(); Address = GetExpression(args); DWORD Buffer[4], cb; // Read and display first 4 dwords at Address if (ReadMemory(Address, &Buffer, sizeof(Buffer), &cb) && cb == sizeof(Buffer)) { dprintf("%p: %08lx %08lx %08lx %08lx\n\n", Address, Buffer[0], Buffer[1], Buffer[2], Buffer[3]); } // // Method 1 to dump a struct // dprintf("Method 1:\n"); // Inititalze type read from the Address if (InitTypeRead(Address, _EXCEPTION_RECORD) != 0) { dprintf("Error in reading _EXCEPTION_RECORD at %p", // Use %p to print pointer values Address); } else { // read and dump the fields dprintf("_EXCEPTION_RECORD @ %p\n", Address); dprintf("\tExceptionCode : %lx\n", (ULONG) ReadField(ExceptionCode)); dprintf("\tExceptionAddress : %p\n", ReadField(ExceptionAddress)); dprintf("\tExceptionInformation[1] : %I64lx\n", ReadField(ExceptionInformation[1])); // And so on... } // // Method 2 to read a struct // ULONG64 ExceptionInformation_1, ExceptionAddress, ExceptionCode; dprintf("\n\nMethod 2:\n"); // Read and dump the fields by specifying type and address individually if (GetFieldValue(Address, "_EXCEPTION_RECORD", "ExceptionCode", ExceptionCode)) { dprintf("Error in reading _EXCEPTION_RECORD at %p\n", Address); } else { // Pointers are read as ULONG64 values GetFieldValue(Address, "_EXCEPTION_RECORD", "ExceptionAddress", ExceptionAddress); GetFieldValue(Address, "_EXCEPTION_RECORD", "ExceptionInformation[1]", ExceptionInformation_1); // And so on.. dprintf("_EXCEPTION_RECORD @ %p\n", Address); dprintf("\tExceptionCode : %lx\n", ExceptionCode); dprintf("\tExceptionAddress : %p\n", ExceptionAddress); dprintf("\tExceptionInformation[1] : %I64lx\n", ExceptionInformation_1); } ULONG64 Module; ULONG i, TypeId; CHAR Name[MAX_PATH]; // // To get/list field names // g_ExtSymbols->GetSymbolTypeId("_EXCEPTION_RECORD", &TypeId, &Module); dprintf("Fields of _EXCEPTION_RECORD\n"); for (i=0; ;i++) { HRESULT Hr; ULONG Offset=0; Hr = g_ExtSymbols->GetFieldName(Module, TypeId, i, Name, MAX_PATH, NULL); if (Hr == S_OK) { g_ExtSymbols->GetFieldOffset(Module, TypeId, Name, &Offset); dprintf("%lx (+%03lx) %s\n", i, Offset, Name); } else if (Hr == E_INVALIDARG) { // All Fields done break; } else { dprintf("GetFieldName Failed %lx\n", Hr); break; } } // // Get name for an enumerate // // typedef enum { // Enum1, // Enum2, // Enum3, // } TEST_ENUM; // ULONG ValueOfEnum = 0; g_ExtSymbols->GetSymbolTypeId("TEST_ENUM", &TypeId, &Module); g_ExtSymbols->GetConstantName(Module, TypeId, ValueOfEnum, Name, MAX_PATH, NULL); dprintf("Testenum %I64lx == %s\n", ExceptionCode, Name); // This prints out, Testenum 0 == Enum1 // // Read an array // // typedef struct FOO_TYPE { // ULONG Bar; // ULONG Bar2; // } FOO_TYPE; // // FOO_TYPE sampleArray[20]; ULONG Bar, Bar2; CHAR TypeName[100]; for (i=0; i<20; i++) { sprintf_s(TypeName, sizeof(TypeName), "sampleArray[%lx]", i); if (GetFieldValue(0, TypeName, "Bar", Bar)) break; GetFieldValue(0, TypeName, "Bar2", Bar2); dprintf("%16s - Bar %2ld Bar2 %ld\n", TypeName, Bar, Bar2); } EXIT_API(); return S_OK; }
/* Extension to look at locals through IDebugSymbolGroup interface Usage: !symgrptest [args] To demontrate local/args lookup, this will go through the stack and set scope with the instruction of the stack frame and enumerate all the locals/arguments for the frame function */ HRESULT CALLBACK symgrptest(PDEBUG_CLIENT4 Client, PCSTR args) { HRESULT hRes; IDebugSymbolGroup *pDbgSymGroup; ULONG ulCount, nFrames; DEBUG_STACK_FRAME Stack[50]; ULONG SymGroupType; INIT_API(); if (!_stricmp(args, "args")) { // Disply only the arguments SymGroupType = DEBUG_SCOPE_GROUP_ARGUMENTS; } else { // Display all the locals SymGroupType = DEBUG_SCOPE_GROUP_LOCALS; } // // Get the current stack // if ((hRes = g_ExtControl->GetStackTrace(0, 0, 0, &Stack[0], 50, &nFrames)) != S_OK) { dprintf("Stacktrace failed - %lx\n", hRes); nFrames = 0; } // Create a local symbol group client if ((hRes = g_ExtSymbols-> GetScopeSymbolGroup(SymGroupType, NULL, &pDbgSymGroup)) == E_NOTIMPL) { EXIT_API(); return S_OK; } while (nFrames) { // // Enumerate locals for this frame // --nFrames; // Set scope at this frame g_ExtSymbols->SetScope(0, &Stack[nFrames], NULL, 0); // refresh the symbol group with current scope if ((hRes = g_ExtSymbols-> GetScopeSymbolGroup(DEBUG_SCOPE_GROUP_LOCALS, pDbgSymGroup, &pDbgSymGroup)) == E_NOTIMPL) { break; } hRes = pDbgSymGroup->GetNumberSymbols ( &ulCount); dprintf("\n\n>Scope Frame %lx: %lx Symbols\n",nFrames,ulCount); PDEBUG_SYMBOL_PARAMETERS pSymParams = new DEBUG_SYMBOL_PARAMETERS[ ulCount ] ; if (ulCount) { // Get all symbols for the frame hRes = pDbgSymGroup->GetSymbolParameters (0, ulCount , pSymParams); } if ( S_OK == hRes ) { for ( ULONG i = 0 ; i < ulCount ; i++ ) { TCHAR szName[ MAX_PATH ], *pName; ULONG ulSize; DEBUG_VALUE Value; // Lookup symbol name and print pName = &szName[1]; hRes = pDbgSymGroup->GetSymbolName ( i, pName, MAX_PATH - 1, &ulSize ) ; if (SUCCEEDED(hRes)) { // Prefix ! so this is evaluated as symbol szName[0] = '!'; hRes = g_ExtControl->Evaluate(szName, DEBUG_VALUE_INVALID, &Value, NULL); if (SUCCEEDED(hRes)) { dprintf("%lx: %32s = 0x%p\n", i, pName, Value.I64); } } } } delete []pSymParams; } pDbgSymGroup->Release(); EXIT_API(); return S_OK; }
HRESULT CALLBACK pe(PDEBUG_CLIENT4 Client, PCSTR args) { INIT_API(); ULONG_PTR ulAddress = 0; ULONG_PTR ulBase = 0; ULONG_PTR ulImageSize = 0; HRESULT result = S_OK; ULONG ulSetionCount = 0; BOOL bAllPrint = TRUE; BOOL bPrintDosHeard = FALSE; BOOL bPrintNtHeard = FALSE; BOOL bSection = FALSE; BOOL bImport = FALSE; BOOL bExport = FALSE; IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES] = { 0 }; if ( args == NULL) { result = S_FALSE; goto ex; }do { const char * split = " "; char * p = NULL, *params = NULL, *next = NULL; params = new char[strlen(args) + 1]; if (params == NULL) { result = S_FALSE; goto ex; } _try { memset(params, 0, strlen(args) + 1); strcpy_s(params, strlen(args) + 1, args); p = strtok_s(params, split, &next); while (p != NULL) { if (_stricmp(p, "-section") == 0) { bAllPrint = FALSE; bSection = TRUE; } else if (_stricmp(p, "-dos") == 0) { bAllPrint = FALSE; bPrintDosHeard = TRUE; } else if (_stricmp(p, "-nt") == 0) { bAllPrint = FALSE; bPrintNtHeard = TRUE; } else if (_stricmp(p, "-import") == 0) { bAllPrint = FALSE; bImport = TRUE; } else if (_stricmp(p, "-export") == 0) { bAllPrint = FALSE; bExport = TRUE; } else if (p) { char *endptr = NULL; ulAddress = str2ull(p, &endptr, 16); ulBase = ulAddress; } p = strtok_s(NULL, split, &next); } }_finally { if (params) { delete[]params; params = NULL; } } } while (FALSE); if (ulAddress == 0) { result = S_FALSE; goto ex; } if (result = PE_PrintDosHeard(&ulAddress, bAllPrint | bPrintDosHeard) != S_OK) { goto ex; } if (result = PE_PrintNtHeard(&ulAddress, bAllPrint | bPrintNtHeard, &ulSetionCount, DataDirectory, &ulImageSize) != S_OK) { goto ex; } if (result = PE_PrintSection(&ulAddress, ulSetionCount, bAllPrint | bSection) != S_OK) { goto ex; } PBYTE pImage = new BYTE[ulImageSize]; if (pImage == NULL) { result = S_FALSE; goto ex; } _try { ULONG ulReadSize = 0; memset(pImage, 0, ulImageSize); result = g_ExtDataSpaces->ReadVirtual(ulBase, pImage, ulImageSize, &ulReadSize); if (result != S_OK) { dprintf("读取虚拟地址 %x 错误 \n", ulBase); goto ex; } if (ulReadSize != ulImageSize) { dprintf("读取数据长度错误。 \n"); result = S_FALSE; goto ex; } if (result = PE_PrintImport(pImage, DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT], bAllPrint | bImport) != S_OK) { goto ex; } if (result = PE_PrintExport(pImage, DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT], ulBase, bAllPrint | bExport) != S_OK) { goto ex; } }_finally { if (pImage) { delete[]pImage; pImage = NULL; } } ex: EXIT_API(); return result; }