7

I'm currently working on taking apart a game (Soul Reaver: Legacy of Kain) and I often come across odd looking sections such as this in the decompiler

  *(_DWORD *)(a2 + 16) = a2 + 624;
  *(_DWORD *)(a2 + 38200) = a2 + 8;
  *(_DWORD *)(a2 + 20) = 0;
  *(_DWORD *)(a2 + 37592) = 0;
  *(_DWORD *)(a2 + 37596) = a2 + 36968;
  *(_DWORD *)(a1 + 8) = a2;
  *(_DWORD *)a1 = 0;
  *(_DWORD *)(a1 + 4) = 0;

These appear to me to be offsets in a struct, but some of the offsets make little sense, e.g. 36968. I'm aware that it is quite difficult to be sure, but some pointers in the correct direction would be much appreciated :)

Assembly for those who want it :)

.text:004B0126                   xor     esi, esi
.text:004B0128                   mov     [ecx+10h], eax
.text:004B012B                   lea     eax, [ecx+8]
.text:004B012E                   mov     [ecx+9538h], eax
.text:004B0134                   mov     eax, [esp+4+arg_0]
.text:004B0138                   lea     edx, [ecx+9068h]
.text:004B013E                   mov     [ecx+14h], esi
.text:004B0141                   mov     [ecx+92D8h], esi
.text:004B0147                   mov     [ecx+92DCh], edx
.text:004B014D                   mov     [eax+8], ecx
.text:004B0150                   mov     [eax], esi
.text:004B0152                   mov     [eax+4], esi

2 Answers 2

5

There is nothing strange in structures or objects with large arrays or other structures inside.In addition I see that most of the large offsets are counted from ecx register, which fits to the definition of Visual Studio variant of __thiscall calling convention. So I think that it is just large structure or object. In addition - structures in IDA not intended to restore original structures, they are intended to make structure in created code, so if it organizes resulting code better - why not to use it anyway ?

Anyway, you can check where the memory in which this parameter allocated comes from. If you see that it is allocated with single malloc or new operator it should be single object/structure or array of objects/structures.

(quote from x86 calling conventions Wiki article)

On the Microsoft Visual C++ compiler, the this pointer is passed in ECX and it is the callee that cleans the stack, mirroring the stdcall convention used in C for this compiler and in Windows API functions. When functions use a variable number of arguments, it is the caller that cleans the stack (cf. cdecl). The thiscall calling convention can only be explicitly specified on Microsoft Visual C++ 2005 and later. On any other compiler thiscall is not a keyword. (However, disassemblers, such as IDA, must specify it. So IDA uses keyword __thiscall for this.)

1
  • Many thanks for the answer. I should also mention it's compiled using Visual C++ 6.0. I have so far come across next to no new or malloc occurences (it appears to use its own memory allocation system, due to its porting from the PS1, which is a wrapper around malloc). I understand how IDA uses structs primarily to organise assembly and make it easier to read. The primary reason it was throwing me off was the large gaps between offsets, and that the values written did not appear to be capable of filling the gaps. Once again, many thanks for the answer, it's a great help :) Mar 10, 2017 at 14:00
0

I have also found very strange and huge offsets in my disassembled C++ code. I first thought that IDA pro is disassembling wrong. But also the pure assembler code has these huge offsets and also Ghidra creates the same pseudo code:

undefined * FUN_00410370(undefined *param_1)
{
  FUN_00402b70();
  *param_1 = 1;
  _memset(param_1 + 0x500440, 0, 0xf001b0);
  param_1[0x0500458] = 0x68;
  param_1[0x0a004e8] = 0x68;
  param_1[0x0f00578] = 0x68;
  param_1[0x1400608] = 0x68;
  return param_1;
}

I finally found out that they create a buffer of 31 MB with malloc() in some subfunction and they subdivide this huge buffer into sections of 5 MB which are used separately.

The function above sets 15 MB of the buffer (0xf001b0 bytes) to zero. Then it writes 0x68 to offsets at 5 MB (0x500458), 10 MB (0xa004e8), 15 MB (0xf00578) and 20 MB (0x1400608).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.