1 __try
2 {
3 __try
4 {
5 *((ULONG*)NULL) = 0;
6 }
7 __except((STATUS_INVALID_PARAMETER == GetExceptionCode()) ? EXCEPTION_CONTINUE_SEARCH : EXCEPTION_EXECUTE_HANDLER)
8 {
9 ...
10 }
11 }
12 __finally
13 {
14 ...
15 {
typedef struct _RUNTIME_FUNCTION {
ULONG BeginAddress;
ULONG EndAddress;
ULONG UnwindData;
} RUNTIME_FUNCTION, *PRUNTIME_FUNCTION;
typedef enum _UNWIND_OP_CODES {
UWOP_PUSH_NONVOL = 0,
UWOP_ALLOC_LARGE, // 1
UWOP_ALLOC_SMALL, // 2
UWOP_SET_FPREG, // 3
UWOP_SAVE_NONVOL, // 4
UWOP_SAVE_NONVOL_FAR, // 5
UWOP_SPARE_CODE1, // 6
UWOP_SPARE_CODE2, // 7
UWOP_SAVE_XMM128, // 8
UWOP_SAVE_XMM128_FAR, // 9
UWOP_PUSH_MACHFRAME // 10
} 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;
#define UNW_FLAG_NHANDLER 0x0
#define UNW_FLAG_EHANDLER 0x1
#define UNW_FLAG_UHANDLER 0x2
#define UNW_FLAG_CHAININFO 0x4
typedef struct _UNWIND_INFO {
UCHAR Version : 3;
UCHAR Flags : 5;
UCHAR SizeOfProlog;
UCHAR CountOfCodes;
UCHAR FrameRegister : 4;
UCHAR FrameOffset : 4;
UNWIND_CODE UnwindCode[1];
//
// The unwind codes are followed by an optional DWORD aligned field that
// contains the exception handler address or a function table entry if
// chained unwind information is specified. If an exception handler address
// is specified, then it is followed by the language specified exception
// handler data.
//
// union {
// struct {
// ULONG ExceptionHandler;
// ULONG ExceptionData[];
// };
//
// RUNTIME_FUNCTION FunctionEntry;
// };
//
} 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
KiDispatchException (
IN PEXCEPTION_RECORD ExceptionRecord,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN PKTRAP_FRAME TrapFrame,
IN KPROCESSOR_MODE PreviousMode,
IN BOOLEAN FirstChance
);
#define UNWIND_HISTORY_TABLE_SIZE 12
typedef struct _UNWIND_HISTORY_TABLE_ENTRY {
ULONG64 ImageBase;
PRUNTIME_FUNCTION FunctionEntry;
} UNWIND_HISTORY_TABLE_ENTRY, *PUNWIND_HISTORY_TABLE_ENTRY;
#define UNWIND_HISTORY_TABLE_NONE 0
#define UNWIND_HISTORY_TABLE_GLOBAL 1
#define UNWIND_HISTORY_TABLE_LOCAL 2
typedef struct _UNWIND_HISTORY_TABLE {
ULONG Count;
UCHAR Search;
ULONG64 LowAddress;
ULONG64 HighAddress;
UNWIND_HISTORY_TABLE_ENTRY Entry[UNWIND_HISTORY_TABLE_SIZE];
} UNWIND_HISTORY_TABLE, *PUNWIND_HISTORY_TABLE;
PRUNTIME_FUNCTION
RtlLookupFunctionEntry (
IN ULONG64 ControlPc,
OUT PULONG64 ImageBase,
IN OUT PUNWIND_HISTORY_TABLE HistoryTable OPTIONAL
);
PEXCEPTION_ROUTINE
RtlVirtualUnwind (
IN ULONG HandlerType,
IN ULONG64 ImageBase,
IN ULONG64 ControlPc,
IN PRUNTIME_FUNCTION FunctionEntry,
IN OUT PCONTEXT ContextRecord,
OUT PVOID *HandlerData,
OUT PULONG64 EstablisherFrame,
IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers OPTIONAL
);
EXCEPTION_DISPOSITION
RtlpExecuteHandlerForException (
IN PEXCEPTION_RECORD ExceptionRecord,
IN PVOID EstablisherFrame,
IN OUT PCONTEXT ContextRecord,
IN OUT PVOID DispatcherContext
);
typedef struct _DISPATCHER_CONTEXT {
ULONG64 ControlPc;
ULONG64 ImageBase;
PRUNTIME_FUNCTION FunctionEntry;
ULONG64 EstablisherFrame;
ULONG64 TargetIp;
PCONTEXT ContextRecord;
PEXCEPTION_ROUTINE LanguageHandler;
PVOID HandlerData;
PUNWIND_HISTORY_TABLE HistoryTable;
ULONG ScopeIndex;
ULONG Fill0;
} DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT;
EXCEPTION_DISPOSITION
__C_specific_handler (
IN PEXCEPTION_RECORD pExceptionRecord,
IN PVOID pEstablisherFrame,
IN OUT PCONTEXT pContext,
IN OUT PVOID pDispatcherContext
);
kd> uf nt!__C_specific_handler
nt!__C_specific_handler:
fffff800`008a42d0 mov qword ptr [rsp+10h],rdx ; 在栈上保存 pEstablisherFrame
fffff800`008a42d5 mov rax,rsp
fffff800`008a42d8 sub rsp,88h
fffff800`008a42df mov qword ptr [rax-8],rbx
fffff800`008a42e3 mov qword ptr [rax-10h],rbp
fffff800`008a42e7 mov rbp,qword ptr [r9] ; rbp = pDispatcherContext->ControlPc
fffff800`008a42ea mov qword ptr [rax-18h],rsi
fffff800`008a42ee mov qword ptr [rax-20h],rdi
fffff800`008a42f2 mov qword ptr [rax-28h],r12
fffff800`008a42f6 mov r12,qword ptr [r9+38h] ; r12 = pDispatcherContext->HandlerData
fffff800`008a42fa mov qword ptr [rax-30h],r13
fffff800`008a42fe mov qword ptr [rax-38h],r14
fffff800`008a4302 mov r14,qword ptr [r9+8] ; r14 = pDispatcherContext->ImageBase
fffff800`008a4306 mov qword ptr [rax-40h],r15
fffff800`008a430a mov r13,r9 ; r13 = pDispatcherContext
fffff800`008a430d sub rbp,r14 ; l_OffsetInFunc = pDispatcherContext->ControlPc - pDispatcherContext->ImageBase
fffff800`008a4310 test byte ptr [rcx+4],66h ; pExceptionRecord->ExceptionFlags, EXCEPTION_UNWIND (0x66)
fffff800`008a4314 mov rsi,rdx ; rsi = pEstablisherFrame
fffff800`008a4317 mov r15,rcx ; r15 = pExceptionRecord
< fffff800`008a431a jne nt!__C_specific_handler+0xf5 (fffff800`008a43c5)
:
: -------------------------------------------------------------------
: nt!__C_specific_handler+0x50:
: fffff800`008a4320 movsxd rdi,dword ptr [r9+48h] ; l_ScopeIndex (rdi) = pDispatcherContext->ScopeIndex
: fffff800`008a4324 mov qword ptr [rax-58h],rcx ; [rax-58h] = pExceptionRecord,供给 GetExceptionCode(Information) 使用
: fffff800`008a4328 mov qword ptr [rax-50h],r8 ; [rax-50h] = pContext,供给 GetExceptionCode(Information) 使用
: fffff800`008a432c cmp edi,dword ptr [r12] ; cmp l_ScopeIndex, pDispatcherContext->HandlerData->Count
: fffff800`008a4330 mov rax,rdi ; rax = l_ScopeIndex
:< fffff800`008a4333 jae nt!__C_specific_handler+0x166 (fffff800`008a4436)
::
:: nt!__C_specific_handler+0x69:
:: fffff800`008a4339 add rax,rax ; 这里 *2,下面紧接着 *8,目的是跳过指定数目的 ScopeRecord(大小为16字节)
:: fffff800`008a433c lea rbx,[r12+rax*8+0Ch] ; rbx = &(pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].HandlerAddress)
::
:: nt!__C_specific_handler+0x71:
:: ; 检查 ControlPc 处于哪个 __try 保护域,之步骤一
:: > fffff800`008a4341 mov eax,dword ptr [rbx-8] ; eax = pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].BeginAddress
:: : fffff800`008a4344 cmp rbp,rax ; cmp l_OffsetInFunc, pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].BeginAddress
::< : fffff800`008a4347 jb nt!__C_specific_handler+0xdd (fffff800`008a43ad)
::: :
::: : nt!__C_specific_handler+0x79:
::: : ; 检查 ControlPc 处于哪个 __try 保护域,之步骤二
::: : fffff800`008a4349 mov eax,dword ptr [rbx-4] ; eax = pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].EndAddress
::: : fffff800`008a434c cmp rbp,rax ; cmp l_OffsetInFunc, pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].EndAddress
:::< : fffff800`008a434f jae nt!__C_specific_handler+0xdd (fffff800`008a43ad)
:::: :
:::: : nt!__C_specific_handler+0x81:
:::: : ; 判断是否是 __try/__finally(JumpTarget 为 NULL)。如果是,那么跳转到下一个 ScopeRecord 继续遍历。
:::: : fffff800`008a4351 cmp dword ptr [rbx+4],0 ; cmp pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].JumpTarget, NULL
::::< : fffff800`008a4355 je nt!__C_specific_handler+0xdd (fffff800`008a43ad)
::::: :
::::: : nt!__C_specific_handler+0x87:
::::: : ; 到这里,已经找到与异常地址最匹配的 __try/__except
::::: : fffff800`008a4357 mov eax,dword ptr [rbx] ; eax = pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].HandlerAddress
::::: : fffff800`008a4359 cmp eax,1 ; cmp pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].HandlerAddress, EXCEPTION_EXECUTE_HANDLER (0x1)
:::::< : fffff800`008a435c je nt!__C_specific_handler+0xa3 (fffff800`008a4373) ; 如果返回 EXCEPTION_EXECUTE_HANDLER 则跳转
:::::: :
:::::: : nt!__C_specific_handler+0x8e:
:::::: : ; 是 __try/__except,且过滤域并不是 EXCEPTION_EXECUTE_HANDLER,执行 HandlerAddress
:::::: : ; (注:HandlerAddress 指向的函数仍有可能会返回 EXCEPTION_EXECUTE_HANDLER)
:::::: : fffff800`008a435e lea rcx,[rsp+30h]
:::::: : fffff800`008a4363 add rax,r14 ; rax = pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].HandlerAddress + pDispatcherContext->ImageBase
:::::: : fffff800`008a4366 mov rdx,rsi ; rdx = pEstablisherFrame
:::::: : fffff800`008a4369 call rax ; 调用 EXCEPT_FILTER
:::::: : fffff800`008a436b test eax,eax
::::::< : fffff800`008a436d js nt!__C_specific_handler+0xee (fffff800`008a43be) ; 返回 EXCEPTION_CONTINUE_EXECUTION (-1) 则跳转
::::::: :
::::::: : nt!__C_specific_handler+0x9f:
::::::: : fffff800`008a436f test eax,eax
:::::::<: fffff800`008a4371 jle nt!__C_specific_handler+0xdd (fffff800`008a43ad) ; 返回 EXCEPTION_CONTINUE_SEARCH (0) 则跳转
:::::::::
::::::::: nt!__C_specific_handler+0xa3:
::::::::: ; 返回的是 EXCEPTION_EXECUTE_HANDLER
:::::>::: fffff800`008a4373 mov ecx,dword ptr [rbx+4] ; ecx = pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].JumpTarget
::::: ::: fffff800`008a4376 mov r8d,1
::::: ::: fffff800`008a437c mov rdx,rsi ; rdx = pEstablisherFrame
::::: ::: fffff800`008a437f add rcx,r14 ; rcx = pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].JumpTarget + pDispatcherContext->ImageBase
::::: ::: fffff800`008a4382 call nt!_NLG_Notify (fffff800`008b1460)
::::: ::: fffff800`008a4387 mov rax,qword ptr [r13+40h] ; rax = pDispatcherContext->HistoryTable
::::: ::: fffff800`008a438b mov edx,dword ptr [rbx+4] ; edx = pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].JumpTarget
::::: ::: fffff800`008a438e movsxd r9,dword ptr [r15] ; r9 = pExceptionRecord->ExceptionCode
::::: ::: fffff800`008a4391 mov qword ptr [rsp+28h],rax ; _ARG_6 = pDispatcherContext->HistoryTable
::::: ::: fffff800`008a4396 mov rax,qword ptr [r13+28h] ; rax = pDispatcherContext->ContextRecord
::::: ::: fffff800`008a439a add rdx,r14 ; rdx = pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].JumpTarget + pDispatcherContext->ImageBase
::::: ::: fffff800`008a439d mov r8,r15 ; r8 = pExceptionRecord
::::: ::: fffff800`008a43a0 mov rcx,rsi ; rcx = pEstablisherFrame
::::: ::: fffff800`008a43a3 mov qword ptr [rsp+20h],rax ; _ARG_5 = pDispatcherContext->ContextRecord
::::: ::: fffff800`008a43a8 call nt!RtlUnwindEx (fffff800`00891e80) ; 这里不会返回
::::: ::: ; RtlUnwindEx(pEstablisherFrame,
::::: ::: ; pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].JumpTarget + pDispatcherContext->ImageBase
::::: ::: ; pExceptionRecord,
::::: ::: ; pExceptionRecord->ExceptionCode
::::: ::: ; pDispatcherContext->ContextRecord,
::::: ::: ; pDispatcherContext->HistoryTable)
::::: :::
::::: ::: nt!__C_specific_handler+0xdd:
::>>> :>: fffff800`008a43ad inc edi ; l_ScopeIndex += 1
:: : : fffff800`008a43af add rbx,10h ; 调整到下一个 ScopeRecord::HandlerAddress
:: : : fffff800`008a43b3 cmp edi,dword ptr [r12] ; cmp l_ScopeIndex, pDispatcherContext->HandlerData->Count
:: : < fffff800`008a43b7 jb nt!__C_specific_handler+0x71 (fffff800`008a4341)
:: :
:: : nt!__C_specific_handler+0xe9:
:: : ; pDispatcherContext->HandlerData 遍历完毕
::< : fffff800`008a43b9 jmp nt!__C_specific_handler+0x166 (fffff800`008a4436)
::: :
::: : nt!__C_specific_handler+0xee:
::: > fffff800`008a43be xor eax,eax ; eax = ExceptionContinueExecution
:::< fffff800`008a43c0 jmp nt!__C_specific_handler+0x16b (fffff800`008a443b)
::::
:::: -------------------------------------------------------------------------------------
:::: nt!__C_specific_handler+0xf5:
:::: ; 设置了 EXCEPTION_UNWIND,当前是展开过程
>::: fffff800`008a43c5 movsxd rdi,dword ptr [r9+48h] ; l_ScopeIndex (rdi) = pDispatcherContext->ScopeIndex
::: fffff800`008a43c9 mov rsi,qword ptr [r9+20h] ; rsi = pDispatcherContext->TargetIp
::: fffff800`008a43cd sub rsi,r14 ; rsi = pDispatcherContext->TargetIp - pDispatcherContext->ImageBase
::: fffff800`008a43d0 cmp edi,dword ptr [r12] ; cmp l_ScopeIndex, pDispatcherContext->HandlerData->Count
::: fffff800`008a43d4 mov rax,rdi ; rax = l_ScopeIndex
:::< fffff800`008a43d7 jae nt!__C_specific_handler+0x166 (fffff800`008a4436)
::::
:::: nt!__C_specific_handler+0x109:
:::: fffff800`008a43d9 add rax,rax ;
:::: fffff800`008a43dc lea rbx,[r12+rax*8+8] ; rbx = &(pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].EndAddress)
::::
:::: nt!__C_specific_handler+0x111:
:::: ; 检查 ControlPc 处于哪个 __try 保护域,之步骤一
:::: > fffff800`008a43e1 mov eax,dword ptr [rbx-4] ; eax = pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].BeginAddress
:::: : fffff800`008a43e4 cmp rbp,rax ; cmp l_OffsetInFunc, pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].BeginAddress
::::< : fffff800`008a43e7 jb nt!__C_specific_handler+0x15a (fffff800`008a442a)
::::: :
::::: : nt!__C_specific_handler+0x119:
::::: : ; 检查 ControlPc 处于哪个 __try 保护域,之步骤二
::::: : fffff800`008a43e9 mov ecx,dword ptr [rbx] ; ecx = pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].EndAddress
::::: : fffff800`008a43eb cmp rbp,rcx ; cmp l_OffsetInFunc, pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].EndAddress
:::::< : fffff800`008a43ee jae nt!__C_specific_handler+0x15a (fffff800`008a442a)
:::::: :
:::::: : nt!__C_specific_handler+0x120:
:::::: : ; 到这里,已经找到与异常地址匹配的最内层(如果有多层) __try/__except
:::::: : fffff800`008a43f0 cmp rsi,rax ; cmp pDispatcherContext->TargetIp - pDispatcherContext->ImageBase, pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].BeginAddress
::::::< : fffff800`008a43f3 jb nt!__C_specific_handler+0x131 (fffff800`008a4401)
::::::: :
::::::: : nt!__C_specific_handler+0x125:
::::::: : fffff800`008a43f5 cmp rsi,rcx ; cmp pDispatcherContext->TargetIp - pDispatcherContext->ImageBase, pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].EndAddress
:::::::< : fffff800`008a43f8 ja nt!__C_specific_handler+0x131 (fffff800`008a4401)
:::::::: :
:::::::: : nt!__C_specific_handler+0x12a:
:::::::: : ; 如果标记了 EXCEPTION_TARGET_UNWIND,说明是最后一个需要局部展开的函数。但是该次局部展开只展开到 EXCEPT_HANDLER(不包含 EXCEPT_HANDLER),所以需要判断 TargetIp
:::::::: : fffff800`008a43fa test byte ptr [r15+4],20h ; test pExceptionRecord->ExceptionFlags, EXCEPTION_TARGET_UNWIND (0x20)
::::::::< : fffff800`008a43ff jne nt!__C_specific_handler+0x166 (fffff800`008a4436)
::::::::: :
::::::::: : nt!__C_specific_handler+0x131:
::::::>>: : fffff800`008a4401 mov eax,dword ptr [rbx+8] ; eax = pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].JumpTarget
:::::: : : fffff800`008a4404 test eax,eax ; 判断 pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].JumpTarget 是否为 NULL,即是否是 __try/__finally
:::::: :< : fffff800`008a4406 je nt!__C_specific_handler+0x13f (fffff800`008a440f) ; 如果是 __try/__finally 则跳转
:::::: :: :
:::::: :: : nt!__C_specific_handler+0x138:
:::::: :: : fffff800`008a4408 cmp rsi,rax ; cmp pDispatcherContext->TargetIp, pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].JumpTarget
:::::: ::< : fffff800`008a440b je nt!__C_specific_handler+0x166 (fffff800`008a4436)
:::::: ::: :
:::::: ::: : nt!__C_specific_handler+0x13d:
:::::: :::<: fffff800`008a440d jmp nt!__C_specific_handler+0x15a (fffff800`008a442a)
:::::: :::::
:::::: ::::: nt!__C_specific_handler+0x13f:
:::::: ::::: ; 注意这里是先修改 pDispatcherContext->ScopeIndex,然后调用 EXCEPT_HANDLER。这样如果 EXCEPT_HANDLER 触发异常,后续展开就会跳过这个 EXCEPT_HANDLER。
:::::: :>::: fffff800`008a440f mov rdx,qword ptr [rsp+98h]
:::::: : ::: fffff800`008a4417 lea eax,[rdi+1] ; eax = l_ScopeIndex + 1
:::::: : ::: fffff800`008a441a mov cl,1
:::::: : ::: fffff800`008a441c mov dword ptr [r13+48h],eax ; pDispatcherContext->ScopeIndex = eax
:::::: : ::: fffff800`008a4420 mov r8d,dword ptr [rbx+4] ; r8d = pDispatcherContext->HandlerData->ScopeRecord[i].HandlerAddress
:::::: : ::: fffff800`008a4424 add r8,r14 ; r8 = pDispatcherContext->HandlerData->ScopeRecord[i].HandlerAddress + pDispatcherContext->ImageBase
:::::: : ::: fffff800`008a4427 call r8 ; 调用 __finally 处理块,会返回(注:对于 __try/__finally,HandlerAddress 保存的是 __finally 代码块的 RVA)
:::::: : :::
:::::: : ::: nt!__C_specific_handler+0x15a:
::::>> : :>: fffff800`008a442a inc edi ; l_ScopeIndex += 1
:::: : : : fffff800`008a442c add rbx,10h ; 调整到下一个 ScopeRecord::HandlerAddress
:::: : : : fffff800`008a4430 cmp edi,dword ptr [r12] ; cmp l_ScopeIndex, pDispatcherContext->HandlerData->Count
:::: : : < fffff800`008a4434 jb nt!__C_specific_handler+0x111 (fffff800`008a43e1)
:::: : :
:::: : : nt!__C_specific_handler+0x166:
>>:> > > fffff800`008a4436 mov eax,1 ; eax = ExceptionContinueSearch (0n1)
:
: nt!__C_specific_handler+0x16b:
> fffff800`008a443b mov r15,qword ptr [rsp+48h]
fffff800`008a4440 mov r14,qword ptr [rsp+50h]
fffff800`008a4445 mov r13,qword ptr [rsp+58h]
fffff800`008a444a mov r12,qword ptr [rsp+60h]
fffff800`008a444f mov rdi,qword ptr [rsp+68h]
fffff800`008a4454 mov rsi,qword ptr [rsp+70h]
fffff800`008a4459 mov rbp,qword ptr [rsp+78h]
fffff800`008a445e mov rbx,qword ptr [rsp+80h]
fffff800`008a4466 add rsp,88h
fffff800`008a446d ret
1 VOID SehTest()
2 {
3 __try // 1
4 {
5 }
6 __except()
7 {
8 }
9
10 __try // 2
11 {
12 __try // 3
13 {
14 ...
15 }
16 __except()
17 {
18 }
19 }
20 __except()
21 {
22 }
23
24 __try // 4
25 {
26 }
27 __finally()
28 {
29 }
30}
VOID
RtlUnwindEx (
IN PVOID TargetFrame OPTIONAL,
IN PVOID TargetIp OPTIONAL,
IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL,
IN PVOID ReturnValue,
IN PCONTEXT OriginalContext,
IN PUNWIND_HISTORY_TABLE HistoryTable OPTIONAL
);
__try
{
ExRaiseStatus(STATUS_INVALID_PARAMETER);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
+---------------------------------------+
| ...... |
| RtlRaiseStatus |调 |
| RtlDispatchException |用 |-> ThreadContext &
| RtlpExecuteHandlerForException |方 | TargetIp = ExceptionHandler
| __C_specific_handler |向 |
| RtlUnwindEx v |
| |
+---------------------------------------+
+---------------------------------------+
+---------------------------------------+
| ...... | | ...... |
| RtlRaiseStatus |调 | | RtlRaiseStatus |调 |
| RtlDispatchException |用 |-> ThreadContext & | RtlDispatchException |用 |-> ThreadContext_Copy &
| RtlpExecuteHandlerForException |方 | TargetIp = ExceptionHandler | RtlpExecuteHandlerForException |方 | TargetIp = ExceptionHandler
| __C_specific_handler |向 | | __C_specific_handler |向 |
| RtlUnwindEx v | | RtlUnwindEx v |
| | | |
+---------------------------------------+ +---------------------------------------+
+---------------------------------------+
+---------------------------------------+
| ..... | | ...... |
| RtlRaiseStatus |调 | | RtlRaiseStatus ^展 |
| RtlDispatchException |用 |-> ThreadContext | RtlDispatchException |开 |-> ThreadContext_Copy &
| RtlpExecuteHandlerForException |方 | TargetIp = ExceptionHandler | RtlpExecuteHandlerForException |方 | TargetIp = ExceptionHandler
| __C_specific_handler |向 | | __C_specific_handler |向 |
| RtlUnwindEx v | | RtlUnwindEx | |
| | | |
+---------------------------------------+ +---------------------------------------+
+---------------------------------------+
| ...... |
| EXCEPT_HANDLER |-> ThreadContext (ThreadContext.Rip = TargetIp)
| |
+---------------------------------------+
EXCEPTION_DISPOSITION
RtlpExecuteHandlerForUnwind (
IN PEXCEPTION_RECORD ExceptionRecord,
IN PVOID EstablisherFrame,
IN OUT PCONTEXT ContextRecord,
IN OUT PVOID DispatcherContext
);
1 VOID SehTest()
2 {
3 __try
4 {
5 ExRaiseStatus();
6 }
7 __except(ExRaiseStatus(), EXCEPTION_CONTINUE_SEARCH) // EXCEPT_FILTER_1
8 { // EXCEPT_HANDLER_1
9 }
10 }
11
12 VOID Caller()
13 {
14 __try
15 {
16 SehTest();
17 }
18 __except(EXCEPTION_EXECUTE_HANDLER) // EXCEPT_FILTER_2
19 { // EXCEPT_HANDLER_2
20 }
21 }
(1) Caller | E & __C_specific_handler$1
(2) SehTest | E & __C_specific_handler$2
(3) ExRaiseStatus#1 | N
(4) RtlDispatchException#1 | N
(5) RtlpExecuteHandlerForException#1 | EU & RtlpExceptionHandler$5
(6) __C_specific_handler$2 | N
(7) EXCEPT_FILTER_1#1 | N
(1) Caller | E & __C_specific_handler$1
(2) SehTest | E & __C_specific_handler$2
(3) ExRaiseStatus#1 | N
(4) RtlDispatchException#1 | N
(5) RtlpExecuteHandlerForException#1 | EU & RtlpExceptionHandler$5
(6) __C_specific_handler$2 | N
(7) EXCEPT_FILTER_1#1 | N
(8) ExRaiseStatus#2 | N
(9) RtlDispatchException#2 | N
(10) RtlpExecuteHandlerForException#2 | EU & RtlpExceptionHandler$10
(11) __C_specific_handler$2 | N
(12) EXCEPT_FILTER_1#2 | N
(13) ExRaiseStatus#3 | N
1 VOID SehTest()
2 {
3 __try
4 {
5 ExRaiseStatus();
6 }
7 __finally
8 { // FINALLY_HANDLER_1
9 ExRaiseStatus();
10 }
11 }
12
13 VOID Caller()
14 {
15 __try
16 {
17 SehTest();
18 }
19 __except(EXCEPTION_EXECUTE_HANDLER) // EXCEPT_FILTER_2
20 { // EXCEPT_HANDLER_2
21 }
22 }
(1) Caller | E & __C_specific_handler$1
(2) SehTest | U & __C_specific_handler$2
(3) ExRaiseStatus#1 | N
(4) RtlDispatchException#1 | N
(5) RtlpExecuteHandlerForException#1 | EU & RtlpExceptionHandler$5
(6) __C_specific_handler$1 | N
(7) RtlUnwindEx#1 | N
(8) RtlpExecuteHandlerForUnwind#1 | EU & RtlpUnwindHandler$8
(9) __C_specific_handler$2 | N
(10) FINALLY_HANDLER_1 | N
(11) ExRaiseStatus#2 | N
(1) Caller | E & __C_specific_handler$1
(2) SehTest | U & __C_specific_handler$2,但没有 EXCEPT_HANDLER
(3) ExRaiseStatus#1 | N
(4) RtlDispatchException#1 | N
(5) RtlpExecuteHandlerForException#1 | EU & RtlpExceptionHandler$6
(6) __C_specific_handler$1 | N
(7) RtlUnwindEx#1 | N
(8) RtlpExecuteHandlerForUnwind#1 | EU & RtlpUnwindHandler$8
(9) __C_specific_handler$2 | N
(10) FINALLY_HANDLER#1 | N
(11) ExRaiseStatus#2 | N
(12) RtlDispatchException#2 | N
(13) RtlpExecuteHandlerForException#2 | EU & RtlpExceptionHandler
(14) __C_specific_handler$1 | N
(15) RtlUnwindEx | N
VOID SehTest()
{
__try
{
__try
{
ExRaiseStatus(STATUS_INVALID_PARAMETER);
DbgPrint("%u [%s] __try \n", __LINE__, __FILE__);
}
__except((STATUS_INVALID_PARAMETER == GetExceptionCode()) ? EXCEPTION_CONTINUE_SEARCH : EXCEPTION_EXECUTE_HANDLER)
{
DbgPrint("%u [%s] __except \n", __LINE__, __FILE__);
}
}
__finally
DbgPrint("%u [%s] __finally \n", __LINE__, __FILE__);
}
}
kd> uf passthrough!SehTest
PassThrough!SehTest:
fffffadf`f1100020 sub rsp,38h
fffffadf`f1100024 mov ecx,0C000000Dh
fffffadf`f1100029 call qword ptr [PassThrough!_imp_ExRaiseStatus (fffffadf`f1101050)]
fffffadf`f110002f lea r8,[PassThrough! ?? ::FNODOBFM::`string‘ (fffffadf`f1100500)]
fffffadf`f1100036 mov edx,39h
fffffadf`f110003b lea rcx,[PassThrough! ?? ::FNODOBFM::`string‘ (fffffadf`f1100540)]
fffffadf`f1100042 call PassThrough!DbgPrint (fffffadf`f11004a6)
fffffadf`f1100047 jmp PassThrough!SehTest+0x42 (fffffadf`f1100062)
PassThrough!SehTest+0x42:
fffffadf`f1100062 lea r8,[PassThrough! ?? ::FNODOBFM::`string‘ (fffffadf`f1100500)]
fffffadf`f1100069 mov edx,42h
fffffadf`f110006e lea rcx,[PassThrough! ?? ::FNODOBFM::`string‘ (fffffadf`f1100570)]
fffffadf`f1100075 call PassThrough!DbgPrint (fffffadf`f11004a6)
fffffadf`f110007a add rsp,38h
fffffadf`f110007e ret
!boxr.unwindinfo module-name unwindinfo_addr
功能:
用于查询指定 UNWIND_INFO 结构的详细信息。
参数说明:
module-name —— 待查询的 UNWIND_INFO 结构对应函数的模块名
unwindinfo_addr —— UNWIND_INFO 结构的绝对地址
!boxr.rtfn option module runtimefunction_addr
功能:
用于查询指定 RUNTIME_FUNCTION 结构的详细信息。(rtfn 表示 RunTime_FunctioN)
参数说明:
option —— 参数选项,目前支持两种:
/a 表示 module 参数为模块基地址
/n 表示 module 参数为模块名称
module —— RUNTIME_FUNCTION 结构对应函数所在的模块,具体形式根据 option 而定。
runtimefunction_addr —— 需要查询的 RUNTIME_FUNCTION 结构体的绝对地址。支持 @rax 操作方式,但不支持复杂的组合,比如 @rax+8。
VOID SehTest()
{
__try
{
DbgPrint("%u [%s] __try \n", __LINE__, __FILE__);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DbgPrint("%u [%s] __except \n", __LINE__, __FILE__);
}
__try
{
__try
{
__try
{
CollidedUnwind();
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DbgPrint("%u [%s] __except \n", __LINE__, __FILE__);
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DbgPrint("%u [%s] __except \n", __LINE__, __FILE__);
}
}
__finally
{
DbgPrint("%u [%s] __finally \n", __LINE__, __FILE__);
}
__try
{
DbgPrint("%u [%s] __try \n", __LINE__, __FILE__);
__try
{
DbgPrint("%u [%s] __try \n", __LINE__, __FILE__);
}
__finally
{
DbgPrint("%u [%s] __finally \n", __LINE__, __FILE__);
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DbgPrint("%u [%s] __except \n", __LINE__, __FILE__);
}
return;
}
kd> .fnent passthrough!SehTest
Debugger function entry 00000000`00758210 for:
(fffffadf`f135d080) PassThrough!SehTest | (fffffadf`f135d180) PassThrough!LeafTest
Exact matches:
PassThrough!SehTest (void)
BeginAddress = 00000000`00001080
EndAddress = 00000000`00001175
UnwindInfoAddress = 00000000`000026b8
Unwind info at fffffadf`f135e6b8, 10 bytes
version 1, flags 3, prolog 4, codes 1
handler routine: PassThrough!_C_specific_handler (fffffadf`f135d5de), data 6
00: offs 4, unwind op 2, op info 4 UWOP_ALLOC_SMALL.
kd> !boxr.unwindinfo passthrough fffffadf`f135e6b8
_UNWIND_INFO for fffffadff135e6b8
Flags:
EU
ExceptionRoutine:
PassThrough!_C_specific_handler (fffffadf`f135d5de)
ScopeTable:
Count: 6
ScopeRecord[0] (fffffadff135e6c8)
BeginAddress:
PassThrough!SehTest+0x4 (fffffadf`f135d084)
EndAddress:
PassThrough!SehTest+0x1e (fffffadf`f135d09e)
HandlerAddress:
PassThrough!SehTest$filt$0 (fffffadf`f135d8a0)
JumpTarget:
PassThrough!SehTest+0x1e (fffffadf`f135d09e)
[省略中间3个 ScopeRecord 成员]
ScopeRecord[5] (fffffadff135e718)
BeginAddress:
PassThrough!SehTest+0x8b (fffffadf`f135d10b)
EndAddress:
PassThrough!SehTest+0xd7 (fffffadf`f135d157)
HandlerAddress:
PassThrough!SehTest$filt$5 (fffffadf`f135d960)
JumpTarget:
PassThrough!SehTest+0xd7 (fffffadf`f135d157)
kd> !box.rtfn /n passThrough @rax
_RUNTIME_FUNCTION for fffffadff1113000
BeginAddress:
PassThrough!CollidedUnwind (fffffadf`f1110020)
EndAddress:
PassThrough!CollidedUnwind+0x38 (fffffadf`f1110058)
UnwindData:
fffffadff1111688
_UNWIND_INFO for fffffadff1111688
Flags:
U
ExceptionRoutine:
PassThrough!_C_specific_handler (fffffadf`f11104ee)
ScopeTable:
Count: 1
ScopeRecord[0] (fffffadff1111698)
BeginAddress:
PassThrough!CollidedUnwind+0x4 (fffffadf`f1110024)
EndAddress:
PassThrough!CollidedUnwind+0x10 (fffffadf`f1110030)
HandlerAddress:
PassThrough!CollidedUnwind$fin$0 (fffffadf`f1110750)
JumpTarget:
0
VOID
RtlUnwindEx (
/* rcx */ IN PVOID pEstablisherFrame OPTIONAL,
/* rdx */ IN PVOID pJumpTargetIp OPTIONAL,
/* r8 */ IN PEXCEPTION_RECORD pExceptionRecord OPTIONAL,
/* r9 */ IN PVOID ReturnValue,
/* rsp+28 */ IN PCONTEXT pOriginalContext,
/* rsp+30 */ IN PUNWIND_HISTORY_TABLE pHistoryTable OPTIONAL
);
kd> uf nt!RtlUnwindEx
nt!RtlUnwindEx:
fffff800`00891e70 mov qword ptr [rsp+20h],r9
fffff800`00891e75 mov qword ptr [rsp+18h],r8
fffff800`00891e7a mov qword ptr [rsp+10h],rdx
fffff800`00891e7f mov rax,rsp
fffff800`00891e82 sub rsp,678h
fffff800`00891e89 mov qword ptr [rax-8],rbx
fffff800`00891e8d mov qword ptr [rax-10h],rbp
fffff800`00891e91 mov qword ptr [rax-18h],rsi
fffff800`00891e95 mov rsi,qword ptr [rsp+6A0h] ; rsi = pOriginalContext
fffff800`00891e9d mov qword ptr [rax-20h],rdi
fffff800`00891ea1 mov qword ptr [rax-28h],r12
fffff800`00891ea5 mov qword ptr [rax-40h],r15
fffff800`00891ea9 mov rbp,rcx
fffff800`00891eac mov r15,rdx
fffff800`00891eaf lea rdx,[rsp+40h] ; rsp+40 为 l_HighLimit
fffff800`00891eb4 lea rcx,[rsp+50h] ; rsp+50 为 l_LowLimit
fffff800`00891eb9 mov rbx,r8
fffff800`00891ebc mov rdi,rsi
fffff800`00891ebf lea r12,[rax-518h] ; r12 = &l_Context
fffff800`00891ec6 call nt!RtlpGetStackLimits (fffff800`00890da0)
fffff800`00891ecb mov rcx,rsi
fffff800`00891ece call nt!RtlCaptureContext (fffff800`008bd150)
fffff800`00891ed3 mov rax,qword ptr [rsp+6A8h] ; rax = pHistoryTable
fffff800`00891edb test rax,rax
< fffff800`00891ede je nt!RtlUnwindEx+0x74 (fffff800`00891ee4)
.
. nt!RtlUnwindEx+0x70:
. fffff800`00891ee0 mov byte ptr [rax+4],1 ; pHistoryTable->Search = UNWIND_HISTORY_TABLE_GLOBAL
.
. nt!RtlUnwindEx+0x74:
> fffff800`00891ee4 xor ecx,ecx
fffff800`00891ee6 test rbx,rbx ; 判断 pExceptionRecord 是否为 NULL
< fffff800`00891ee9 jne nt!RtlUnwindEx+0xbc (fffff800`00891f2c)
.
. nt!RtlUnwindEx+0x7b:
. ; pExceptionRecord 等于 NULL
. fffff800`00891eeb mov rax,qword ptr [rsi+0F8h] ; rax = pOriginalContext->Rip
. fffff800`00891ef2 lea rbx,[rsp+0C0h] ; rbx = &l_ExceptionRecord
. fffff800`00891efa mov dword ptr [rsp+0C0h],0C0000027h ; l_ExceptionRecord.ExceptionCode = STATUS_UNWIND (0xC0000027)
. fffff800`00891f05 mov qword ptr [rsp+0D0h],rax ; l_ExceptionRecord.ExceptionAddress = pOriginalContext->Rip
. fffff800`00891f0d mov rax,qword ptr [rsp+6A8h] ; rax = pHistoryTable
. fffff800`00891f15 mov qword ptr [rsp+690h],rbx ; [r8-home] = &l_ExceptionRecord ????
. fffff800`00891f1d mov qword ptr [rsp+0C8h],rcx ; l_ExceptionRecord.ExceptionRecord = NULL
. fffff800`00891f25 mov dword ptr [rsp+0D8h],ecx ; l_ExceptionRecord.NumberParameters = 0
.
. nt!RtlUnwindEx+0xbc:
> fffff800`00891f2c mov rbx,qword ptr [rsp+680h] ; rbx = &[rcx-home]
fffff800`00891f34 mov esi,2 ; l_ExceptionFlags(esi) = EXCEPTION_UNWINDING (2)
fffff800`00891f39 mov ecx,6 ; ecx = EXCEPTION_EXIT_UNWIND (6)
fffff800`00891f3e test rbp,rbp ; 判断 pEstablisherFrame 是否为 NULL
fffff800`00891f41 mov qword ptr [rsp+648h],r13 ; 保存 r13
fffff800`00891f49 mov qword ptr [rsp+640h],r14 ; 保存 r14
fffff800`00891f51 cmove esi,ecx ; if (NULL == pEstablisherFrame) { l_ExceptionFlags = EXCEPTION_EXIT_UNWIND (6) }
fffff800`00891f54 xchg ax,ax
fffff800`00891f58 xchg ax,ax
fffff800`00891f5c xchg ax,ax
nt!RtlUnwindEx+0xf0:
> fffff800`00891f60 mov r13,qword ptr [rdi+0F8h] ; r13 = pOriginalContext->Rip
. fffff800`00891f67 lea rdx,[rsp+60h] ; rdx = &l_pImageBase
. fffff800`00891f6c mov r8,rax ; r8 = pHistoryTable
. fffff800`00891f6f mov rcx,r13
. fffff800`00891f72 mov qword ptr [rsp+68h],r13
. fffff800`00891f77 call nt!RtlLookupFunctionEntry (fffff800`00890e60)
. ; l_pFunctionEntry = RtlLookupFunctionEntry(pOriginalContext->Rip,
. ; &l_pImageBase,
. ; pHistoryTable)
. fffff800`00891f7c test rax,rax ; 判断 l_pFunctionEntry (eax) 是否为 NULL
. fffff800`00891f7f mov r14,rax ; r14 = l_pFunctionEntry
< . fffff800`00891f82 je nt!RtlUnwindEx+0x3ab (fffff800`0089221b)
. .
. . nt!RtlUnwindEx+0x118:
. . fffff800`00891f88 mov rdx,rdi ; rdx = pOriginalContext
. . fffff800`00891f8b mov rcx,r12 ; rcx = &l_Context
. . fffff800`00891f8e call nt!RtlpCopyContext (fffff800`00891080)
. . ; RtlpCopyContext(&l_Context, pOriginalContext)
. . fffff800`00891f93 mov rdx,qword ptr [rsp+60h] ; rdx = l_pImageBase
. . fffff800`00891f98 mov qword ptr [rsp+38h],0 ; _ARG_8 = 0
. . fffff800`00891fa1 lea rax,[rsp+680h] ; rax = &[rcx-home],这里被用作局部变量 l_pEstablisherFrame 空间
. . fffff800`00891fa9 mov r9,r14 ; r9 = l_pFunctionEntry
. . fffff800`00891fac mov r8,r13 ; r8 = pOriginalContext->Rip
. . fffff800`00891faf mov qword ptr [rsp+30h],rax ; _ARG7 = &l_pEstablisherFrame
. . fffff800`00891fb4 lea rax,[rsp+58h] ; rax = &l_pHandlerData
. . fffff800`00891fb9 mov ecx,2 ; ecx = UNW_FLAG_UHANDLER (2)
. . fffff800`00891fbe mov qword ptr [rsp+28h],rax ; _ARG_6 = &l_pHandlerData
. . fffff800`00891fc3 mov qword ptr [rsp+20h],r12 ; _ARG_5 = &l_Context
. . fffff800`00891fc8 call nt!RtlVirtualUnwind (fffff800`00891380)
. . ; l_pExceptionRoutine = RtlVirtualUnwind(UNW_FLAG_UHANDLER,
. . ; l_pImageBase,
. . ; pOriginalContext->Rip,
. . ; l_pFunctionEntry,
. . ; &l_Context,
. . ; &l_pHandlerData,
. . ; &l_pEstablisherFrame,
. . ; NULL);
. . fffff800`00891fcd mov rbx,qword ptr [rsp+680h] ; rbx = l_pEstablisherFrame
. . fffff800`00891fd5 mov rcx,rax ; rcx = l_pExceptionRoutine
. . fffff800`00891fd8 mov qword ptr [rsp+48h],rax
. . fffff800`00891fdd test bl,7 ; 检查 l_pEstablisherFrame 是否对齐
.< . fffff800`00891fe0 jne nt!RtlUnwindEx+0x431 (fffff800`008922a1)
.. .
.. . nt!RtlUnwindEx+0x176:
.. . fffff800`00891fe6 cmp rbx,qword ptr [rsp+50h] ; cmp l_pEstablisherFrame, l_LowLimit
..< . fffff800`00891feb jb nt!RtlUnwindEx+0x184 (fffff800`00891ff4)
... .
... . nt!RtlUnwindEx+0x17d:
... . fffff800`00891fed cmp rbx,qword ptr [rsp+40h] ; cmp l_pEstablisherFrame, l_HighLimit
...< . fffff800`00891ff2 jb nt!RtlUnwindEx+0x1d3 (fffff800`00892043)
.... .
.... . nt!RtlUnwindEx+0x184:
.... . ; 检查 l_pEstablisherFrame 是否合法
..>. . fffff800`00891ff4 mov cl,byte ptr gs:[20DEh] ; cl = _KPCR->DpcRoutineActive
.. . . fffff800`00891ffc test cl,cl ; 判断当前是否在执行 DPC
.< . . fffff800`00891ffe jne nt!RtlUnwindEx+0x431 (fffff800`008922a1) ; 如果是在执行 DPC 则失败???
.. . .
.. . . nt!RtlUnwindEx+0x194:
.. . . fffff800`00892004 mov rcx,qword ptr [rsp+40h] ; rcx = l_HighLimit
.. . . fffff800`00892009 mov rax,qword ptr [rcx-28h] ; rax = l_KernelStackCtrl->Previous.StackBase
.. . . fffff800`0089200d test rax,rax ; 判断 l_KernelStackCtrl->Previous.StackBase 是否为 NULL
.< . . fffff800`00892010 je nt!RtlUnwindEx+0x431 (fffff800`008922a1)
.. . .
.. . . nt!RtlUnwindEx+0x1a6:
.. . . fffff800`00892016 mov rdx,qword ptr [rcx-20h] ; rdx = l_KernelStackCtrl->Previous.StackLimit
.. . . fffff800`0089201a mov rbx,qword ptr [rsp+680h] ; rbx = l_pEstablisherFrame
.. . . fffff800`00892022 cmp rbx,rdx ; cmp l_pEstablisherFrame, l_KernelStackCtrl->Previous.StackLimit
.< . . fffff800`00892025 jb nt!RtlUnwindEx+0x431 (fffff800`008922a1)
.. . .
.. . . nt!RtlUnwindEx+0x1bb:
.. . . fffff800`0089202b cmp rbx,rax ; cmp l_pEstablisherFrame, l_KernelStackCtrl->Previous.StackBase
.< . . fffff800`0089202e jae nt!RtlUnwindEx+0x431 (fffff800`008922a1)
.. . .
.. . . nt!RtlUnwindEx+0x1c4:
.. . . fffff800`00892034 mov rcx,qword ptr [rsp+48h] ; rcx = l_pExceptionRoutine
.. . . fffff800`00892039 mov qword ptr [rsp+50h],rdx ; l_LowLimit = l_KernelStackCtrl->Previous.StackLimit
.. . . fffff800`0089203e mov qword ptr [rsp+40h],rax ; l_HighLimit = l_KernelStackCtrl->Previous.StackBase
.. . .
.. . . nt!RtlUnwindEx+0x1d3:
.. > . fffff800`00892043 test rbp,rbp ; 判断 pEstablisherFrame 是否为 NULL
.. < . fffff800`00892046 je nt!RtlUnwindEx+0x1e1 (fffff800`00892051)
.. . .
.. . . nt!RtlUnwindEx+0x1d8:
.. . . fffff800`00892048 cmp rbp,rbx ; cmp pEstablisherFrame, l_pEstablisherFrame
.< . . fffff800`0089204b jb nt!RtlUnwindEx+0x431 (fffff800`008922a1)
.. . .
.. . . nt!RtlUnwindEx+0x1e1:
.. > . fffff800`00892051 test rcx,rcx ; 判断 l_pExceptionRoutine 是否为 NULL
.. < . fffff800`00892054 je nt!RtlUnwindEx+0x39b (fffff800`0089220b)
.. . .
.. . . nt!RtlUnwindEx+0x1ea:
.. . . fffff800`0089205a mov r13,qword ptr [rsp+58h] ; r13 = l_pHandlerData
.. . . fffff800`0089205f mov qword ptr [rsp+90h],r15 ; [rsp+90] = pJumpTargetIp
.. . . fffff800`00892067 xor r15d,r15d
.. . . fffff800`0089206a xchg ax,ax
.. . . fffff800`0089206d xchg ax,ax
.. . .
.. . . nt!RtlUnwindEx+0x200:
.. . > . fffff800`00892070 cmp rbp,rbx ; cmp pEstablisherFrame, l_pEstablisherFrame
.. .< . . fffff800`00892073 jne nt!RtlUnwindEx+0x208 (fffff800`00892078)
.. .. . .
.. .. . . nt!RtlUnwindEx+0x205:
.. .. . . fffff800`00892075 or esi,20h ; l_ExceptionFlags |= EXCEPTION_TARGET_UNWIND (0x20)
.. .. . .
.. .. . . nt!RtlUnwindEx+0x208:
.. .> . . fffff800`00892078 mov r10,qword ptr [rsp+690h] ; r10 = &l_ExceptionRecord
.. . . . fffff800`00892080 mov rax,qword ptr [rsp+698h] ; rax = ReturnValue
.. . . . fffff800`00892088 mov qword ptr [rsp+0A0h],rcx ; l_DispatcherContext.LanguageHandler = l_pExceptionRoutine
.. . . . fffff800`00892090 mov dword ptr [r10+4],esi ; l_ExceptionRecord.ExceptionFlags = l_ExceptionFlags
.. . . . fffff800`00892094 mov qword ptr [rdi+78h],rax ; pOriginalContext->Rax = ReturnValue
.. . . . fffff800`00892098 mov rax,qword ptr [rsp+68h] ; rax = pOriginalContext->Rip
.. . . . fffff800`0089209d mov qword ptr [rsp+70h],rax ; l_DispatcherContext.ControlPc = pOriginalContext->Rip
.. . . . fffff800`008920a2 mov rax,qword ptr [rsp+60h] ; rax = l_pImageBase
.. . . . fffff800`008920a7 lea r9,[rsp+70h] ; r9 = &l_DispatcherContext
.. . . . fffff800`008920ac mov qword ptr [rsp+78h],rax ; l_DispatcherContext.ImageBase = l_pImageBase
.. . . . fffff800`008920b1 mov rax,qword ptr [rsp+6A8h] ; rax = pHistoryTable
.. . . . fffff800`008920b9 mov r8,rdi ; r8 = pOriginalContext
.. . . . fffff800`008920bc mov rdx,rbx ; rdx = l_pEstablisherFrame
.. . . . fffff800`008920bf mov rcx,r10 ; rcx = &l_ExceptionRecord
.. . . . fffff800`008920c2 mov qword ptr [rsp+80h],r14 ; l_DispatcherContext.FunctionEntry = l_pFunctionEntry
.. . . . fffff800`008920ca mov qword ptr [rsp+0B0h],rax ; l_DispatcherContext.HistoryTable = pHistoryTable
.. . . . fffff800`008920d2 mov qword ptr [rsp+88h],rbx ; l_DispatcherContext.EstablisherFrame = l_pEstablisherFrame
.. . . . fffff800`008920da mov qword ptr [rsp+98h],rdi ; l_DispatcherContext.ContextRecord = pOriginalContext
.. . . . fffff800`008920e2 mov qword ptr [rsp+0A8h],r13 ; l_DispatcherContext.HandlerData = l_pHandlerData
.. . . . fffff800`008920ea mov dword ptr [rsp+0B8h],r15d ; l_DispatcherContext.ScopeIndex = 0
.. . . . fffff800`008920f2 and esi,0FFFFFF9Fh ; l_ExceptionFlags &= ~(EXCEPTION_TARGET_UNWIND|EXCEPTION_COLLIDED_UNWIND)
.. . . . fffff800`008920f5 call nt!RtlpExecuteHandlerForUnwind (fffff800`008bd9d0)
.. . . . ; RtlpExecuteHandlerForUnwind(&l_ExceptionRecord,
.. . . . ; l_pEstablisherFrame,
.. . . . ; pOriginalContext,
.. . . . ; &l_DispatcherContext);
.. . . . fffff800`008920fa dec eax
.. .< . . fffff800`008920fc je nt!RtlUnwindEx+0x368 (fffff800`008921d8) ; 如果返回 ExceptionContinueSearch 则跳转
.. .. . .
.. .. . . nt!RtlUnwindEx+0x292:
.. .. . . fffff800`00892102 cmp eax,2 ; cmp eax, ExceptionCollidedUnwind (3 - 1)
.. ..< . . fffff800`00892105 jne nt!RtlUnwindEx+0x426 (fffff800`00892296)
.. ... . .
.. ... . . nt!RtlUnwindEx+0x29b:
.. ... . . ; ExceptionCollidedUnwind 的情况
.. ... . . fffff800`0089210b mov r8,qword ptr [rsp+70h] ; r8 = l_DispatcherContext.ControlPc
.. ... . . fffff800`00892110 mov r10,qword ptr [rsp+78h] ; r10 = l_DispatcherContext.ImageBase
.. ... . . fffff800`00892115 mov rdx,qword ptr [rsp+98h] ; rdx = l_DispatcherContext.ContextRecord
.. ... . . fffff800`0089211d mov rcx,qword ptr [rsp+6A0h] ; rcx = pOriginalContext
.. ... . . fffff800`00892125 mov r14,qword ptr [rsp+80h] ; r14 = l_DispatcherContext.FunctionEntry
.. ... . . fffff800`0089212d mov qword ptr [rsp+68h],r8
.. ... . . fffff800`00892132 mov qword ptr [rsp+60h],r10
.. ... . . fffff800`00892137 call nt!RtlpCopyContext (fffff800`00891080)
.. ... . . ; RtlpCopyContext(pOriginalContext, l_DispatcherContext.ContextRecord);
.. ... . . fffff800`0089213c mov rdx,rcx ; rdx = pOriginalContext
.. ... . . fffff800`0089213f mov rdi,rcx ; rdi = pOriginalContext
.. ... . . fffff800`00892142 lea rcx,[rsp+160h] ; rcx = &l_Context
.. ... . . fffff800`0089214a lea r12,[rsp+160h] ; r12 = &l_Context
.. ... . . fffff800`00892152 call nt!RtlpCopyContext (fffff800`00891080)
.. ... . . ; RtlpCopyContext(&l_Context, pOriginalContext);
.. ... . . fffff800`00892157 mov qword ptr [rsp+38h],0 ; _ARG_8 = NULL
.. ... . . fffff800`00892160 lea rax,[rsp+680h] ; rax = &l_pEstablisherFrame
.. ... . . fffff800`00892168 mov qword ptr [rsp+30h],rax ; _ARG_7 = &l_pEstablisherFrame
.. ... . . fffff800`0089216d lea rax,[rsp+58h] ; rax = &l_pHandlerData
.. ... . . fffff800`00892172 mov r9,r14 ; r9 = l_DispatcherContext.FunctionEntry
.. ... . . fffff800`00892175 mov qword ptr [rsp+28h],rax ; _ARG_6 = &l_pHandlerData
.. ... . . fffff800`0089217a lea rax,[rsp+160h] ; rax = &l_Context
.. ... . . fffff800`00892182 mov rdx,r10 ; rdx = l_DispatcherContext.ImageBase
.. ... . . fffff800`00892185 xor ecx,ecx ; ecx = UNW_FLAG_NHANDLER (0)
.. ... . . fffff800`00892187 mov qword ptr [rsp+20h],rax ; _ARG_5 = &l_Context
.. ... . . fffff800`0089218c call nt!RtlVirtualUnwind (fffff800`00891380)
.. ... . . ; RtlVirtualUnwind(UNW_FLAG_NHANDLER,
.. ... . . ; l_DispatcherContext.ImageBase,
.. ... . . ; l_DispatcherContext.ControlPc,
.. ... . . ; l_DispatcherContext.FunctionEntry,
.. ... . . ; &l_Context,
.. ... . . ; &l_pHandlerData,
.. ... . . ; &l_pEstablisherFrame,
.. ... . . ; NULL);
.. ... . . fffff800`00892191 mov rbx,qword ptr [rsp+88h] ; rbx = l_DispatcherContext.EstablisherFrame
.. ... . . fffff800`00892199 mov rcx,qword ptr [rsp+0A0h] ; rcx = l_DispatcherContext.LanguageHandler
.. ... . . fffff800`008921a1 mov r13,qword ptr [rsp+0A8h] ; r13 = l_DispatcherContext.HandlerData
.. ... . . fffff800`008921a9 mov rax,qword ptr [rsp+0B0h] ; rax = l_DispatcherContext.HistoryTable
.. ... . . fffff800`008921b1 mov r15d,dword ptr [rsp+0B8h] ; r15d = l_DispatcherContext.ScopeIndex
.. ... . . fffff800`008921b9 mov qword ptr [rsp+680h],rbx ; l_pEstablisherFrame = l_DispatcherContext.EstablisherFrame
.. ... . . fffff800`008921c1 mov qword ptr [rsp+48h],rcx ; l_pExceptionRoutine = l_DispatcherContext.LanguageHandler
.. ... . . fffff800`008921c6 mov qword ptr [rsp+58h],r13 ; l_pHandlerData = l_DispatcherContext.HandlerData
.. ... . . fffff800`008921cb mov qword ptr [rsp+6A8h],rax ; pHistoryTable = l_DispatcherContext.HistoryTable
.. ... . . fffff800`008921d3 or esi,40h ; l_ExceptionFlags |= EXCEPTION_COLLIDED_UNWIND (40)
.. ...< . . fffff800`008921d6 jmp nt!RtlUnwindEx+0x382 (fffff800`008921f2)
.. .... . .
.. .... . . nt!RtlUnwindEx+0x368:
.. .>.. . . fffff800`008921d8 cmp rbx,rbp ; cmp l_DispatcherContext.EstablisherFrame, pEstablisherFrame
.. . ..<. . fffff800`008921db je nt!RtlUnwindEx+0x37d (fffff800`008921ed)
.. . .... .
.. . .... . nt!RtlUnwindEx+0x36d:
.. . .... . fffff800`008921dd mov rcx,qword ptr [rsp+48h] ; rcx = l_pExceptionRoutine
.. . .... . fffff800`008921e2 mov rax,rdi ; rax = pOriginalContext
.. . .... . fffff800`008921e5 mov rdi,r12 ; rdi = &l_Context
.. . .... . fffff800`008921e8 mov r12,rax ; r12 = pOriginalContext
.. . .v.. . fffff800`008921eb jmp nt!RtlUnwindEx+0x382 (fffff800`008921f2)
.. . .... .
.. . .... . nt!RtlUnwindEx+0x37d:
.. . ..>. . fffff800`008921ed mov rcx,qword ptr [rsp+48h] ; rcx = l_pExceptionRoutine
.. . .. . .
.. . .. . . nt!RtlUnwindEx+0x382:
.. . .> . . fffff800`008921f2 test sil,40h ; test sil, EXCEPTION_COLLIDED_UNWIND (40)
.. . . < . fffff800`008921f6 jne nt!RtlUnwindEx+0x200 (fffff800`00892070)
.. . . .
.. . . . nt!RtlUnwindEx+0x38c:
.. . . . fffff800`008921fc mov r13,qword ptr [rsp+68h] ; r13 = pOriginalContext->Rip
.. . . . fffff800`00892201 mov r15,qword ptr [rsp+688h] ; r15 = pJumpTargetIp
.. . .< . fffff800`00892209 jmp nt!RtlUnwindEx+0x3c7 (fffff800`00892237)
.. . .. .
.. . .. . nt!RtlUnwindEx+0x39b:
.. > .. . fffff800`0089220b cmp rbx,rbp ; cmp l_DispatcherContext.EstablisherFrame, pEstablisherFrame
.. .< . fffff800`0089220e je nt!RtlUnwindEx+0x3c7 (fffff800`00892237)
.. .. .
.. .. . nt!RtlUnwindEx+0x3a0:
.. .. . fffff800`00892210 mov rax,rdi ; rax = &l_Context
.. .. . fffff800`00892213 mov rdi,r12 ; rdi = pOriginalContext
.. .. . fffff800`00892216 mov r12,rax ; r12 = &l_Context
.. .< . fffff800`00892219 jmp nt!RtlUnwindEx+0x3c7 (fffff800`00892237)
.. .. .
.. .. . nt!RtlUnwindEx+0x3ab:
>. .. . fffff800`0089221b mov rcx,qword ptr [rdi+98h] ; rcx = pOriginalContext->Rsp
. .. . fffff800`00892222 mov rax,qword ptr [rcx] ; rax = pOriginalContext->Rsp[0]
. .. . fffff800`00892225 mov qword ptr [rdi+0F8h],rax ; pOriginalContext->Rip = pOriginalContext->Rsp[0]
. .. . fffff800`0089222c lea rax,[rcx+8] ; rax = pOriginalContext->Rsp + 8
. .. . fffff800`00892230 mov qword ptr [rdi+98h],rax ; pOriginalContext->Rsp = pOriginalContext->Rsp + 8 (跳过返回值)
. .. .
. .. . nt!RtlUnwindEx+0x3c7:
. .> . fffff800`00892237 test bl,7 ; 检查 l_DispatcherContext.EstablisherFrame 是否对齐
. .< . fffff800`0089223a jne nt!RtlUnwindEx+0x444 (fffff800`008922b4)
. .. .
. .. . nt!RtlUnwindEx+0x3cc:
. .. . fffff800`0089223c cmp rbx,qword ptr [rsp+50h] ; cmp l_DispatcherContext.EstablisherFrame, l_LowLimit
. ..< . fffff800`00892241 jb nt!RtlUnwindEx+0x3da (fffff800`0089224a)
. ... .
. ... . nt!RtlUnwindEx+0x3d3:
. ... . fffff800`00892243 cmp rbx,qword ptr [rsp+40h] ; cmp l_DispatcherContext.EstablisherFrame, l_HighLimit
. ...< . fffff800`00892248 jb nt!RtlUnwindEx+0x414 (fffff800`00892284)
. .... .
. .... . nt!RtlUnwindEx+0x3da:
. ..>. . fffff800`0089224a mov al,byte ptr gs:[20DEh] ; al = _KPCR->DpcRoutineActive
. .. . . fffff800`00892252 test al,al
. .. .<. fffff800`00892254 jne nt!RtlUnwindEx+0x43c (fffff800`008922ac)
. .. ...
. .. ... nt!RtlUnwindEx+0x3e6:
. .. ... fffff800`00892256 mov rcx,qword ptr [rsp+40h] ; rcx = l_HighLimit
. .. ... fffff800`0089225b mov rax,qword ptr [rcx-28h] ; rax = l_KernelStackCtrl->Previous.StackBase
. .. ... fffff800`0089225f test rax,rax
. .. .<. fffff800`00892262 je nt!RtlUnwindEx+0x43c (fffff800`008922ac)
. .. ...
. .. ... nt!RtlUnwindEx+0x3f4:
. .. ... fffff800`00892264 mov rdx,qword ptr [rcx-20h] ; rdx = l_KernelStackCtrl->Previous.StackLimit
. .. ... fffff800`00892268 mov rbx,qword ptr [rsp+680h] ; rbx = l_pEstablisherFrame
. .. ... fffff800`00892270 cmp rbx,rdx ; cmp l_pEstablisherFrame, l_KernelStackCtrl->Previous.StackLimit
. .< ... fffff800`00892273 jb nt!RtlUnwindEx+0x444 (fffff800`008922b4)
. .. ...
. .. ... nt!RtlUnwindEx+0x405:
. .. ... fffff800`00892275 cmp rbx,rax ; cmp l_pEstablisherFrame, l_KernelStackCtrl->Previous.StackBase
. .< ... fffff800`00892278 jae nt!RtlUnwindEx+0x444 (fffff800`008922b4)
. .. ...
. .. ... nt!RtlUnwindEx+0x40a:
. .. ... fffff800`0089227a mov qword ptr [rsp+50h],rdx ; l_LowLimit = l_KernelStackCtrl->Previous.StackLimit
. .. ... fffff800`0089227f mov qword ptr [rsp+40h],rax ; l_HighLimit = l_KernelStackCtrl->Previous.StackBase
. .. ...
. .. ... nt!RtlUnwindEx+0x414:
. .. >.. fffff800`00892284 cmp rbx,rbp ; cmp l_pEstablisherFrame, pEstablisherFrame
. .. <.. fffff800`00892287 je nt!RtlUnwindEx+0x449 (fffff800`008922b9)
. .. ...
. .. ... nt!RtlUnwindEx+0x419:
. .. ... fffff800`00892289 mov rax,qword ptr [rsp+6A8h] ; rax = pHistoryTable
. .. ..^ fffff800`00892291 jmp nt!RtlUnwindEx+0xf0 (fffff800`00891f60)
. .. ..
. .. .. nt!RtlUnwindEx+0x426:
. >. .. fffff800`00892296 mov ecx,0C0000026h ; ecx = STATUS_INVALID_DISPOSITION
. . .. fffff800`0089229b call nt!RtlRaiseStatus (fffff800`00889df0)
. . .. fffff800`008922a0 int 3
. . ..
. . .. nt!RtlUnwindEx+0x431:
> . .. fffff800`008922a1 mov ecx,0C0000028h ; ecx = STATUS_BAD_STACK
. .. fffff800`008922a6 call nt!RtlRaiseStatus (fffff800`00889df0)
. .. fffff800`008922ab int 3
. ..
. .. nt!RtlUnwindEx+0x43c:
. .> fffff800`008922ac mov rbx,qword ptr [rsp+680h] ; rbx = l_pEstablisherFrame
. .
. . nt!RtlUnwindEx+0x444:
> . fffff800`008922b4 cmp rbx,rbp ; cmp l_pEstablisherFrame, pEstablisherFrame
< . fffff800`008922b7 jne nt!RtlUnwindEx+0x479 (fffff800`008922e9)
. .
. . nt!RtlUnwindEx+0x449:
. > fffff800`008922b9 mov rax,qword ptr [rsp+698h] ; rax = ReturnValue
. fffff800`008922c1 mov rbx,qword ptr [rsp+690h] ; rbx = pExceptionRecord
. fffff800`008922c9 mov qword ptr [rdi+78h],rax ; pOriginalContext->Rax, ReturnValue
. fffff800`008922cd cmp dword ptr [rbx],80000029h ; cmp pExceptionRecord->ExceptionCode, STATUS_UNWIND_CONSOLIDATE
.< fffff800`008922d3 je nt!RtlUnwindEx+0x46c (fffff800`008922dc)
..
.. nt!RtlUnwindEx+0x465:
.. fffff800`008922d5 mov qword ptr [rdi+0F8h],r15 ; pOriginalContext->Rip, pJumpTargetIp
..
.. nt!RtlUnwindEx+0x46c:
.> fffff800`008922dc mov rdx,rbx ; rdx = pExceptionRecord
. fffff800`008922df mov rcx,rdi ; rcx = pOriginalContext
. fffff800`008922e2 call nt!RtlRestoreContext (fffff800`008bd290)
.< fffff800`008922e7 jmp nt!RtlUnwindEx+0x4a0 (fffff800`00892310)
..
.. nt!RtlUnwindEx+0x479:
>. fffff800`008922e9 cmp r13,qword ptr [rdi+0F8h] ; pOriginalContext->Rip
.< fffff800`008922f0 jne nt!RtlUnwindEx+0x48d (fffff800`008922fd)
..
.. nt!RtlUnwindEx+0x482:
.. fffff800`008922f2 mov ecx,0C00000FFh ; ecx = STATUS_BAD_FUNCTION_TABLE
.. fffff800`008922f7 call nt!RtlRaiseStatus (fffff800`00889df0)
.. fffff800`008922fc int 3
..
.. nt!RtlUnwindEx+0x48d:
.> fffff800`008922fd mov rcx,qword ptr [rsp+690h] ; rcx = pExceptionRecord
. fffff800`00892305 xor r8d,r8d ; r8d = 0
. fffff800`00892308 mov rdx,rdi ; rdx = pOriginalContext
. fffff800`0089230b call nt!ZwRaiseException (fffff800`008b9b80)
. ; ZwRaiseException(pExceptionRecord, pOriginalContext, FALSE);
.
. nt!RtlUnwindEx+0x4a0:
> fffff800`00892310 mov r15,qword ptr [rsp+638h]
fffff800`00892318 mov r14,qword ptr [rsp+640h]
fffff800`00892320 mov r13,qword ptr [rsp+648h]
fffff800`00892328 mov r12,qword ptr [rsp+650h]
fffff800`00892330 mov rdi,qword ptr [rsp+658h]
fffff800`00892338 mov rsi,qword ptr [rsp+660h]
fffff800`00892340 mov rbp,qword ptr [rsp+668h]
fffff800`00892348 mov rbx,qword ptr [rsp+670h]
fffff800`00892350 add rsp,678h
fffff800`00892357 ret
原文:https://www.cnblogs.com/kuangke/p/9397493.html