[WinDBG] C++ EH Exception (0xE06D7363)

Rainie
職場學習筆記
Published in
7 min readAug 5, 2021

最近看 dump 碰到 C++ exception 0xE06D7363 的問題,這是 visual c++ 的 compiler 碰到 c++ exception 會拋出的錯誤碼,這篇文章就來記錄一下如何透過 WinDBG 查看實際拋出的 exception 是屬於哪種類型。

0:030> .formats 0xE06D7363
Evaluate expression:
Hex: 00000000`e06d7363
Decimal: 3765269347
Octal: 0000000000034033271543
Binary: 00000000 00000000 00000000 00000000 11100000 01101101 01110011 01100011
Chars: .....msc
Time: ***** Invalid
Float: low -6.84405e+019 high 0
Double: 1.86029e-314

Step1. 觀察 EXCEPTION_RECORD

analyze -v 後,在 EXCEPTION_RECORD 有兩個重要的參數:

EXCEPTION_RECORD:  (.exr -1)
ExceptionAddress: 00007ff908019689 (KERNELBASE!RaiseException+0x0000000000000069)
ExceptionCode: e06d7363 (C++ EH exception)
ExceptionFlags: 00000001
NumberParameters: 4
Parameter[0]: 0000000019930520
Parameter[1]: 00000065b2dff2d8
Parameter[2]: 00007ff6a0d009b8
Parameter[3]: 00007ff6a0820000
  • Parameter [2] 存放 _s__ThrowInfo 結構的記憶體位址,這個結構裡的 CatchableTypeArray 會保存 exception 的詳細資訊。
ehdata_forceinclude.h
  • Parameter [3] 存放拋出異常 module 的 base address (僅在 x64 環境才需要)

Step2. 觀察 _s_ThrowInfo

使用 dx -r1 指令把記憶體資訊轉換成高階易讀的資料結構,並遞迴的把相關欄位也一起輸出

0:030> dx -r1 ((VCRUNTIME140!_s_ThrowInfo *)0x7ff6a0d009b8)
((VCRUNTIME140!_s_ThrowInfo *)0x7ff6a0d009b8) : 0x7ff6a0d009b8 [Type: _s_ThrowInfo *]
[+0x000] attributes : 0x0 [Type: unsigned int]
[+0x004] pmfnUnwind : 0 [Type: int]
[+0x008] pForwardCompat : 0 [Type: int]
[+0x00c] pCatchableTypeArray : 5114328 [Type: int]

_s_ThrowInfo 結構裡的第四個參數 pCatchableTypeArray ,是一個指向存放 _s_CatchableTypeArray list 的指標 ( 我到現在還是不理解為什麼 WinDBG 有時候會把型態 map 成別的,有人知道的話可以留言跟我分享 😧 )。

在 x64 系統上這個指標的值是相對虛擬記憶體位址 (RVA),在後續試圖存取與這個值相關的結構,都必須把值加上 parameter[3] 的 base address 才能取得真正 pCatchableTypeArray 的記憶體位址,x86 系統則可以直接存取

Step3. 觀察 _s_CatchableTypeArray

0:030> dx -r1 ((VCRUNTIME140!_s_CatchableTypeArray *)0x7FF6A0D009D8)((VCRUNTIME140!_s_CatchableTypeArray *)0x7FF6A0D009D8)                 : 0x7ff6a0d009d8 [Type: _s_CatchableTypeArray *]
[+0x000] nCatchableTypes : 1 [Type: int]
[+0x004] arrayOfCatchableTypes [Type: int [0]]
ehdata_forceinclude.h

為了得到第二個參數 arrayOfCatchableTypes 的值,使用 dd 把兩個 DWORD 的記憶體資訊倒出來

0:030> dd 0x7FF6A0D009D8 l2
00007ff6`a0d009d8 00000001 004e09e8

Step4. 觀察 _s_CatchableType

0:030> dx -r1 ((VCRUNTIME140!_s_CatchableType *)0x7FF6A0D009E8)
((VCRUNTIME140!_s_CatchableType *)0x7FF6A0D009E8) : 0x7ff6a0d009e8 [Type: _s_CatchableType *]
[+0x000] properties : 0x0 [Type: unsigned int]
[+0x004] pType : 5166632 [Type: int]
[+0x008] thisDisplacement [Type: PMD]
[+0x014] sizeOrOffset : 1 [Type: int]
[+0x018] copyFunction : 0 [Type: int]
ehdata_forceinclude.h

到這步已經離目標越來越近了!跟 exception type 相關的資訊就放在 TypeDescriptor 裡

Step5. 觀察 TypeDescriptor

0:030> dx -r1 ((VCRUNTIME140!TypeDescriptor*)0x7FF6A0D0D628)
((VCRUNTIME140!TypeDescriptor*)0x7FF6A0D0D628) : 0x7ff6a0d0d628 [Type: TypeDescriptor *]
[+0x000] pVFTable : 0x7ff6a0c5f348 [Type: void *]
[+0x008] spare : 0x0 [Type: void *]
[+0x010] name : ".?AVCNewException@@" [Type: char [0]]
ehdata_forceinclude.h

從 name 的欄位可以看出這是一個 NewException 啦!知道出什麼問題後,後續就能根據這類的 exception 做 error handle 了 😃

[Ref]

--

--