C 无法使用数组反编译程序集代码

C 无法使用数组反编译程序集代码,c,assembly,decompiling,ida,C,Assembly,Decompiling,Ida,我正在编译一个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,

我正在编译一个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
这段代码向数组的第一个元素添加一个固定值(加法器),然后将前面所有元素的总和添加到下一个元素,并在结束分隔符(-1)处停止

将.OBJ文件加载到IDA中并使用十六进制射线创建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;
int-dword_3408E=0;//虚弱的
int dword_34092=29535;//虚弱的
int dword_34096=29535;//虚弱的
int dword_3409A=29096;//虚弱的
int dword_3409E=27889;//虚弱的
int dword_340A2=35168;//虚弱的
int dword_340A6=39271;//虚弱的
int dword_340AA=24798;//虚弱的
int dword_340AE=29855;//虚弱的
int dword_340B2=29772;//虚弱的
int dword_340B6=38197;//虚弱的
int dword_340BA=22395;//虚弱的
int dword_340BE=56219;//虚弱的
int dword_340C2=56131;//虚弱的
int dword_340C6=56121;//虚弱的
int dword_340CA=56133;//虚弱的
int dword_340CE=24256;//虚弱的
int dword_340D2=24229;//虚弱的
int dword_340D6=24412;//虚弱的
int dword_340DA=51616;//虚弱的
int dword_340DE=37038;//虚弱的
int dword_340E2=28755;//虚弱的
int dword_340E6=29069;//虚弱的
int dword_340EA=28107;//虚弱的
int dword_340EE=46700;//虚弱的
int dword_340F2=31766;//虚弱的
int dword_340F6=30517;//虚弱的
int dword_340FA=35050;//虚弱的
int dword_3411A=64000;//虚弱的
int dword_3411E=32190;//虚弱的
int dword_34126=64000;//虚弱的
int dword_3412A=25841;//虚弱的
int dword_3412E=9185;//虚弱的
int dword_34132=25203;//虚弱的
int dword_34136=24473;//虚弱的
int dword_3413A=25203;//虚弱的
int dword_3415E=64000;//虚弱的
int dword_34162=15266;//虚弱的
int dword_34166=50285;//虚弱的
int dword_3417A;//虚弱的
__int64用户呼叫sub_167AA@(int64 a1@)
{
int*v1;//edi@1
签名int v2;//eax@1
__int64 v4;//[sp-20h][bp-20h]@1
v4=a1;
v1=&dword_3408E;
v2=255442;
而(*v1!=-1)
{
v2+=*v1;
*v1=v2;
++v1;
}
dword_3417A=v2;
返回v4;
}
//3408E:使用猜测类型int dword_3408E;
//3417A:使用猜测类型int-dword_3417A;
看起来变量中缺少值2547764000640064000和-1分隔符,C代码假设所有int都是相邻的

有人能猜出是什么导致十六进制射线失败,以及如何修改汇编代码以获得正确的C输出吗?

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

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


可以在“部件”窗口中将dword_3408;转换为数组。之后,如果您更改了默认值,请使用F5或其他热键在Hex-Rays窗口中重新分析代码,以便Hex-Rays也将其显示为数组


还有一件事。函数的原型也不正确。它应该是“void sub_167AA()”,因为您不使用参数和返回值,而是使用全局变量;mov dword ptr[edi],eax您是否正在将一个运行求和写入数组?是的,感谢您发现了这一点,我将编辑我的问题。汇编代码中没有等效的C代码。通常,反编译到C只能在它最初是从C编译的情况下工作,即使这样,也有很多原因说明它可能会失败。对齐数组可能会得到更好的结果,因为C编译器会给它一个4的偶数倍的地址。删除所有推送和弹出指令也可能有所帮助。段寄存器的保存和恢复是无用的,但其他寄存器的保存和恢复可能不是。@rossRidge Yes“保存寄存器”是一个伪方便宏。这是有用的输入,我想添加一些解释反编译器如何区分数据和代码的内容将是一个很好的答案。