我正在使用 Delphi 二进制文件,在生成伪代码时发现了一个小问题。这是 IDA 给我的输出(经过一些清理):
Integer __fastcall LBCommon::TLBMemStream::GetFromId(PLBMemStream Self, Integer Id)
{
int v4[2]; // [esp+0h] [ebp-10h] BYREF
if ( LBCommon::IndexFromId(Self->FFullData, Id, &v4[1]) )
v4[0] = &Self->FFullData[*&Self->FFullData[sizeof(TLBDataEntry) * v4[1] + 0x19] + offsetof(TLBDataItem, FData)];
else
v4[0] = 0;
return v4[0];
}
如您所见,它只是一段简单的代码,它执行一些简单的数学运算然后返回。但是有一个问题:v4 表示为一个整数数组,而不是两个分隔的变量。
理论上,v4[0] 是一个指向将被返回的内存的“指针”,而 v4[1] 是一个应该有多次前进的变量。但是 IDA 将它们视为一个数组并将它们粘在一起。我尝试通过将类型设置为“int v4”来分离它们并且它起作用了,但是 IDA 然后告诉我:
/局部变量分配失败,输出可能有误!
它还显示了用红色生成的两个变量,表明出现问题。
我不太了解 IDA 如何从 ASM 生成伪代码,但我认为问题在于代码如何访问内存区域。对于 v4[0] 它执行“ mov edx, [esp+10h+var_10] ”而对于 v4[1] 它执行“ mov edx, [esp+10h+var_10+4] ” 所以我相信这就是原因它们被视为一个数组。
这是 ASM 中的函数以防万一:
CODE:0046A7E4 var_10 = dword ptr -10h
CODE:0046A7E4
CODE:0046A7E4 push ebx
CODE:0046A7E5 push esi
CODE:0046A7E6 add esp, 0FFFFFFF8h
CODE:0046A7E9 mov esi, edx
CODE:0046A7EB mov ebx, eax
CODE:0046A7ED lea ecx, [esp+10h+var_10+4] ; Index
CODE:0046A7F1 mov edx, esi ; FId
CODE:0046A7F3 mov eax, [ebx+4] ; Header
CODE:0046A7F6 call LBCommon::IndexFromId
CODE:0046A7FB test al, al
CODE:0046A7FD jz short loc_46A818
CODE:0046A7FF mov eax, [ebx+4]
CODE:0046A802 mov edx, [esp+10h+var_10+4]
CODE:0046A806 mov eax, [eax+edx*8+19h]
CODE:0046A80A mov edx, [ebx+4]
CODE:0046A80D lea eax, [edx+eax]
CODE:0046A810 add eax, 0Dh
CODE:0046A813 mov [esp+10h+var_10], eax
CODE:0046A816 jmp short loc_46A81D
CODE:0046A818 ; ---------------------------------------------------------------------------
CODE:0046A818
CODE:0046A818 loc_46A818:
CODE:0046A818 xor eax, eax
CODE:0046A81A mov [esp+10h+var_10], eax
CODE:0046A81D
CODE:0046A81D loc_46A81D:
CODE:0046A81D mov eax, [esp+10h+var_10]
CODE:0046A820 pop ecx
CODE:0046A821 pop edx
CODE:0046A822 pop esi
CODE:0046A823 pop ebx
CODE:0046A824 retn
有没有办法在不产生错误的情况下解决问题?因为我不相信最初的开发人员在这里使用数组来做这个简单的事情,并且在某些部分已经重复了一段时间的问题。