【问题标题】:Hex-rays failing to decompile assembly code using an arrayHex-rays 无法使用数组反编译汇编代码
【发布时间】:2016-10-16 21:13:05
【问题描述】:

我正在用这个使用全局变量的函数编译一个 TASM 程序集文件(以保护模式运行):

array dd 0,29535,29535,29096,27889,35168,39271,24798,29855,29772,38197,22395
dd 56219,56131,56121,56133,24256,24229,24412,51616,37038,28755,29069,28107,46700,31766,30517,35050,33790,00000,0000,64000,64000,64000,64000,64000
dd 32190,10299,64000,25841,9185,25203,24473,25203,39396,64000,64000,64000,64000,64000,64000,64000,64000,15266,50285,25477,64000,64000
dd -1

adderVar EQU 0255442

result dd ?

modifyList proc near
PUSHAD
PUSH DS ES
mov edi,offset array
mov eax,adderVar
e:
cmp dword ptr [edi],-1
je f
add dword ptr eax,[edi]
mov dword ptr [edi],eax
add edi,4
jmp e
f:
mov [result],eax
POP ES DS
POPAD
ret
modifyList endp

此代码将一个固定值 (adderVar) 添加到数组的第一个元素,然后将所有先前元素的总和添加到下一个元素,在结束分隔符 (-1) 处停止。

将 .OBJ 文件加载到 IDA 并使用 Hex-rays 创建 C 文件会生成以下代码:

int dword_3408E = 0; // weak
int dword_34092 = 29535; // weak
int dword_34096 = 29535; // weak
int dword_3409A = 29096; // weak
int dword_3409E = 27889; // weak
int dword_340A2 = 35168; // weak
int dword_340A6 = 39271; // weak
int dword_340AA = 24798; // weak
int dword_340AE = 29855; // weak
int dword_340B2 = 29772; // weak
int dword_340B6 = 38197; // weak
int dword_340BA = 22395; // weak
int dword_340BE = 56219; // weak
int dword_340C2 = 56131; // weak
int dword_340C6 = 56121; // weak
int dword_340CA = 56133; // weak
int dword_340CE = 24256; // weak
int dword_340D2 = 24229; // weak
int dword_340D6 = 24412; // weak
int dword_340DA = 51616; // weak
int dword_340DE = 37038; // weak
int dword_340E2 = 28755; // weak
int dword_340E6 = 29069; // weak
int dword_340EA = 28107; // weak
int dword_340EE = 46700; // weak
int dword_340F2 = 31766; // weak
int dword_340F6 = 30517; // weak
int dword_340FA = 35050; // weak
int dword_3411A = 64000; // weak
int dword_3411E = 32190; // weak
int dword_34126 = 64000; // weak
int dword_3412A = 25841; // weak
int dword_3412E = 9185; // weak
int dword_34132 = 25203; // weak
int dword_34136 = 24473; // weak
int dword_3413A = 25203; // weak
int dword_3415E = 64000; // weak
int dword_34162 = 15266; // weak
int dword_34166 = 50285; // weak
int dword_3417A; // weak


__int64 __usercall sub_167AA@<edx:eax>(__int64 a1@<edx:eax>)
{
  int *v1; // edi@1
  signed int v2; // eax@1
  __int64 v4; // [sp-20h] [bp-20h]@1

  v4 = a1;
  v1 = &dword_3408E;
  v2 = 255442;
  while ( *v1 != -1 )
  {
    v2 += *v1;
    *v1 = v2;
    ++v1;
  }
  dword_3417A = v2;
  return v4;
}
// 3408E: using guessed type int dword_3408E;
// 3417A: using guessed type int dword_3417A;

变量中似乎缺少值 25477,64000,64000 和 -1 分隔符,并且 C 代码假设所有 int 都将是相邻的。

有人能猜出导致 Hex-rays 失败的原因,以及如何修改汇编代码以获得正确的 C 输出吗?

【问题讨论】:

  • 使用add dword ptr eax,[edi]; mov dword ptr [edi],eax,您只是将运行总和写回数组吗?
  • 是的,感谢您发现这一点,我将编辑我的问题。
  • 没有与汇编代码等效的 C 代码。通常反编译为 C 只能在最初是从 C 编译时才能工作,即使那样,它也有很多可能失败的原因。通过对齐数组,您可能会获得更好的结果,因为 C 编译器会给它一个偶数 4 的地址。删除所有 push 和 pop 指令也可能会有所帮助。段寄存器的保存和恢复没用,但其他寄存器的保存恢复可能没用。
  • @rossRidge 是的,“保存寄存器”是一个虚拟的便利宏。这是有用的输入,我想添加一些解释反编译器如何区分数据和代码的内容将是一个很好的答案。

标签: c assembly decompiling ida


【解决方案1】:

您可以在汇编窗口中将 dword_3408E 转换为数组。之后使用 F5 或其他热键重新分析 Hex-Rays 窗口中的代码(如果您更改了默认值),因此 Hex-Rays 也会将其显示为数组。

另一件事。您的功能原型也不正确。应该是'void sub_167AA()',因为你使用的不是参数和返回值,而是全局变量。

【讨论】:

    【解决方案2】:

    十六进制射线doesn't work properly with manually crafted code。 我在尝试加载 Nasm ELF/DWARF .OBJ 时注意到了一些差异,但结果仍然很糟糕。

    目前反编译器可以处理编译器生成的代码。手动 精心制作的代码也可能被反编译,但结果通常更糟 而不是编译器代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-14
      • 2015-12-21
      • 2017-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-29
      • 1970-01-01
      相关资源
      最近更新 更多