4

I am thinking on a decompilation method which uses the runtime behavior of the binary executable to extract usable compilation data. Analysing the runtime behavior (i.e. trapping after every cpu instruction and check what it does), we could get a lot of additional infos, like:

  • we could differentiate between the static constant data (".text") and the binary asm
  • additional information, what type of data is in which register or global / local variable (pointers, floats and integers)
  • where the cpu instructions are starting
  • from the stack behavior we could get highly useful heuristics, where are the functions / internal functions and how long / what type of parameters they have.

On my opinion, maybe even the holy grail, the recompilable source code wouldn't be so far away.

Is it possible? Does any tool / software already exist which is capable to do this?

  • 1
    What you're saying sounds like a combination of funcap and Hex-Rays Decompiler. – Jason Geffner Sep 13 '15 at 16:22
  • @JasonGeffner Thanks! They sound quite interesting. – peterh says reinstate Monica Sep 13 '15 at 16:45
  • 1
    In the university of Moscow there is an employee that cracked my heavily obfuscated crackme using a patched version of qemu to emulate the code and jump over anti debug code. – Stolas Sep 14 '15 at 5:43
  • @Stolas I think at first would be even enough if normal binary (without intentionally setup anti-disasm traps) would be decompilable. For example, if an asm code could be even created, it would be already transformable to an equivalent C code, which would be compilable on other architectures, too. – peterh says reinstate Monica Sep 14 '15 at 6:46
  • @peterh if you are looking to build something like this, I made a bare version once with libemu as base. I used this to emulate the code and run it as libemu. – Stolas Sep 14 '15 at 12:35
5

This problem is linked to the halting problem on a Turing machine (which is known to be undecidable).

Approaching decompilation through emulation suppose that you have to run through all the branches of the software at least once, and reaching all possible program points cannot be guaranteed if you have to go through a (potentially) infinite loop.

Yet, this is a theoretical problem that you unlikely find in real life (except if it has been planted here intentionally to prevent the full exploration through emulation).

But, in a more practical perspective, exploring all paths can be done only if you can easily run through all the path at runtime, which is not the case when the user is required to solve a challenge (possibly on-line) such as giving a password whose hash is stored in the program or prove that he posses a private key by signing a message and returning it to the software.

  • I think in case of conditional branches the direction of the condition could be negated to map the alternate direction, too. Of course it would cause likely a software fault, but it should be done only once on every conditional jump in the binary, which is not too many. – peterh says reinstate Monica Sep 13 '15 at 16:26
  • 1
    Except if you actually need the result to process the rest of the software (let say that it generates a key from the user input and use it to decipher the assembly code of the rest of the program). – perror Sep 13 '15 at 16:57
  • I am thinking on a 2-phase solution: 1) run the software unmodified, and collect as many data as it is possible 2) using the collected data, only the conditional branches need to be revisited which weren't mapped into both directions. – peterh says reinstate Monica Sep 13 '15 at 17:00

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.