Windows逆向工程入门之堆栈回溯
- 公开视频 -> 链接点击跳转公开课程
- 博客首页 -> 链接点击跳转博客主页
目录
堆栈回溯
效果
代码
符号解析
符号信息
示例代码
DBG
IDA
堆栈回溯
效果
代码
#include <iostream>
#include <iomanip>
void PrintCallBack()
{
// 栈帧结构
int StackFrameCount = 0;
// 栈帧获取
int* varEbp = 0;
__asm
{
mov[varEbp], ebp
}
// 堆栈回溯
while (varEbp)
{
/*
PrintCallBack
[EBP + 0] -> FUN3.EBP
[EBP + 4] -> FUN3.RETADDR
FUN3
[EBP + 0] -> FUN2.EBP
[EBP + 4] -> FUN2.RETADDR
*/
// 返回地址
int varRetAddr = varEbp[1];
if (!varRetAddr) return;
std::cout << "StackFrameCount -> " << std::setw(2) << std::setfill('0') << std::dec << StackFrameCount << "\t";
std::cout << "RetAddr -> " << std::showbase << std::hex << varRetAddr << std::endl;
varEbp = (int*)varEbp[0];
StackFrameCount++;
}
}
void Fun3()
{
//[EBP + 0] -> FUN2.EBP
//[EBP + 4] -> FUN2.RETADDR
PrintCallBack();
}
void Fun2()
{
//[EBP + 0] -> FUN1.EBP
//[EBP + 4] -> FUN1.RETADDR
Fun3();
}
void Fun1()
{
//[EBP + 0] -> MAIN.EBP
//[EBP + 4] -> MAIN.RETADDR
Fun2();
}
int main()
{
Fun1();
return 0;
}
符号解析
符号信息
示例代码
#include <iostream>
#include <Windows.h>
#include <DbgHelp.h>
#pragma comment(lib, "dbghelp.lib")
void PrintCallBack()
{
WORD wFrameCount = 0;
HANDLE hProcess = NULL;
PVOID pStack[100] = { 0 };
SYMBOL_INFO* symInfo = NULL;
hProcess = GetCurrentProcess();
// 符号解析
if (SymInitialize(hProcess, NULL, TRUE) == FALSE) return;
// 获取栈帧
wFrameCount = RtlCaptureStackBackTrace(1, 100, pStack, NULL);
// 符号信息
symInfo = (SYMBOL_INFO*)malloc(sizeof(SYMBOL_INFO) + MAX_PATH);
memset(symInfo, 0, sizeof(SYMBOL_INFO) + MAX_PATH);
symInfo->SizeOfStruct = sizeof(SYMBOL_INFO);
symInfo->MaxNameLen = 255;
// 回溯信息
for (size_t i = 0; i < wFrameCount; i++)
{
CHAR strModule[MAX_PATH] = { 0 };
DWORD dwModuleBase = NULL;
SymFromAddr(hProcess, (DWORD64)pStack[i], 0, symInfo);
dwModuleBase = SymGetModuleBase(hProcess, (DWORD64)pStack[i]);
GetModuleFileNameA((HMODULE)dwModuleBase, strModule, MAX_PATH);
if (dwModuleBase)
{
std::cout << "---------------------------------------" << std::endl;
std::cout << "ModuleName -> " << strModule << std::endl;
std::cout << "FunctnName -> " << symInfo->Name << std::endl;
std::cout << "FunStrAddr -> " << "0x" << std::hex << symInfo->Address << std::endl;
std::cout << "FunRetAddr -> " << "0x" << std::hex << (DWORD)pStack[i] << std::endl;
std::cout << "ModuleAddr -> " << "0x" << std::hex << dwModuleBase << std::endl;
}
}
}
void Fun3()
{
PrintCallBack();
}
void Fun2()
{
Fun3();
}
void Fun1()
{
Fun2();
}
int main()
{
Fun1();
return 0;
}
DBG
-
visual studio中设置工程项目属性
-
随机基址 - 否
-
固定基址 - 是
-
- F11运行工程项目转到反汇编查看MAIN函数地址
- DBG启动调试程序
- CTRL + G 转到指定MAIN函数地址
- 通过函数头部下断方式查看栈顶数据返回地址进行堆栈回溯
IDA
- 加载指定PE文件
- Function窗口中搜索MAIN
- 选中函数过程名点击X展开交叉引用窗口