自己认识x64 seh结构时的小工具,可能有bug
#define UNW_FLAG_NHANDLER 0x0
#define UNW_FLAG_EHANDLER 0x1
#define UNW_FLAG_UHANDLER 0x2
#define UNW_FLAG_CHAININFO 0x4
typedef enum _UNWIND_OP_CODES {
UWOP_PUSH_NONVOL = 0,
UWOP_ALLOC_LARGE,
UWOP_ALLOC_SMALL,
UWOP_SET_FPREG,
UWOP_SAVE_NONVOL,
UWOP_SAVE_NONVOL_FAR,
UWOP_SPARE_CODE1,
UWOP_SPARE_CODE2,
UWOP_SAVE_XMM128,
UWOP_SAVE_XMM128_FAR,
UWOP_PUSH_MACHFRAME
} UNWIND_OP_CODES, *PUNWIND_OP_CODES;
typedef union _UNWIND_CODE {
struct {
UCHAR CodeOffset;
UCHAR UnwindOp : 4;
UCHAR OpInfo : 4;
};
USHORT FrameOffset;
} UNWIND_CODE, *PUNWIND_CODE;
typedef struct _UNWIND_INFO {
UCHAR Version : 3;
UCHAR Flags : 5;
UCHAR SizeOfProlog;
UCHAR CountOfCodes;
UCHAR FrameRegister : 4;
UCHAR FrameOffset : 4;
UNWIND_CODE UnwindCode[1];
/* UNWIND_CODE MoreUnwindCode[((CountOfCodes + 1) & ~1) - 1];
* union {
* OPTIONAL ULONG ExceptionHandler;
* OPTIONAL ULONG FunctionEntry;
* };
* OPTIONAL ULONG ExceptionData[]; */
} UNWIND_INFO, *PUNWIND_INFO;
typedef struct _SCOPE_TABLE {
ULONG Count;
struct
{
ULONG BeginAddress;
ULONG EndAddress;
ULONG HandlerAddress;
ULONG JumpTarget;
} ScopeRecord[1];
} SCOPE_TABLE, *PSCOPE_TABLE;
void DumpUnwindInfo(PUNWIND_INFO pUnInfo)
{
ULONG_PTR pImageBase = (ULONG_PTR)GetModuleHandle(NULL);
printf("unwind flag: UNW_FLAG_NHANDLER %d\nUNW_FLAG_EHANDLER %d\nUNW_FLAG_UHANDLER %d\nUNW_FLAG_CHAININFO %d\n",
pUnInfo->Flags & UNW_FLAG_NHANDLER,
pUnInfo->Flags & UNW_FLAG_EHANDLER,
pUnInfo->Flags & UNW_FLAG_UHANDLER,
pUnInfo->Flags & UNW_FLAG_CHAININFO);
printf("unwind sizeof prolog %d\nOffset of FrameReg 0x%x\nOffset of Frame 0x%x\n",
pUnInfo->SizeOfProlog,
pUnInfo->FrameRegister,
pUnInfo->FrameOffset);
for (int i=0;i<pUnInfo->CountOfCodes;i++)
{
printf("unwind code offset:%d\nUnwind op type %d\nFrameOff %d\n\n",
pUnInfo->UnwindCode[i].CodeOffset,
pUnInfo->UnwindCode[i].UnwindOp,
pUnInfo->UnwindCode[i].FrameOffset);
}
if (pUnInfo->Flags & UNW_FLAG_EHANDLER || pUnInfo->Flags & UNW_FLAG_UHANDLER)
{
ULONG_PTR pHandler = *(ULONG*)&pUnInfo->UnwindCode[pUnInfo->CountOfCodes] + pImageBase;
ULONG64 pt = (ULONG64)&pUnInfo->UnwindCode[pUnInfo->CountOfCodes];
pt+=4;
PSCOPE_TABLE scope = (PSCOPE_TABLE)pt;
printf("handler 0x%p\n",pHandler);
for (int i=0;i<scope->Count;i++)
{
if (scope->ScopeRecord[i].HandlerAddress == EXCEPTION_EXECUTE_HANDLER)
{
printf("scope %d\nBegin:0x%p\nEnd:0x%p\nHandler:%s\nJumpTarget0x%p\n\n",
i,
pImageBase + scope->ScopeRecord[i].BeginAddress,
pImageBase + scope->ScopeRecord[i].EndAddress,
"EXCEPTION_EXECUTE_HANDLER", //seh中 __except() 括号中的内容,rva or flag
pImageBase + scope->ScopeRecord[i].JumpTarget) ; //异常处理后要执行的部分
}
else
{
printf("scope %d\nBegin:0x%p\nEnd:0x%p\nHandler:0x%p\nJumpTarget0x%p\n\n",
i,
pImageBase + scope->ScopeRecord[i].BeginAddress,
pImageBase + scope->ScopeRecord[i].EndAddress,
pImageBase + scope->ScopeRecord[i].HandlerAddress, //seh中 __except() 括号中的内容,rva or flag
pImageBase + scope->ScopeRecord[i].JumpTarget) ; //异常处理后要执行的部分,等于0表示这是一个finally
}
}
}
}
void DpcMonitor(PULONG64 pUl)
{
__try
{
ULONG64 ul = *pUl;
printf("0x%p",ul);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
ULONG_PTR pImageBase;
PUNWIND_INFO pUnInfo = 0;
PRUNTIME_FUNCTION pRtlFunc = RtlLookupFunctionEntry((ULONGLONG)DpcMonitor,&pImageBase,0);
printf("DpcMonitor(0x%p)\nBeginAddress 0x%p\nEndAddress 0x%p\nUnwindData 0x%p \n",
DpcMonitor,
pRtlFunc->BeginAddress+pImageBase,
pRtlFunc->EndAddress+pImageBase,
pRtlFunc->UnwindData+pImageBase);
pUnInfo = (PUNWIND_INFO)(pRtlFunc->UnwindData+pImageBase);
DumpUnwindInfo(pUnInfo);
return;
}
}
void test2()
{
DpcMonitor(0);
}
int _tmain(int argc, _TCHAR* argv[])
{
//test1();
test2();
//MyPeView();
system("pause");
return 0;
}
本文介绍了一个用于深入理解x64结构异常处理(SEH)机制的实用小工具,该工具可能存在一些已知的bug,是作者在探索过程中创建的。

被折叠的 条评论
为什么被折叠?



