Windows逆向工程入门之堆栈回溯

发布于:2025-02-19 ⋅ 阅读:(38) ⋅ 点赞:(0)

目录

堆栈回溯

效果

代码

符号解析

符号信息

示例代码

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展开交叉引用窗口