去混淆 IDA 伪代码

逆向工程 艾达 反编译 去混淆
2021-06-21 22:20:04

我想进入逆向工程艺术已经有一段时间了,所以我看了一些在线课程(例如 opensecuritytraining.info)并且还接触了 IDA Pro。

显然,由于这是一个复杂的话题,我被寄存器、指针、指令等淹没了。我对汇编程序和 C 相当了解,这只是(就像我之前说的)一个你必须学习很多东西的话题。

现在回到我的实际问题:我已经下载了一个“CrackMe”程序并开始调试它。基本上目标是找到一个密钥,然后您必须将其输入到程序的文本框中。我很容易地找到了关键检查功能并确定了一些逻辑,但我无法理解程序实际上如何比较字符串。我的 C 技能比我的汇编技能高得多,所以我决定打印一些伪代码。问题是伪代码非常混乱(我猜这是因为编译器优化)而且我基本上无法理解这段代码应该做什么。

这是代码(抱歉有点长):

int __usercall TSDIAppForm_Button1Click<eax>(int a1<eax>, int a2<ebx>, int a3<edi>, int a4<esi>)
{
  int v4; // ebx@1
  int v5; // esi@1
  int v6; // eax@1
  signed int v7; // eax@3
  signed int v8; // edx@3
  int v9; // ebx@3
  int v11; // edx@12
  int v12; // [sp-24h] [bp-34h]@1
  int (*v13)(); // [sp-20h] [bp-30h]@1
  int *v14; // [sp-1Ch] [bp-2Ch]@1
  int v15; // [sp-18h] [bp-28h]@1
  int (*v16)(); // [sp-14h] [bp-24h]@1
  int *v17; // [sp-10h] [bp-20h]@1
  int v18; // [sp-Ch] [bp-1Ch]@1
  int v19; // [sp-8h] [bp-18h]@1
  int v20; // [sp-4h] [bp-14h]@1
  int v21; // [sp+0h] [bp-10h]@1
  int v22; // [sp+4h] [bp-Ch]@1
  int v23; // [sp+8h] [bp-8h]@2
  void (__fastcall *v24)(int); // [sp+Ch] [bp-4h]@7
  int v25; // [sp+10h] [bp+0h]@1

  v22 = 0;
  v21 = 0;
  v20 = a2;
  v19 = a4;
  v18 = a3;
  v5 = a1;
  v17 = &v25;
  v16 = loc_45C6FD;
  v15 = *MK_FP(__FS__, 0);
  *MK_FP(__FS__, 0) = &v15;
  JUMPOUT(Controls__TControl__GetTextLen(*(_DWORD *)(a1 + 872)), 0xFu, *(unsigned int *)"j");
  v6 = Controls__TControl__GetTextLen(*(_DWORD *)(a1 + 872));
  System____linkproc___DynArraySetLength(v6);
  System____linkproc___DynArraySetLength(664);
  v14 = &v25;
  v13 = loc_45C699;
  v12 = *MK_FP(__FS__, 0);
  *MK_FP(__FS__, 0) = &v12;
  v4 = 0;
  do
  {
    Controls__TControl__GetText(*(_DWORD *)(v5 + 872), &v21, v12);
    *(_DWORD *)(v23 + 4 * v4) = *(_BYTE *)(v21 + v4 - 1);
    ++v4;
  }
  while ( v4 != 16 );
  v8 = 1;
  v9 = 0;
  v7 = 4585384;
  do
  {
    if ( v8 == 16 )
      v8 = 1;
    *(_BYTE *)(v22 + v9++) = *(_BYTE *)v7++ ^ *(_BYTE *)(v23 + 4 * v8++);
  }
  while ( v9 != 665 );
  v24 = (void (__fastcall *)(int))v22;

  // I know the key to success lies here, but I can't figure out what this if is supposed to do
  if ( *(_BYTE *)v22 != 96 || *(_BYTE *)(v22 + 4) != 208 || *(_BYTE *)(v22 + 9) )
    MessageBoxA_0(0, "Invalid Key", "Error", 0);
  else
    v24(v22);
  *MK_FP(__FS__, 0) = v12;
  v11 = v15;
  *MK_FP(__FS__, 0) = v15;
  System____linkproc___LStrClr(&v21, v11, 4572932);
  System____linkproc___DynArrayClear(&v22, off_45C568);
  return System____linkproc___DynArrayClear(&v23, off_45C548);
}

如果有人能给我关于如何“反混淆”这段代码的建议,我将不胜感激。有没有插件可以做到这一点?有没有一种特殊的技术可以用来解决这个问题?查看汇编程序代码而不是伪代码会更好吗?

我特别想知道这些奇怪的常量(例如 872)从何而来。

答案将不胜感激。

1个回答

IDA Pro 并不是自动将二进制文件反编译为其源代码的神奇工具。尽管 IDA 拥有最好的反编译器,但不应每次都依赖反编译器输出(因为编译会导致信息丢失)。而是专注于反汇编列表。对于特定部分,您可以使用反编译器输出作为参考。

去混淆是一个多步骤的过程。首先尝试理解变量结构的用法,然后给它们一个更易于理解的名称来反映它们的用途。在许多情况下,您可以通过注意变量在函数调用中的使用方式来理解变量的用途。例如Vcl.Controls.TControl.GetTextLen返回控件文本的长度。这意味着在传递的参数中,一个必须是指向TControl. 您可以使用此信息重命名变量。

对于VCL二进制文件,Interactive Delphi Reconstructor将为您提供更易于理解的反汇编,因为它专为该目的而设计。IDR 还具有非常有限的反编译能力。

为了更好地理解 IDA Pro 及其无数功能,我建议阅读这两本书IDA Pro BookReverse Engineering Code with IDA Pro