找到在堆栈上写入特定值的代码的负责部分

逆向工程 艾达
2021-07-01 13:21:26

我正在尝试重新创建一个应用程序,该应用程序在点击特定数字后显示。该数字来自解析后的文件。输入 = 5,显示的数字 = 5,依此类推。

我能够追踪到正在加载数字的反汇编代码。

v3 = *(_DWORD *)(*((_DWORD *)AfxGetModuleState() + 1) + 164);

ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::Format(v2 + 168, "%u", *(_DWORD *)(v13 + 1032));

最后一部分v13 + 1032告诉我在哪里查看堆栈,确实我找到了数字。

堆栈概览

00188F7C  0000000
00188F80  0000004
00188F84  0000001
00188F88  000001D

现在我的问题是:在 IDA 中有什么方法可以向我展示将这 4 个值放在堆栈上的代码吗?环绕线(Line1、3 和 4)始终具有相同的值。

2个回答

在建立堆栈帧的位置设置一个代码断点,并在使用目标值的位置设置另一个断点(因此必须已经写入)。

在第一个断点的条件脚本中,您可以为目标位置添加硬件写入断点;它的绝对地址可以在那个时候计算出来,因为你有 ESP 和 EBP 的实际值。第二个断点用于删除该硬件断点。

在硬件断点的条件脚本中,您可以做任何您想做的事情:检查正在写入的特定值,检查周围的值等。

注意:CheatEngine是专门为此类任务编写的。如果您使用 CheatEngine 而不是试图理解 IDA 的贫乏记录 - 通常非常奇怪 - 接口,您可能会更快、更容易地获得结果。

这是一个基本脚本,您可以通过修改 中的测试target_check_()并调整 中的堆栈偏移量来进行调整set_target_breakpoint_()那里的值来自我为确保代码工作而进行的快速测试。这适用于 IDA 6.7;它绝对不能与免费的 IDA (v5.0) 一起使用。

#include "idc.idc"

static main ()
{
   set_helper_breakpoints_(LocByName("test_ufuncs_t"), 0);
}

static target_check_ (ea)
{
   auto e;

   try
   {
      Message("DbgDword(%x): %x @ EIP %x\n", ea, DbgDword(ea), EIP);

      return DbgDword(ea) == 0x410A10;
   }
   catch (e)  {  Message("error: %s\n", e.description);  }

   return 0;
}

static set_target_breakpoint_ (term_bpt)
{
   auto target_ea = ESP - 0x70;

   Message("target_ea %a\n", target_ea);

   SetBptCndEx(term_bpt, form("DelBpt(0x%x) & 0", target_ea), 0);
   AddBptEx(target_ea, 4, BPT_WRITE);
   SetBptCndEx(target_ea, form("target_check_(0x%x)", target_ea), 0);

   return 0;
}

static set_helper_breakpoints_ (init_bpt, term_bpt)
{
   if (term_bpt <= 0)
      term_bpt = FindCode(GetFunctionAttr(init_bpt, FUNCATTR_END), SEARCH_UP);

   Message("set_helper_breakpoints(): %s %s\n", GetFuncOffset(init_bpt), GetFuncOffset(term_bpt));

   AddBptEx(init_bpt, 0, BPT_DEFAULT);
   AddBptEx(term_bpt, 0, BPT_DEFAULT);
   SetBptCndEx(init_bpt, form("set_target_breakpoint_(0x%x)", term_bpt), 0);
   SetBptCndEx(term_bpt, "0", 0);
}

我会试着猜测你的二进制文件中发生了什么,但这只是我的猜测,直到你提供它。

在调试处理获取键盘代码和打印结果的应用程序时,您需要中断 API 函数。WinDbg 中,它可以像bp USER32!GetKeyboardState; dd esp+x (or dd poi(esp+x) ) 注意一样完成,此操作需要安装调试符号。

你的问题是关于 IDA,但在我看来,单独的调试器更适合这样的任务。