- UID
- 2
- 精华
- 积分
- 7736
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
本帖最后由 元始天尊 于 2015-8-9 21:54 编辑
栈回溯,一是用于调试,便于分析程序流程,另一是用于开发中,可以观察调用者是否自身进程,之前用过也简要分析过RtlpWalkFrameChain的原理http://www.0xaa55.com/forum.php? ... tid=1447&extra=,然而无论是用该函数,还是用dbghelp的stackwalk函数,都是利用微软的x86栈桢结构。
如果自己简单做用ebp链完全可以,然而这样做了你会发现得到的结果,比windbg k命令得到的回溯栈少好多,这是为什么呢,这篇帖子及该系列就来探究这个问题。
dbghelp.dll是用c++写的因此分析流程比较麻烦,请做好心理准备,本文先从简单ebp链入来思考这一问题。
众所周知,微软函数(vs系)编译器会自动生成栈桢结构,而api本身也是这种结构,下面以2层调用为例:
funcA:
xor edi,edi //对齐字节
push ebp //开始创建当前层栈桢
mov ebp,esp
sub esp,X
......
push param1
push param2
..........
push paramN
call funcB
funcB:
xor edi,edi //对齐字节
push ebp
mov ebp,esp -------------假设执行到这里
sub esp,Y
.......
mov esp,ebp
pop ebp
ret ?
......
mov esp,ebp //开始销毁栈桢
pop ebp
ret ?
这样一来,栈中的布局:
..........
———————
Y
———————
funcB.ebp -> 当前ebp指向
———————
funcB.nexteip
———————
funcB.paramN
———————
.........
———————
funcB.param1
———————
X
———————
funcA.ebp
———————
funcA.paramN
———————
.........
———————
funcA.param1
———————
nexteip
———————
.........
这种布局是重复的,因此当前ebp位置处可以看做链表(而标准函数中ebp一般是一成不变的,用于保存栈桢):
ebp:
+00 上层ebp
+04 返回地址
+08 paramN
.......
+?? 分配的栈变量空间
+?? 上上层ebp
+?? 上上层返回地址
..............
再来看非标准栈桢(不使用ebp)
..........
———————
Y
———————
funcB.nexteip
———————
funcB.paramN
———————
.........
———————
funcB.param1
———————
X
———————
funcA.paramN
———————
.........
———————
funcA.param1
———————
nexteip
———————
.........
所以根据该链表很容易得到调用栈,然而我们的程序中并不能遇到“理想”的情况,因为以上布局是假设函数存在创建和销毁栈桢的过程,假设该函数没用ebp做栈桢,或者压根没使用栈桢,那么这种方法肯定是行不通了。然而windbg却仍能正确找到,这是为什么呢?最直观的想法是解析了上述栈桢,计算出X,Y param1-N,然后把他们所占的从2个相邻ebp节点中除去,剩下的部分,探测是否返回地址,然后根据解析的返回地址位置重构每一层函数栈,当然返回地址处前一条指令必须是函数调用指令,而且调用地址应该是下一层函数起始位置。
为了验证这个问题,需要研究windbg执行原理,而这就需要用windbg动态调试windbg。由于知道windbg必从栈桢得到返回地址,因此可以对ReadProcessMemory下断:
被调试者断在这里:
0:000> g
(a34.17b8): Break instruction exception - code 80000003 (first chance)
eax=cccccccc ebx=7f1e9000 ecx=00000000 edx=00000001 esi=00d11069 edi=002dfe38
eip=00d11360 esp=002dfd68 ebp=002dfe38 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
*** WARNING: Unable to verify checksum for teststack.exe
teststack!func3:
00d11360 cc int 3
观察到ebp以后,在另一个windbg中对齐下断:
bp kernelbase!ReadProcessMemory ".if poi(esp+8)!=0x2dfe38 {gc}"
再在之前的windbg运行k命令,即可断下,此时查看调用栈:
078dc44c 67ad1432 KERNELBASE!ReadProcessMemory
078dc470 678f4fb0 dbgeng!LiveUserDebugServices::ReadVirtual+0x22
078dc4b0 678f4e6c dbgeng!LiveUserTargetInfo::ReadVirtualUncached+0xa0
078dc4d4 67a29116 dbgeng!LiveUserTargetInfo::ReadVirtual+0x3c
078dc500 676c94fe dbgeng!SwReadMemory+0xe6
078dc528 67702d02 dbghelp!DbhStackServices::ReadMemory+0x2e
078dc548 67736cd7 dbghelp!DbsX86WalkFrame::readMemory+0x32
078dc568 677501c8 dbghelp!CDiaStackWalkHelper::readMemory+0x27
078dc5d0 6775058c dbghelp!StackWalkVM::Operator+0x1b8
078dc600 677506ea dbghelp!StackWalkVM::Statement+0x4c
078dc624 677247ce dbghelp!StackWalkVM::next+0x4a
078dc7f4 67749d07 dbghelp!CStackFrameTrav::next+0x6e
078dc80c 6774b294 dbghelp!CFrameDataFrameTrav::next+0x67
078dc850 6774b6ff dbghelp!CStackTrav::next+0x524
078dc864 6773af4a dbghelp!CStackTrav::execute+0x4f
078dcb6c 67708695 dbghelp!CDiaFrameData::execute+0xda
078dcc08 67703787 dbghelp!DbsX86StackUnwinder::ApplyUnwindInfo+0x2f5
078dcc30 67701dde dbghelp!DbsX86StackUnwinder::Unwind+0x187
078dcc40 676e761e dbghelp!DbsStackUnwinder:bhUnwind+0x19e
078dcd40 676e7a24 dbghelp!PickX86Walk+0x17e
078dda10 67a29ee4 dbghelp!StackWalk64+0x154
078de6a4 67a2a52c dbgeng!TargetInfo::GetTargetStackFrames+0x6a4
078de738 679b4ce2 dbgeng!DoStackTrace+0x1cc
078de7bc 679b6369 dbgeng!WrapParseStackCmd+0x162
078de8a0 679b71a9 dbgeng!ProcessCommands+0xad9
078de8e4 678e76c9 dbgeng!ProcessCommandsAndCatch+0x49
078ded7c 678e794a dbgeng!Execute+0x2b9
078dedac 00c090f6 dbgeng!DebugClient::ExecuteWide+0x6a
078dee58 00c09612 windbg!ProcessCommand+0x156
078dfe78 00c0b8f6 windbg!ProcessEngineCommands+0xb2
其中dbghelp中使我们最感兴趣的,如果对dbgeng中的函数下断,会发现做了N层循环,每执行一次StackWalk64就会得到一层调用栈。
TargetInfo::GetTargetStackFrames:
。。。。。。。。。。。
- for ( i = 0; i < *(_DWORD *)(a1 + 24); ++i )
- {
- v36 = 0;
- v35 = 0;
- v33 = 1;
- if ( g_DebugClrStack )
- dprintf(L"Frame %d\n", i);
- if ( *(_DWORD *)(a1 + 16) )
- {
- FrameInfo::SetToDefault((FrameInfo *)(*(_DWORD *)(a1 + 16) + 152 * i));
- *(_DWORD *)(*(_DWORD *)(a1 + 16) + 152 * i + 132) = i + *(_DWORD *)(a1 + 44);
- }
- if ( *(_DWORD *)(a1 + 20) )
- qmemcpy((void *)(*(_DWORD *)(a1 + 20) + 0xA70 * i), &v104, 0xA70u);
- if ( v39 && v40 )
- {
- if ( v38 && !ProcessInfo::IsClrMethod(**(ProcessInfo ***)(a1 + 8), v53) )
- {
- if ( !StackWalk64(
- **(_DWORD **)(v105 + 44),
- *(HANDLE *)(**(_DWORD **)(a1 + 8) + 88),
- *(HANDLE *)(*(_DWORD *)(a1 + 8) + 40),
- (LPSTACKFRAME64)&v49,
- &v104,
- SwReadMemory,
- SwFunctionTableAccess,
- SwGetModuleBase,
- SwTranslateAddress) )
- break;
- v35 = 1;
- }
- if ( *(_DWORD *)(a1 + 16) )
- v20 = ProcessClrFrame(
- v39,
- i,
- (struct _CROSS_PLATFORM_CONTEXT *)&v104,
- v40,
- (struct FrameInfo *)(*(_DWORD *)(a1 + 16) + 152 * i),
- (struct _tagSTACKFRAME64 *)&v49);
- else
- v20 = ProcessClrFrame(v39, i, (struct _CROSS_PLATFORM_CONTEXT *)&v104, v40, 0, (struct _tagSTACKFRAME64 *)&v49);
- v33 = v20;
- if ( v20 < 0 )
- {
- v21 = FormatStatusCode(v20);
- ErrOut(L"Managed frame processing failed, %s\n", v21);
- v33 = 1;
- }
- v36 = v33 == 0;
- }
- v38 = 0;
- if ( v33 == 1 || !v40 )
- {
- if ( !v35
- && !StackWalk64(
- **(_DWORD **)(v105 + 44),
- *(HANDLE *)(**(_DWORD **)(a1 + 8) + 88),
- *(HANDLE *)(*(_DWORD *)(a1 + 8) + 40),
- (LPSTACKFRAME64)&v49,
- &v104,
- SwReadMemory,
- SwFunctionTableAccess,
- SwGetModuleBase,
- SwTranslateAddress) )
- break;
- v38 = 1;
- if ( i && *(_DWORD *)(a1 + 20) )
- qmemcpy((void *)(*(_DWORD *)(a1 + 20) + 2672 * i), &v104, 0xA70u);
- if ( v39 && !v40 )
- {
- if ( *(_DWORD *)(a1 + 16) )
- v22 = ProcessClrFrame(
- v39,
- i,
- (struct _CROSS_PLATFORM_CONTEXT *)&v104,
- 0,
- (struct FrameInfo *)(*(_DWORD *)(a1 + 16) + 152 * i),
- (struct _tagSTACKFRAME64 *)&v49);
- else
- v22 = ProcessClrFrame(v39, i, (struct _CROSS_PLATFORM_CONTEXT *)&v104, 0, 0, (struct _tagSTACKFRAME64 *)&v49);
- v34 = v22;
- if ( v22 < 0 )
- {
- v23 = FormatStatusCode(v22);
- ErrOut(L"Managed frame processing failed, %s\n", v23);
- }
- v36 = v34 == 0;
- }
- if ( *(_DWORD *)(a1 + 16) )
- {
- if ( !v36 )
- {
- v32 = (UnmanagedFrameInfo *)TypedData::operator new(0x98u, (void *)(*(_DWORD *)(a1 + 16) + 152 * i));
- v112 = 0;
- if ( v32 )
- UnmanagedFrameInfo::UnmanagedFrameInfo(v32);
- v112 = -1;
- }
- if ( **(_DWORD **)(v105 + 44) == 332 )
- {
- v24 = 152 * i;
- v25 = *(_DWORD *)(a1 + 16);
- *(_DWORD *)(v25 + v24 + 144) = v62;
- *(_DWORD *)(v25 + v24 + 148) = v63;
- }
- v26 = *(_DWORD *)(a1 + 16) + 152 * i + 8;
- *(_DWORD *)v26 = v49;
- *(_DWORD *)(v26 + 4) = v50;
- *(_QWORD *)(v26 + 8) = v53;
- *(_DWORD *)(v26 + 16) = v54;
- *(_DWORD *)(v26 + 20) = v55;
- *(_DWORD *)(v26 + 24) = v58;
- *(_DWORD *)(v26 + 28) = v59;
- *(_QWORD *)(v26 + 32) = v66;
- *(_DWORD *)(v26 + 120) = v68;
- v27 = v26 + 72;
- *(_DWORD *)v27 = v69;
- *(_DWORD *)(v27 + 4) = v70;
- *(_DWORD *)(v27 + 8) = v71;
- *(_DWORD *)(v27 + 12) = v72;
- *(_DWORD *)(v27 + 16) = v73;
- *(_DWORD *)(v27 + 20) = v74;
- v28 = v26 + 96;
- *(_DWORD *)v28 = 0;
- *(_DWORD *)(v28 + 4) = 0;
- *(_DWORD *)(v28 + 8) = 0;
- *(_DWORD *)(v28 + 12) = 0;
- *(_DWORD *)(v28 + 16) = 0;
- *(_DWORD *)(v28 + 20) = 0;
- qmemcpy((void *)(v26 + 40), &v67, 0x20u);
- }
- if ( **(_DWORD **)(v105 + 44) == 512 && v107 && *(_DWORD *)(v107 + 8) == 1 )
- {
- if ( *(_QWORD *)&v49 >= 0xE0000000FFA00000ui64 && *(_QWORD *)&v49 < 0xE0000000FFA02000ui64 )
- {
- v29 = *(_QWORD *)&v49
- - __PAIR__(
- -536870912 - ((unsigned int)(*(_DWORD *)(v107 + 1408) > 0xFFA00000) + *(_DWORD *)(v107 + 1412)),
- -6291456 - *(_DWORD *)(v107 + 1408));
- v49 -= -6291456 - *(_DWORD *)(v107 + 1408);
- v50 = HIDWORD(v29);
- }
- if ( i
- && *(_DWORD *)(a1 + 16)
- && *(_QWORD *)(*(_DWORD *)(a1 + 16) + 152 * (i - 1) + 8) >= 0xE0000000FFA00000ui64
- && *(_QWORD *)&v49 < 0xE0000000FFA02000ui64 )
- {
- v30 = 152 * (i - 1);
- v31 = *(_DWORD *)(a1 + 16);
- *(_DWORD *)(v31 + v30 + 16) = v49;
- *(_DWORD *)(v31 + v30 + 20) = v50;
- }
- }
- }
- if ( *(_DWORD *)(a1 + 40) || *(_DWORD *)(a1 + 36) & 0x10 )
- {
- if ( *(_DWORD *)(a1 + 16) )
- FrameInfo::OutputFrameOfTrace(
- i,
- *(_DWORD *)(a1 + 24),
- *(struct FrameInfo **)(a1 + 16),
- *(struct _CROSS_PLATFORM_CONTEXT **)(a1 + 20),
- (struct _CROSS_PLATFORM_CONTEXT *)&v104,
- *(_DWORD *)(a1 + 40),
- &v106);
- }
- }
复制代码 。。。。。。。。。。。。。。。。。
*(_DWORD *)(a1 + 24)正是需要回溯的层数,而且该函数还支持clr(C#)函数回溯,而最重要的操作还是在stackwalk64中,先来看dbghelp的帮助文件:
BOOL WINAPI StackWalk64(
__in DWORD MachineType,
__in HANDLE hProcess,
__in HANDLE hThread,
__in_out LPSTACKFRAME64 StackFrame,
__in_out PVOID ContextRecord,
__in PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
__in PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
__in PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
__in PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress
);
MachineType:处理器类型
IMAGE_FILE_MACHINE_I386 0x014c Intel x86
IMAGE_FILE_MACHINE_IA64 0x0200 Intel Itanium Processor Family (IPF)
IMAGE_FILE_MACHINE_AMD64 0x8664 x64 (AMD64 or EM64T)
hProcess 目标进程句柄
hThread 目标线程句柄
StackFrame 提供一个初始化过得STACKFRAME64,包括eip,ebp,esp等 ,用于迭代得到回溯栈
ContextRecord 提供一个初始化的CONTEXT结构 ,用于非x86架构
ReadMemoryRoutine 读取内存的例程,用于解析栈桢
FunctionTableAccessRoutine 访问运行时函数表的例程,x86下,该函数返回FPO_DATA结构体指针,该函数解析目标地址处函数的栈桢信息
GetModuleBaseRoutine 根据给定虚拟地址求模块基址的例程
TranslateAddress 用于16bit地址翻译例程
typedef struct _FPO_DATA
{
DWORD ulOffStart; 函数起始位置
DWORD cbProcSize; 函数大小
DWORD cdwLocals; 局部变量栈大小
WORD cdwParams; 参数个数
WORD cbProlog :8; Prolog字节数
WORD cbRegs :3; 保存寄存器个数
WORD fHasSEH :1; 是否SEH
WORD fUseBP :1; 是否使用EBP
WORD reserved :1;
WORD cbFrame :2; 栈帧类型
} FPO_DATA, *PFPO_DATA
FRAME_FPO 0 FPO frame
FRAME_NONFPO 3 Non-FPO frame
FRAME_TRAP 1 Trap frame
FRAME_TSS 2 TSS frame
typedef struct _tagSTACKFRAME64 {
ADDRESS64 AddrPC; // EIP StIIP RIP
ADDRESS64 AddrReturn; // 返回地址
ADDRESS64 AddrFrame; // EBP AddrBstore RBP/RDI
ADDRESS64 AddrStack; // ESP SP RSP
ADDRESS64 AddrBStore; // RsBSP
PVOID FuncTableEntry; // FPO_DATA 指针
DWORD64 Params[4]; // 推导函数参数
BOOL Far; // WOW far call
BOOL Virtual; // 是否Virtual Frame
DWORD64 Reserved[3];
KDHELP64 KdHelp; //用于内核回调桢
} STACKFRAME64, *LPSTACKFRAME64;
- BOOL __stdcall StackWalk64(DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME64 StackFrame, PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress)
- {
- v22 = 0;
- DbhStackServices::DbhStackServices(&a2);
- if ( StackFrame )
- {
- v13 = hProcess;
- v14 = hThread;
- dword_31142D0 = MachineType;
- if ( FunctionTableAccessRoutine )
- {
- v16 = FunctionTableAccessRoutine;
- }
- else
- {
- v16 = FunctionTableAccessRoutineLocal;
- v22 = 1;
- }
- if ( GetModuleBaseRoutine )
- {
- v17 = GetModuleBaseRoutine;
- }
- else
- {
- v17 = GetModuleBaseRoutineLocal;
- v22 = 1;
- }
- if ( ReadMemoryRoutine )
- v15 = ReadMemoryRoutine;
- else
- v15 = (PREAD_PROCESS_MEMORY_ROUTINE64)ReadMemoryRoutineLocal;
- if ( TranslateAddress )
- v18 = TranslateAddress;
- else
- v18 = TranslateAddressRoutineLocal;
- if ( !v22 || TrySymInit(hProcess) )
- {
- a1 = 0;
- v11 = DbsStackUnwinder::New(
- (struct DbsStackServices *)&a2,
- MachineType,
- (ACCESS_MODE)StackFrame->AddrPC.Mode,
- &v20,
- 3200u,
- &a1);
- if ( !v11 )
- {
- v19 = DbsStackUnwinder::GetFunctionEntryBytes(a1);
- if ( MachineType == 332 )
- {
- v11 = PickX86Walk(a1, (DbhStackServices *)&a2, StackFrame, ContextRecord);
- }
- else if ( ContextRecord )
- {
- v10 = GetTlsPtr();
- v11 = DbsStackUnwinder::DbhUnwind(
- a1,
- StackFrame,
- (unsigned __int16)gApiRevision,
- (char *)v10 + 96,
- 800u,
- ContextRecord);
- }
- else
- {
- v11 = 0x80070057;
- }
- }
- if ( a1 )
- (**(void (__thiscall ***)(DbsStackUnwinder *, _DWORD))a1)(a1, 0);
- result = v11 == 0;
- }
- else
- {
- result = 0;
- }
- }
- else
- {
- result = error(0x57u);
- }
- return result;
- }
复制代码
为方便起见,下面的函数只写最简略形式,参数和返回类型后面一步步推导
这里构造了DbhStackServices类,并用传入的参数初始化之,之后用该类生成对应的DbhStackUnwinder类,最后分是否x86分别执行PickX86Walk和DbhUnwind获取回溯信息
- class DbsStackServices
- {
- //虚表
- public:
- virtual LONG ReadMemory()=0 //+00h
- virtual LONG GetModuleBase()=0 //+04h
- virtual LONG GetFunctionEntry()=0 //+08h
- virtual LONG GetUnwindInfoFromSymbols //+0Ch
- virtual LONG FreeUnwindInfoFromSymbols //+10h
- virtual LONG TranslateToFlatAddress //+14h
- virtual LONG GetSegmentDescriptor //+18h
- virtual LONG Status //+1Ch
- //成员
- public:
- HANDLE hProcess; //+04h
- HANDLE hThread; //+08h
- FARPROC ReadMemoryRoutine; //+0Ch
- FARPROC FunctionTableAccessRoutine; //+10h
- FARPROC GetModuleBaseRoutine; //+14h
- FARPROC TranslateAddressRoutine; //+18h
- DWORD mem1; //+1Ch
- DWORD mem2; //+20h
- }
- class DbhStackServices:DbsStackServices
- {
- public:
- DbhStackServices();
- //虚表覆盖
- public:
- virtual LONG ReadMemory();
- virtual LONG GetModuleBase();
- virtual LONG GetFunctionEntry();
- //非虚函数
- LONG TranslateToFlatAddress();
- }
复制代码
而栈回溯对象DbsStackUnwinder为基类,其子类根据处理器不同有五类:(微软做的还是很全面的)
DbsIa64StackUnwinder IA64指令集
DbsPpcBeStackUnwinder PowerPC指令集
DbsX64StackUnwinder X64指令集
DbsX86StackUnwinder X86 32bit
DbsX8616StackUnwinder X86 16bit
DbsArmStackUnwinder ARM指令集
分别重写了基类的Start 和UpdateAbstractPointers方法
- class DbsStackUnwinder
- {
- //虚表
- public:
- virtual ~DbsStackUnwinder(); //+00h
- virtual LONG Start(CONTEXT* ContextRecord,DWORD ContextSize) //+04h
- virtual LONG Unwind()=0; //+08h
- virtual LONG GetContext(CONTEXT* ContextRecord,DWORD ContextSize) //+0Ch
- virtual LONG GetUnwindInfo(); //+10h
- virtual LONG GetFullUnwindInfoSize(); //+14h
- virtual LONG DbhStart(STACKFRAME64 * StackFrame,CONTEXT* ContextRecord) //+18h
- virtual LONG DbhContinue(STACKFRAME64 * StackFrame,CONTEXT* ContextRecord) //+1Ch
- virtual LONG DbhUpdatePreUnwind(STACKFRAME64 * StackFrame); //+20h
- virtual LONG DbhUpdatePostUnwind(STACKFRAME64 * StackFrame,LONG status); //+24h
- virtual LONG SetRestart(); //+28h
- virtual LONG ClearUnwindDerived(); //+2Ch
- virtual LONG UpdateAbstractPointers()=0; //+30h
- //普通函数
- LONG AdjustForNoReturn();
- LONG DbhGetKdHelp();
- LONG DbgSetKdHelp();
- LONG DbgUnwind();
- LONG DbgStackUnwinder();
- LONG FillMemCache();
- LONG FreeUnwindInfo();
- LONG GetFuncitonEntryBytes();
- LONG GetServices();
- LONG InvalidateMemCache();
- LONG PopMemCache();
- LONG PushAndFillMem();
- LONG PushMemCache();
- LONG ReadMemCache();
- LONG SetImlFlags();
- LONG SetInvalidInstructionPointer();
- LONG StartAdjustForNoReturn();
- LONG UnwindNtKernelCallback();
- LONG UpdateCallPointer();
- void operator delete();
- void operator new(int);
- void operator new(int,void*,long);
- class DeclMemCache<T>
- {
- public:
- ~DeclMemCache<T>();
- void PushAndFill();
- void Pop();
- }
- static __stdcall LONG New();
- //成员变量
- DWORD unkonw1;//+004h
- DbsStackServices* StackService;//+008h
- char* MachineName;//+00Ch
- DWORD MachineType;//+010h
- int ContextSize;//+014h
- int FunctionEntryBytes;//+018h 函数入口构成栈桢的字节数
- int u3;//+01Ch
- DWORD ??;//+020h
- DWORD RegSize;//+024h 机器字长
- int u6;//+028h
- BOOL IsVirtualFrame;//+040h
- int ImplFlags;//+044h
- CONTEXT* context;//+048h
- int u24;//+04Ch
- LONGLONG Xbp;//+050h
- LONGLONG RetAddr;//060h
- LONGLONG FrameOffset;//070h
- int u25;
- int u7;//+090h
- KDHELP64 KdHelp;//+098h
- LONGLONG StackUpLimit;//+0D0h
- LONGLONG StackDownLimit;//+0D8h
- int DbhVersion;//+108h
- LONGLONG RsBSP;//+110h
- }
- class DbsX86StackUnwinder:DbsStackUnwinder
- {
- public:
- DbsX86StackUnwinder(DbsStackServices* StackService):DbsStackUnwinder(StackService,"X86", 332, 204, 16, 0, 8, 4, 1){...}
- //成员变量
- public:
- DWORD Dr0;//+11Ch
- DWORD Dr1;//+120h
- DWORD Dr2;//+124h
- DWORD Dr3;//+128h
- DWORD Dr6;//+12Ch
- DWORD Dr7;//+130h
- DWORD SegGs;//+1A4h
- DWORD SegFs;//+1A8h
- DWORD SegEs;//+1ACh
- DWORD SegDs;//+1B0h
- DWORD _Edi;//+1B4h
- DWORD _Esi;//+1B8h
- DWORD _Ebx;//+1BCh
- DWORD _Edx;//+1C0h
- DWORD _Ecx;//+1C4h
- DWORD _Eax;//+1C8h
- DWORD _Ebp;//+1CCh
- DWORD _Eip;//+1D0h
- DWORD SegCs;//+1D4h
- DWORD EFlags;//+1D8h
- DWORD _Esp;//+1DCh
- DWORD SegSs;//+1E0h
- ;//+1E8h
- DWORD ARGS1;//+1ECh
- _FPO_DATA* Fpo;//+204h
- DWORD ARGS2;//+20Ch
- int u133;//+214h DbsX86StackUnwinder::ForceEbpRegion *
- DWORD u1;//+3C8h
- }
复制代码
部分实现:
- LONG New(DbsStackServices* StackService,DWORD MachineType,ACCESS_MODE AccessMode,DbsStackUnwinder** OutPtr)
- {
- switch(MachineType)
- {
- case 0x1F2:
- *OutPtr = new DbsPpcBeStackUnwinder(StackService);
- break;
- case IMAGE_FILE_MACHINE_IA64:
- *OutPtr = new DbsIa64StackUnwinder(StackService);
- break;
- case IMAGE_FILE_MACHINE_AMD64:
- *OutPtr = new DbsX64StackUnwinder(StackService);
- break;
- case IMAGE_FILE_MACHINE_ARM:
- case IMAGE_FILE_MACHINE_THUMB:
- case 0x1C4:
- *OutPtr = new DbsArmStackUnwinder(StackService);
- break;
- case IMAGE_FILE_MACHINE_I386:
- switch(AccessMode)
- {
- case AddrModeFlat:
- *OutPtr = new DbsX86StackUnwinder(StackService);
- break;
- case AddrMode1616:
- *OutPtr = new DbsX8616StackUnwinder(StackService);
- break;
- }
- *OutPtr = new DbsX86StackUnwinder(StackService);
- break;
- }
- }
- LONG DbhUnwind(STACKFRAME64 * StackFrame,CONTEXT* ContextRecord)
- {
- LONG status;
- if(StackFrame->Virtual)
- {
- IsVirtualFrame = TRUE;
- status=DbhContinue(StackFrame,ContextRecord);
- if(status)
- return status;
- status=Unwind();
- if(status)
- return status;
- status=GetContext(ContextRecord,u6);
- if(status)
- return status;
- }
- else
- {
- status=DbhStart(StackFrame,ContextRecord);
- if(status)
- return status;
- }
- memset(StackFrame->Params,0,sizeof(StackFrame->Params));
- status=DbhUpdatePreUnwind(StackFrame);
- if(status)
- return status;
- status=Unwind();
- if(status)
- {
- u24=u25=0;
- }
- status=DbhUpdatePostUnwind(StackFrame,status);
- return status;
- }
- LONG DbhGetKdHelp(STACKFRAME64* StackFrame)
- {
- memcpy(&KdHelp,&StackFrame->KdHelp,sizeof(KdHelp));
- }
- virtual LONG Start(CONTEXT* ContextRecord,DWORD ContextSize)//+04h
- {
- if(context && ContextSize >= this->ContextSize)
- {
- memcpy(context,ContextRecord,this->ContextSize);
- }
- }
- virtual LONG GetContext(CONTEXT* ContextRecord,DWORD ContextSize)//+0Ch
- {
- if(context && ContextSize >= this->ContextSize)
- {
- memcpy(ContextRecord,context,this->ContextSize);
- SetRestart();
- UpdateAbstractPointers();
- UpdateCallPointer();
- }
- }
- virtual LONG DbhStart(STACKFRAME64 * StackFrame,CONTEXT* ContextRecord)//+18h
- {
- if(!DbhGetKdHelp(StackFrame))
- {
- memset(&StackFrame->AddrBStore,0,sizeof(StackFrame->AddrBStore));
- memset(&StackFrame->AddrReturn,0,sizeof(StackFrame->AddrReturn));
- StackFrame->FuncTableEntry=0;
- memset(StackFrame->Params,0,sizeof(StackFrame->Params));
- StackFrame->Virtual=TRUE;
- memset(StackFrame->Reserved,0,sizeof(StackFrame->Reserved));
- }
- }
- virtual LONG DbhContinue(STACKFRAME64 * StackFrame,CONTEXT* ContextRecord)//+1Ch
- {
- if(!DbhGetKdHelp(StackFrame))
- {
- LONG status=Start(ContextRecord,ContextSize);
- }
- }
复制代码
从x86执行流程来看,重点还是在Unwind函数中,在其中对STACKFRAME64的迭代得到结果,其他的部分我会在下次叙述。 |
|