News for hackers. Stuff that matters.
Re:SpaceCadetPinball – Decompilation of 3D Pinball for Windows by gavinray on Thursday October 14, 2021 @10:55AM (#28865120)
Could anyone speak more about how this decompilation is done from a technical perspective?

This looks nothing like the pseudocode C that IDA/Ghidra spit out, so how would you go about doing this even?

It says in the README:

  Tools used: Ghidra, Ida, Visual Studio

  What was done:

    All structures were populated, globals and locals named.
    All subs were decompiled, C pseudo code was converted to compilable C++. Loose (namespace?) subs were assigned to classes.
Which is a bit "Draw-the-rest-of-the-fucking-owl" for me. Or am I just clueless.
Re:SpaceCadetPinball – Decompilation of 3D Pinball for Windows by bri3d on Thursday October 14, 2021 @12:05PM (#28866151)
I'm not aware of any good general-case automation for this.

When I've done this in the past, it basically consists of:

1) Decompile project using Ghidra/IDA, first pass.

2) Load symbols if present (sounds like there was a PDB for this one, which makes things a lot easier).

3) Read decompilation/asm for unnamed subs and try to name them based on what they do.

4) Export all decompiled source into an editor and start copy/paste/editing into readable source. Highly manual process, for some files it's just pattern matching / renaming and goes really quickly, for others it's full reimplementation and a bit harder.

And, if you look at most "decompiled game" projects, I think this is the industry standard way to do this. For example, OpenRCT2 started as a repository full of manually created source with Hex-Rays names and slowly evolved module-by-module into readable source code. (disclosure: per the child post, my original assumption that OpenRCT2 was copied out of Hex-Rays was inaccurate, since it was originally written in assembler it didn't follow a standard C ABI and the decompiler wouldn't work properly anyway).

Re:SpaceCadetPinball – Decompilation of 3D Pinball for Windows by duncanspumpkin on Thursday October 14, 2021 @12:49PM (#28866702)
For OpenRCT2 thats not quite how we did it. We didn't use IDA decomp output as its useless with Chris Sawyer calling conventions you had to just read the assembly. We did name things as per IDA when things were completely unknown hence why there was lots of sub_XXXX functions and byte_XXXX. I personally just used OllyDbg and read the assembly and wrote equivalent C code. I've a few videos of implementing functions for OpenRCT2 and OpenLoco if you are interested.
Re:SpaceCadetPinball – Decompilation of 3D Pinball for Windows by bri3d on Thursday October 14, 2021 @01:05PM (#28866932)
I stand corrected - I'll check them out! It makes sense that the Sawyer calling conventions wouldn't decompile correctly, since he was just making the ABI up as he programmed.
Re:SpaceCadetPinball – Decompilation of 3D Pinball for Windows by gavinray on Thursday October 14, 2021 @12:18PM (#28866312)

  > sounds like there was a PDB for this one, which makes things a lot easier
Ah yeah that certainly reduces the difficulty by an order of magnitude.

Do you know of anyone who has done this with high-skill as a recorded video tutorial? Seems like one of those things much easier to follow in video than text due to how complicated IDA/Ghidra are as tools.

Re:SpaceCadetPinball – Decompilation of 3D Pinball for Windows by bri3d on Thursday October 14, 2021 @12:31PM (#28866457)
Check out `wrongbaud` tutorials: https://hackaday.io/course/172292-introduction-to-reverse-en... .

wrongbaud's are the best trainings I've seen for Ghidra so far. I actually haven't watched this particular course (I confused it with some other ones) - but given what I've seen, I'm sure it's good.

Re:SpaceCadetPinball – Decompilation of 3D Pinball for Windows by gavinray on Thursday October 14, 2021 @12:35PM (#28866521)
Thanks a ton for the point in the right direction!
Re:SpaceCadetPinball – Decompilation of 3D Pinball for Windows by simcop2387 on Thursday October 14, 2021 @12:07PM (#28866181)
It is definitely skipping over a lot of the details. Essentially the code put out by those tools is going to be almost the right code. The thing you do then is go through each function it produces and fix up the names and maybe re-organize it to be more readable. Then you try to compile it and find and fix the errors. It's going to be entirely project and file specific as to what you'll need to do but usually you'll need to rewrite the conditionals in if statements to be more understandable since the optimization passes that the original compiler did will have likely scrambled the logical version of things before (to reduce the number of things that need to be done, or reordered them to take better advantage of the way the processor pipelines things).
Re:SpaceCadetPinball – Decompilation of 3D Pinball for Windows by gavinray on Thursday October 14, 2021 @12:33PM (#28866488)

  > " The thing you do then is go through each function it produces and fix up the names and maybe re-organize it to be more readable."
How do you do this, when most of the code is like (real fn decompilation from random binary opened with Ghidra v10.0.4 for example's sake just now):

  undefined8 FUN_14004dd60(longlong *param_1)
  {
    if ((((*param_1 != 0) && (param_1[1] != 0)) && (param_1[2] != 0)) &&
      ((param_1[0x2b] != 0 && (*(longlong *)(param_1[0x2b] + 0x28) != 0)))) {
      if (*(char *)((longlong)param_1 + 0x21) != '\0') {
        return 0;
      }
      (**(code **)(param_1[1] + 0x18))();
      *(undefined *)((longlong)param_1 + 0x21) = 1;
      return 1;
    }
    return 0;
  }
This program is 14MB, and Ghidra says:

  # of Functions:  12661
  # of Symbols:   118504
  # of Data Types:  6513
It just seems unapproachably daunting.

(Serious question, not being passive-aggressive. I find this stuff interesting and wish I understood it more.)

Re:SpaceCadetPinball – Decompilation of 3D Pinball for Windows by an-unknown on Thursday October 14, 2021 @12:39PM (#28866577)
What's missing here is type information. This is the reason why the decompiled code is quite unreadable. How to solve this: try to figure out what these missing types (like structs, arrays, ...) are, by looking at how the code uses the variables. Then you define these types in IDA/Ghidra/..., and this will already give you decompiled code that's much easier to read.
Re:SpaceCadetPinball – Decompilation of 3D Pinball for Windows by simcop2387 on Thursday October 14, 2021 @01:11PM (#28867036)
The sibling comment covers it a bit more in detail, but it's largely just some guessing and as much an art to figuring out what the types are or could be. This particular one looks like it's taking a function pointer in and checking if it's a valid function (not null) and then checking the first two bytes of the function. From my memory, the windows ABI uses the first two bytes of functions for installing hooks/debugging by patching the first two bytes into some kind of jump (while originally being nops). The 0x2b part I'm not sure about myself but it looks like some other kind of similar checks.

And actually then thinking about the way it's calling it, i'm wondering if this is actually from some C++ standard library code for doing stuff with a vtable, looking up the vtable entry and checking it's validity before calling it (in this case, location 0x18, and checking some kind of RTTI at 0x28 and 0x2b) and storing that it's been initialized in 0x21. So I think this might be part of an initialization function for some property on top of a object that exists at *param_1. and the decompiler has misinterpreted it as a longlong because of the access patterns (64bit pointers).

Re:SpaceCadetPinball – Decompilation of 3D Pinball for Windows by ndiddy on Thursday October 14, 2021 @01:45PM (#28867503)
In the case of Pinball, Microsoft released the debug symbols for the game because it was a part of Windows (meaning that there wasn't a need to figure out the function/variable/type information).