5

How do I fix structures in IDA PRO so they show up properly in Hex-Rays plugin (C decompiler).

Similar question to: (But the solution doesn't work for me)
Struct with negative offset in IDA possible

Pretty much what happened is I compiled a very good program and it works right, after that I did many changes to it and now it works worse then the older version, I'm trying to figure out what I did wrong (since I lost the source code now) to revert back to the old version. (I also added below the original piece of the code written in C++, which didn't change between both versions).

Structure's addresses somehow optimized in IDA PRO Such as that

*(_BYTE *)(shipsStruct + 279) = 1; //Ships[i].used = true;

should really be [10x4]=40+255= 295

*(_BYTE *)(shipsStruct + 295) = 1;  //Ships[i].used = true;

You can tell the structure size right here (shipsStruct += 296;)

I'm guessing somehow the un-used structure members are stripped out (but why is the structure size valid?).
Seems the assembly somehow is offset wrongly (how do I add the proper offset deltas to the struct to fix this)?

When I try this tip http://www.hexblog.com/?p=63 My whole IDA PRO freezes up when I select the line mov edi, offset dword_10004C38 and press T (IDA PRO 6.1)

structoffset

Seems I made my struct incorrectly?

Here is how the code decompiled code looks like (without applying structure)

  if ( playerListBaseAddress && !IsBadReadPtr(playerListBaseAddress, 4u) )
  {
    shipsStruct = (int)dword_10004C38;
    while ( 1 )
    {
      playerPointer = (struct_v3 *)*((_DWORD *)playerListBaseAddress + maxPlayers);
      if ( !playerPointer )
        break;
      if ( IsBadReadPtr(playerPointer, 4u) )
        break;
      *(_DWORD *)(shipsStruct - 4) = playerPointer->ssXCoord;
      *(_DWORD *)shipsStruct = playerPointer->ssYCoord;
      *(_DWORD *)(shipsStruct + 4) = playerPointer->ssXSpeed;
      *(_DWORD *)(shipsStruct + 8) = playerPointer->ssYSpeed;
      *(_DWORD *)(shipsStruct - 8) = playerPointer->ssFreq;
      *(_DWORD *)(shipsStruct + 20) = playerPointer->ssShipNum;
      if ( playerPointer->ssPlayerName )
        strcpy_s((char *)(shipsStruct + 24), 0xFFu, &playerPointer->ssPlayerName);
      *(_BYTE *)(shipsStruct + 279) = 1;
      if ( v37 == playerPointer )
        break;
      shipsStruct += 296;
      ++maxPlayers;
      v37 = playerPointer;
      if ( shipsStruct >= (signed int)&unk_10017310 )
        goto finish;
    }
    v34 = maxPlayers;
    if ( maxPlayers < 255 )
    {
      v4 = (int)((char *)&unk_10004D4F + 296 * maxPlayers);
      do
      {
        *(_BYTE *)v4 = 0;
        v4 += 296;
      }
      while ( v4 < (signed int)&unk_10017427 );
    }

Here is the orginal code (not decompiled written in C++)

double currentTimer = GetTimer();
double timeElapsed = currentTimer - lastTimer;

int maxPlayers = 0;
DWORD lastPlayerPtr = 0;
if (playerListBaseAddress != NULL && !IsBadReadPtr((void *) playerListBaseAddress, sizeof(ULONG_PTR))) {
    for (int i = 0; i < 255; i++) { //populate player ship list.
    DWORD playerPtr = *(DWORD *) (playerListBaseAddress + (i * 4));

    if (playerPtr != NULL && !IsBadReadPtr((void *) playerPtr, sizeof(ULONG_PTR))) {
        Ships[i].XCoordinate = *(DWORD *) (playerPtr + 0x4);
        Ships[i].YCoordinate = *(DWORD *) (playerPtr + 0x8);
        Ships[i].XSpeed = *(signed long *) (playerPtr + 0x10);
        Ships[i].YSpeed = *(signed long *) (playerPtr + 0x14);
        Ships[i].Freq = *(DWORD *) (playerPtr + 0x58);
        Ships[i].ShipNum = *(BYTE *) (playerPtr + 0x5C)
        //memcpy(&(Ships[i].Name), (void*)((DWORD)playerPtr+0x6D), 19);
        if (!*(BYTE *) (playerPtr + 0x6D) == NULL)
        strcpy_s(Ships[i].Name, (char *) ((DWORD) playerPtr + 0x6D));
        Ships[i].used = true;

        if (lastPlayerPtr == playerPtr)
        goto finishList;
        lastPlayerPtr = playerPtr;
    } else {
      finishList:
        maxPlayers = i;
        for (int j = i; j < 255; j++)
        Ships[j].used = false;
        break;
    }
}

Here is before and after (applying my custom struct)
I did the custom struct by doing a bunch of Arrays (* key), then setting proper sizes. (Guessing this isn't the proper way to make a structure in IDA PRO?) struct
Before:
before
After:
after
ASM:
asm
Edit Function
edit function
Double clicked local variable
dbl click local variables

4

From above...

Decompiled:

*(_DWORD *)(shipsStruct - 4) = playerPointer->ssXCoord;
*(_DWORD *)shipsStruct = playerPointer->ssYCoord;
...

Original:

Ships[i].XCoordinate = *(DWORD *) (playerPtr + 0x4);
Ships[i].YCoordinate = *(DWORD *) (playerPtr + 0x8);
...

Based on these snippets, it looks like the structure in your stack variables is 8 bytes off. Can you share with us the stack variable list for that function? (Double-click on one of the local variables in the decompilation to open the stack view.)

  • Talking about this? i.stack.imgur.com/2rANk.png here: i.stack.imgur.com/9vKkW.png – SSpoke Dec 31 '13 at 2:45
  • Should I risk deleting those db ? ;undefined above? and how did IDA analysis mess on this. Seems 12 bytes off (All functions decompile without errors btw) – SSpoke Dec 31 '13 at 2:53
  • Okay I changed from 0x68 to 0x5C now all undefined are gone begins from var_5C still generates same C code and everything seems the same, except for when clicking the stack variables no more undefined variables there. – SSpoke Dec 31 '13 at 3:06
  • Is shipsStruct a local variable or a global variable? – Jason Geffner Dec 31 '13 at 3:44
  • Well shipsStruct is declared locally from (int)dword_10004C38 which seems to be a global location in memory that location in memory I guess somehow should represent the offsetted structure. shipsStruct is the name I gave it it's really suppose to be casted to ShipStruct. Becomes like this when I convert it to struct* shipsStruct = (ShipStruct *)dword_10004C38; – SSpoke Dec 31 '13 at 3:51
3

This feature is supported since Hex-Rays 1.6:

http://www.hexblog.com/?p=544

(see section 3. CONTAINING_RECORD macro)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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