#!/usr/bin/env python3 """Find strings matching a regex and decompile their referencing functions. Usage: dump-like launcher args: [max_funcs] """ import re import sys import pyghidra pyghidra.start() from ghidra.app.decompiler import DecompInterface # noqa: E402 from ghidra.util.task import ConsoleTaskMonitor # noqa: E402 elf, proj_dir, proj_name, pat = sys.argv[1:5] maxf = int(sys.argv[5]) if len(sys.argv) > 5 else 3 with pyghidra.program_context(pyghidra.open_project( __import__('os').path.abspath(proj_dir), proj_name), '/' + __import__('os').path.basename(elf)) as prog: listing = prog.getListing() fm = prog.getFunctionManager() rm = prog.getReferenceManager() rx = re.compile(pat) dec = DecompInterface() dec.openProgram(prog) seen = set() for d in listing.getDefinedData(True): dt = d.getDataType().getName().lower() if 'string' not in dt and 'char' not in dt: continue v = d.getValue() if v is None or not rx.search(str(v)): continue print('STRING %s %r' % (d.getAddress(), str(v)[:100])) for ref in rm.getReferencesTo(d.getAddress()): f = fm.getFunctionContaining(ref.getFromAddress()) if f is None or f.getEntryPoint() in seen: continue seen.add(f.getEntryPoint()) print(' <- %s %s' % (f.getEntryPoint(), f.getName())) if len(seen) <= maxf: r = dec.decompileFunction(f, 90, ConsoleTaskMonitor()) if r.decompileCompleted(): print(r.getDecompiledFunction().getC()[:6000])