From dd7e3cfa8520e1d8b2d950a9c8f3f3472ecb4fad Mon Sep 17 00:00:00 2001 From: Nukem Date: Sun, 24 Jan 2016 18:38:46 -0500 Subject: [PATCH] DBG: Implement most functions for exception handlers (SEH missing) --- src/dbg/exhandlerinfo.cpp | 167 ++++++++++++++++++++++++++++ src/dbg/exhandlerinfo.h | 26 +++++ src/dbg/undocumented.h | 13 +++ src/dbg/x64_dbg_dbg.vcxproj | 2 + src/dbg/x64_dbg_dbg.vcxproj.filters | 6 + 5 files changed, 214 insertions(+) create mode 100644 src/dbg/exhandlerinfo.cpp create mode 100644 src/dbg/exhandlerinfo.h diff --git a/src/dbg/exhandlerinfo.cpp b/src/dbg/exhandlerinfo.cpp new file mode 100644 index 00000000..5f594eee --- /dev/null +++ b/src/dbg/exhandlerinfo.cpp @@ -0,0 +1,167 @@ +/** +@file exhandlerinfo.cpp + +@brief ??? +*/ + +#include "exhandlerinfo.h" +#include "memory.h" +#include "disasm_helper.h" +#include "disasm_fast.h" +#include "_exports.h" +#include "module.h" +#include "thread.h" + +bool ExHandlerGetInfo(EX_HANDLER_TYPE Type, EX_HANDLER_INFO* Info) +{ + bool ret = false; + std::vector handlerEntries; + + switch(Type) + { + case EX_HANDLER_SEH: + ret = ExHandlerGetSEH(handlerEntries); + break; + + case EX_HANDLER_VEH: + ret = ExHandlerGetVEH(handlerEntries); + break; + + case EX_HANDLER_VCH: + ret = ExHandlerGetVCH(handlerEntries); + break; + + case EX_HANDLER_UNHANDLED: + ret = ExHandlerGetUnhandled(handlerEntries); + break; + } + + // Check if a call failed + if(!ret) + { + Info->count = 0; + Info->addresses = nullptr; + return false; + } + + // Convert vector to C-style array + Info->count = (int)handlerEntries.size(); + Info->addresses = (duint*)BridgeAlloc(Info->count * sizeof(duint)); + + memcpy(Info->addresses, handlerEntries.data(), Info->count * sizeof(duint)); + return false; +} + +bool ExHandlerGetSEH(std::vector & Entries) +{ + // TODO: 32-bit + // TODO: 64-bit + return false; +} + +bool ExHandlerGetVEH(std::vector & Entries) +{ + // Try the address for Windows XP first (or older) + // + // VECTORED_EXCEPTION_NODE RtlpCalloutEntryList; + static duint addr_RtlpCalloutEntryList = 0; + + if(addr_RtlpCalloutEntryList || valfromstring("ntdll:RtlpCalloutEntryList", &addr_RtlpCalloutEntryList)) + { + // Read header node + VECTORED_EXCEPTION_NODE node; + memset(&node, 0, sizeof(VECTORED_EXCEPTION_NODE)); + + if(!MemRead(addr_RtlpCalloutEntryList, &node, sizeof(VECTORED_EXCEPTION_NODE))) + return false; + + // Move to the next link + duint listCurrent = (duint)node.ListEntry.Flink; + duint listEnd = addr_RtlpCalloutEntryList; + + while(listCurrent && listCurrent != listEnd) + { + duint handler = (duint)node.handler; + + MemDecodePointer(&handler); + Entries.push_back(handler); + + // Move to next element + memset(&node, 0, sizeof(VECTORED_EXCEPTION_NODE)); + + if(!MemRead(listCurrent, &node, sizeof(VECTORED_EXCEPTION_NODE))) + break; + + listCurrent = (duint)node.ListEntry.Flink; + } + } + + // Otherwise try the Windows Vista or newer version + return ExHandlerGetVCH(Entries, true); +} + +bool ExHandlerGetVCH(std::vector & Entries, bool UseVEH) +{ + // VECTORED_HANDLER_LIST LdrpVectorHandlerList[2]; + static duint addr_LdrpVectorHandlerList = 0; + + if(!addr_LdrpVectorHandlerList && !valfromstring("ntdll:LdrpVectorHandlerList", &addr_LdrpVectorHandlerList)) + return false; + + // Increase array index when using continue handlers + if(!UseVEH) + addr_LdrpVectorHandlerList += (1 * sizeof(VECTORED_HANDLER_LIST)); + + // Read head entry + VECTORED_HANDLER_LIST list; + memset(&list, 0, sizeof(VECTORED_HANDLER_LIST)); + + if(!MemRead(addr_LdrpVectorHandlerList, &list, sizeof(VECTORED_HANDLER_LIST))) + return false; + + // Sub-entries in list + duint listCurrent = (duint)list.Next; + duint listEnd = addr_LdrpVectorHandlerList; + + while(listCurrent && listCurrent != listEnd) + { + duint handler = (duint)list.VectoredHandler; + + MemDecodePointer(&handler); + Entries.push_back(handler); + + // Move to next element + memset(&list, 0, sizeof(VECTORED_HANDLER_LIST)); + + if(!MemRead(listCurrent, &list, sizeof(VECTORED_HANDLER_LIST))) + break; + + listCurrent = (duint)list.Next; + } + + return true; +} + +bool ExHandlerGetUnhandled(std::vector & Entries) +{ + // Try the address for Windows Vista+ + static duint addr_BasepCurrentTopLevelFilter = 0; + + if(addr_BasepCurrentTopLevelFilter || valfromstring("kernelbase:BasepCurrentTopLevelFilter", &addr_BasepCurrentTopLevelFilter)) + { + // Read external pointer + duint handlerValue = 0; + + if(!MemRead(addr_BasepCurrentTopLevelFilter, &handlerValue, sizeof(duint))) + return false; + + // Decode with remote process cookie + if(!MemDecodePointer(&handlerValue)) + return false; + + Entries.push_back(handlerValue); + return true; + } + + return false; +} \ No newline at end of file diff --git a/src/dbg/exhandlerinfo.h b/src/dbg/exhandlerinfo.h new file mode 100644 index 00000000..b5ac7c05 --- /dev/null +++ b/src/dbg/exhandlerinfo.h @@ -0,0 +1,26 @@ +#ifndef _EXHANDLERINFO_H +#define _EXHANDLERINFO_H + +#include "_global.h" + +enum EX_HANDLER_TYPE +{ + EX_HANDLER_SEH, // Structured + EX_HANDLER_VEH, // Vectored + EX_HANDLER_VCH, // Vectored continue + EX_HANDLER_UNHANDLED, // Unhandled +}; + +struct EX_HANDLER_INFO +{ + int count; + duint* addresses; +}; + +bool ExHandlerGetInfo(EX_HANDLER_TYPE Type, EX_HANDLER_INFO* Info); +bool ExHandlerGetSEH(std::vector & Entries); +bool ExHandlerGetVEH(std::vector & Entries); +bool ExHandlerGetVCH(std::vector & Entries, bool UseVEH); +bool ExHandlerGetUnhandled(std::vector & Entries); + +#endif //_EXHANDLERINFO_H \ No newline at end of file diff --git a/src/dbg/undocumented.h b/src/dbg/undocumented.h index 48dd0132..a512fb85 100644 --- a/src/dbg/undocumented.h +++ b/src/dbg/undocumented.h @@ -215,5 +215,18 @@ typedef struct _TEB PVOID StackReserved; } TEB, *PTEB; +typedef struct _VECTORED_EXCEPTION_NODE +{ + LIST_ENTRY ListEntry; + PVECTORED_EXCEPTION_HANDLER handler; +} VECTORED_EXCEPTION_NODE, *PVECTORED_EXCEPTION_NODE; + +typedef struct _LdrpVectorHandlerList +{ + struct _LdrpVectorHandlerList* Prev; + struct _LdrpVectorHandlerList* Next; + DWORD Depth; + PVECTORED_EXCEPTION_HANDLER VectoredHandler; +} VECTORED_HANDLER_LIST, *PVECTORED_HANDLER_LIST; #endif /* _UNDOCUMENTED_H */ \ No newline at end of file diff --git a/src/dbg/x64_dbg_dbg.vcxproj b/src/dbg/x64_dbg_dbg.vcxproj index bbf66e34..d8920240 100644 --- a/src/dbg/x64_dbg_dbg.vcxproj +++ b/src/dbg/x64_dbg_dbg.vcxproj @@ -42,6 +42,7 @@ + @@ -119,6 +120,7 @@ + diff --git a/src/dbg/x64_dbg_dbg.vcxproj.filters b/src/dbg/x64_dbg_dbg.vcxproj.filters index b2109dc3..59c10616 100644 --- a/src/dbg/x64_dbg_dbg.vcxproj.filters +++ b/src/dbg/x64_dbg_dbg.vcxproj.filters @@ -293,6 +293,9 @@ Source Files\Interfaces/Exports\_scriptapi + + Source Files\Information + @@ -646,5 +649,8 @@ Header Files\Interfaces/Exports\_scriptapi + + Header Files\Information + \ No newline at end of file