mirror of https://github.com/pwndbg/pwndbg.git
chore(ghidra): modularize ghidra functions into utils and commands
Splitting the logic into ghidra related functionality, context processing and plain command invocation makes the code better structured and the individual files smaller.pull/901/head
parent
b036575589
commit
e8b51243c8
@ -0,0 +1,15 @@
|
|||||||
|
import argparse
|
||||||
|
|
||||||
|
import pwndbg.color.message as message
|
||||||
|
import pwndbg.commands
|
||||||
|
import pwndbg.ghidra
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.description = """Decompile a given function using ghidra"""
|
||||||
|
parser.add_argument("func", type=str, default=None, nargs="?", help="Function to be decompiled. Defaults to the current function.")
|
||||||
|
|
||||||
|
|
||||||
|
@pwndbg.commands.OnlyWithFile
|
||||||
|
@pwndbg.commands.ArgparsedCommand(parser)
|
||||||
|
def ghidra(func):
|
||||||
|
print("\n".join(pwndbg.ghidra.decompile(func)))
|
||||||
@ -0,0 +1,66 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
import gdb
|
||||||
|
|
||||||
|
import pwndbg.color.syntax_highlight as H
|
||||||
|
import pwndbg.radare2
|
||||||
|
import pwndbg.regs
|
||||||
|
|
||||||
|
|
||||||
|
def decompile(func=None):
|
||||||
|
"""
|
||||||
|
Return the source of the given function decompiled by ghidra.
|
||||||
|
|
||||||
|
If no function is given, decompile the function within the current pc.
|
||||||
|
This function requires radare2, r2pipe and r2ghidra.
|
||||||
|
|
||||||
|
Raises Exception if any fatal error occures.
|
||||||
|
"""
|
||||||
|
filename = gdb.current_progspace().filename
|
||||||
|
try:
|
||||||
|
r2 = pwndbg.radare2.r2pipe(filename)
|
||||||
|
# LD list supported decompilers (e cmd.pdc=?)
|
||||||
|
# Outputs for example:: pdc\npdg
|
||||||
|
if not "pdg" in r2.cmd("LD").split("\n"):
|
||||||
|
return ["radare2 plugin r2ghidra-dec must be installed and available from r2"]
|
||||||
|
except ImportError: # no r2pipe present
|
||||||
|
return ["r2pipe not available, but required for r2->ghidra-bridge"]
|
||||||
|
if func is None:
|
||||||
|
try:
|
||||||
|
func = hex(pwndbg.regs[pwndbg.regs.current.pc])
|
||||||
|
except:
|
||||||
|
func = "main"
|
||||||
|
src = r2.cmdj("pdgj @" + func)
|
||||||
|
source = src.get("code", "")
|
||||||
|
curline = None
|
||||||
|
try:
|
||||||
|
cur = pwndbg.regs[pwndbg.regs.current.pc]
|
||||||
|
except AttributeError:
|
||||||
|
cur = None # If not running there is no current.pc
|
||||||
|
if cur is not None:
|
||||||
|
closest = 0
|
||||||
|
for off in (a.get("offset", 0) for a in src.get("annotations", [])):
|
||||||
|
if abs(cur - closest) > abs(cur - off):
|
||||||
|
closest = off
|
||||||
|
pos_annotations = sorted([a for a in src.get("annotations", []) if a.get("offset") == closest],
|
||||||
|
key=lambda a: a["start"])
|
||||||
|
if pos_annotations:
|
||||||
|
curline = source.count("\n", 0, pos_annotations[0]["start"])
|
||||||
|
source = source.split("\n")
|
||||||
|
# Append --> for the current line if possible
|
||||||
|
if curline is not None:
|
||||||
|
line = source[curline]
|
||||||
|
if line.startswith(' '):
|
||||||
|
line = line[4:]
|
||||||
|
source[curline] = '--> ' + line
|
||||||
|
# Join the source for highlighting
|
||||||
|
source = "\n".join(source)
|
||||||
|
if pwndbg.config.syntax_highlight:
|
||||||
|
# highlighting depends on the file extension to guess the language, so try to get one...
|
||||||
|
try: # try to read the source filename from debug information
|
||||||
|
src_filename = gdb.selected_frame().find_sal().symtab.fullname()
|
||||||
|
except: # if non, take the original filename and maybe append .c (just assuming is was c)
|
||||||
|
src_filename = filename+".c" if os.path.basename(filename).find(".") < 0 else filename
|
||||||
|
source = H.syntax_highlight(source, src_filename)
|
||||||
|
source = source.split("\n")
|
||||||
|
return source
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
radare2 = {}
|
||||||
|
|
||||||
|
|
||||||
|
def r2pipe(filename):
|
||||||
|
r2 = radare2.get(filename)
|
||||||
|
if r2:
|
||||||
|
return r2
|
||||||
|
import r2pipe
|
||||||
|
r2 = r2pipe.open(filename)
|
||||||
|
radare2[filename] = r2
|
||||||
|
r2.cmd("aaaa")
|
||||||
|
return r2
|
||||||
Loading…
Reference in new issue