Ghidra: Use register assumptions to mark certain code regions as unreachable

Created on 2 Jan 2020  路  2Comments  路  Source: NationalSecurityAgency/ghidra

When analyzing binaries that use opaque predicates to obfuscate the control flow, it would be very useful if Ghidra's builtin register assumptions could be used to mark certain blocks as unreachable.

For example, I have created a little program which contains a very simple opaque predicate. The following screenshot depicts me trying to use register assumptions to eliminate the unreachable branch, without success:

image

It would be very nice if the first branch of the if-statement in this example would be completely eliminated by either of the register assumptions I attempted to use (i.e. the one for EAX and the one for ZF).

Most helpful comment

At the moment, register assumptions are only sent to the decompiler if they are defined at the entry point of a function.

You can deal with opaque predicates in two ways:

  1. By using the instruction patcher to change the conditional jump to an unconditional jump.
  2. By defining a special reference (of type JUMP_OVERRIDE_UNCONDITIONAL) on the conditional jump. This will essentially change the conditional jump to an unconditional jump before decompilation. The reference must be declared primary for the override to take effect.

There's an example in the "Advanced" Ghidra class: see the "Control Flow Oddities" subsection of improvingDisassemblyAndDecompilation.pdf.

Note that the overriding references are new to Ghidra 9.1.

All 2 comments

At the moment, register assumptions are only sent to the decompiler if they are defined at the entry point of a function.

You can deal with opaque predicates in two ways:

  1. By using the instruction patcher to change the conditional jump to an unconditional jump.
  2. By defining a special reference (of type JUMP_OVERRIDE_UNCONDITIONAL) on the conditional jump. This will essentially change the conditional jump to an unconditional jump before decompilation. The reference must be declared primary for the override to take effect.

There's an example in the "Advanced" Ghidra class: see the "Control Flow Oddities" subsection of improvingDisassemblyAndDecompilation.pdf.

Note that the overriding references are new to Ghidra 9.1.

Thank you very much! I was unfamiliar with JUMP_OVERRIDE_UNCONDITIONAL; and it works like a charm!

image

Although I don't think I know an example that isn't theoretically covered by the options that were already mentioned, I still think it would be a useful feature if register assumptions at any point in the code would influence the decompiled code. At least for me, this would be an incredibly versatile and useful tool. That said, I can very well understand if this request is rejected given that there are other ways to go about it.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Barakat picture Barakat  路  3Comments

CalcProgrammer1 picture CalcProgrammer1  路  3Comments

gemini00 picture gemini00  路  3Comments

forkoz picture forkoz  路  3Comments

awsaba picture awsaba  路  3Comments