Skip to content

Decompilation

Quokka can optionally embed pseudocode for each function directly inside the exported .quokka file. This lets you work with high-level C-like code in your analysis scripts without keeping an IDA session open.

Note

IDA exports use Hex-Rays and require a decompiler licence for the target architecture. Ghidra exports use Ghidra's built-in decompiler when the extension is invoked with decompilation enabled. The export will succeed even when the decompiler is unavailable; in that case Program.decompiled_activated is False and Function.decompiled_code is an empty string for every function.

Enabling decompilation at export time

Pass -OQuokkaDecompiled:true alongside the other options:

idat -OQuokkaAuto:true -OQuokkaDecompiled:true -A /path/to/binary.i64

Toggle the Export decompiled code checkbox in the Quokka export dialog (shortcut: Alt+A by default).

Add the --decompiled flag:

quokka-cli --decompiled /path/to/binary

Pass --decompiled=true to the Quokka headless script:

analyzeHeadless /tmp/proj Test \
  -process binary \
  -readOnly \
  -noanalysis \
  -scriptPath "$GHIDRA_INSTALL_DIR/Ghidra/Extensions/QuokkaExporter/ghidra_scripts" \
  -postScript QuokkaExportHeadless.java \
  "--out=/tmp/binary.full.quokka" \
  "--mode=SELF_CONTAINED" \
  "--decompiled=true"

Use Program.from_binary or Program.generate with decompiled=True:

import quokka

prog = quokka.Program.from_binary(
    exec_path="binary",
    decompiled=True,
)

Reading decompiled code

After loading a .quokka file, check Program.decompiled_activated before accessing pseudocode — it tells you whether decompilation was enabled when the file was created.

Each Function exposes the pseudocode as the decompiled_code attribute (a plain str). The attribute is an empty string when no pseudocode is available for that function (e.g. library stubs or imported functions).

import quokka

prog = quokka.Program("binary.quokka", "binary")

if not prog.decompiled_activated:
    print("File was exported without decompilation support.")
else:
    for func in prog.values():
        if func.decompiled_code:
            print(f"=== {func.name} (0x{func.start:x}) ===")
            print(func.decompiled_code)
            print()

Checking a single function

func = prog.get_function("authenticate_user")

if func.decompiled_code:
    print(func.decompiled_code)
else:
    print("No pseudocode available for this function.")

You can also address a function by entry address:

func = prog[0x401234]
print(func.name)
print(func.decompiled_code)

Naming a Function from Decompiled Code

The decompiled text is often enough to brainstorm and apply a better name without returning to the disassembler:

func = prog.get_function("FUN_10003e508")
print(func.decompiled_code)

func.name = "releaseSandboxExtensionHandleVector"
func.add_comment(
    "Releases sandbox extension handles and frees paired path storage."
)

# Persist the edit snapshot and apply it back to the disassembler project.
prog.commit(database_file="binary_ghidra/binary.gpr", overwrite=True)

Program.write(...) serializes the modified export. Program.commit(...) applies edits back to the originating IDA database or Ghidra project.

Use-case: searching pseudocode for patterns

Because decompiled_code is a plain string you can apply any text-processing technique directly:

import quokka

prog = quokka.Program("binary.quokka", "binary")

# Find all functions whose pseudocode mentions strcpy
vulnerable = [
    func for func in prog.values()
    if "strcpy" in func.decompiled_code
]

for func in vulnerable:
    print(f"0x{func.start:x}  {func.name}")