From 180befa0bac42a492deec8087814b99c9ad6e8e3 Mon Sep 17 00:00:00 2001 From: Zion Date: Sun, 5 Jun 2022 12:00:34 -0700 Subject: [PATCH] Register Variable Support (#39) - refactored type setting of stack variables (could use more work) - added support for register variables --- decomp2dbg/clients/gdb/gdb_client.py | 54 +++++++++++++++------------ decompilers/d2d_angr/server.py | 2 +- decompilers/d2d_binja/server.py | 20 ++++++---- decompilers/d2d_ida/d2d_ida/server.py | 49 ++++++++++++------------ install.sh | 2 +- 5 files changed, 70 insertions(+), 57 deletions(-) diff --git a/decomp2dbg/clients/gdb/gdb_client.py b/decomp2dbg/clients/gdb/gdb_client.py index 667d37b..0497c08 100644 --- a/decomp2dbg/clients/gdb/gdb_client.py +++ b/decomp2dbg/clients/gdb/gdb_client.py @@ -81,50 +81,56 @@ def update_global_vars(self): def update_function_headers(self): return self.function_headers + def _clean_type_str(self, type_str): + if "__" in type_str: + type_str = type_str.replace("__", "") + idx = type_str.find("[") + if idx != -1: + type_str = type_str[:idx] + "_t" + type_str[idx:] + else: + type_str += "_t" + type_str = type_str.replace("unsigned ", "u") + + return type_str + def update_function_data(self, addr): func_data = self.function_data(addr) - args = func_data["args"] + reg_vars = func_data["reg_vars"] stack_vars = func_data["stack_vars"] - arch_args = get_arch_func_args() - for idx, arg in list(args.items())[:len(arch_args)]: - idx = int(idx, 0) - expr = f"""(({arg['type']}) {arch_args[idx]}""" + for name, var in reg_vars.items(): + type_str = self._clean_type_str(var['type']) + reg_name = var['reg_name'] + expr = f"""(({type_str}) (${reg_name})""" try: val = gdb.parse_and_eval(expr) - gdb.execute(f"set ${arg['name']} {val}") - continue + gdb.execute(f"set ${name} = {val}") + type_unknown = False except Exception: - pass + type_unknown = True - try: - gdb.execute(f'set ${arg["name"]} NA') - except Exception: - pass + if type_unknown: + try: + gdb.execute(f"set ${name} = (${reg_name})") + except Exception: + continue for offset, stack_var in stack_vars.items(): offset = int(offset, 0) - if "__" in stack_var["type"]: - stack_var["type"] = stack_var["type"].replace("__", "") - idx = stack_var["type"].find("[") - if idx != -1: - stack_var["type"] = stack_var["type"][:idx] + "_t" + stack_var["type"][idx:] - else: - stack_var["type"] += "_t" - stack_var["type"] = stack_var["type"].replace("unsigned ", "u") - - expr = f"""({stack_var['type']}*) ($fp - {offset})""" + type_str = self._clean_type_str(stack_var['type']) + expr = f"""({type_str}*) ($fp - {offset})""" + var_name = stack_var['name'] try: - gdb.execute(f"set ${stack_var['name']} = " + expr) + gdb.execute(f"set ${var_name} = " + expr) type_unknown = False except Exception: type_unknown = True if type_unknown: try: - gdb.execute(f"set ${stack_var['name']} = ($fp - {offset})") + gdb.execute(f"set ${var_name} = ($fp - {offset})") except Exception: continue diff --git a/decompilers/d2d_angr/server.py b/decompilers/d2d_angr/server.py index 241acbe..33747f0 100644 --- a/decompilers/d2d_angr/server.py +++ b/decompilers/d2d_angr/server.py @@ -102,7 +102,7 @@ def function_data(self, addr: int): """ resp = { - "args": {}, + "reg_vars": {}, "stack_vars": {} } diff --git a/decompilers/d2d_binja/server.py b/decompilers/d2d_binja/server.py index e396cd5..27e04c6 100644 --- a/decompilers/d2d_binja/server.py +++ b/decompilers/d2d_binja/server.py @@ -2,6 +2,7 @@ from binaryninja import SymbolType, EntryRegisterValue from binaryninja.binaryview import BinaryDataNotification +import binaryninja # # Binja Hooks @@ -92,7 +93,7 @@ def function_data(self, addr: int): """ resp = { - "args": {}, + "reg_vars": {}, "stack_vars": {} } @@ -121,15 +122,18 @@ def function_data(self, addr: int): "type": str(stack_var.type) } - # get args - func_args = {} - for idx, param in enumerate(func.function_type.parameters): - func_args[str(idx)] = { - "name": param.name, - "type": str(param.type) + # get reg vars + reg_vars = {} + for var in func.vars: + if var.source_type != binaryninja.VariableSourceType.RegisterVariableSourceType or not var.name: + continue + + reg_vars[var.name] = { + "reg_name": self.bv.arch.get_reg_name(var.storage), + "type": str(var.type) } - resp["args"] = func_args + resp["reg_vars"] = reg_vars resp["stack_vars"] = stack_vars return resp diff --git a/decompilers/d2d_ida/d2d_ida/server.py b/decompilers/d2d_ida/d2d_ida/server.py index a24bd4d..d11bba2 100644 --- a/decompilers/d2d_ida/d2d_ida/server.py +++ b/decompilers/d2d_ida/d2d_ida/server.py @@ -142,8 +142,8 @@ def decompile(self, addr): @execute_read def function_data(self, addr): resp = { - "args": None, - "stack_vars": None + "stack_vars": None, + "reg_vars": None } # get the function @@ -158,35 +158,35 @@ def function_data(self, addr): except Exception as e: return resp - # stack var info - frame = idaapi.get_frame(func_addr) + # get var info stack_vars = {} + reg_vars = {} + for var in cfunc.lvars: - if not var.name or not var.location.in_stack: + if not var.name: continue - offset = cfunc.mba.stacksize \ - - var.location.stkoff() \ - + idaapi.get_member_size(frame.get_member(frame.memqty - 1)) - - stack_vars[str(offset)] = { - "name": var.name, - "type": str(var.type()) - } + # stack variables + if var.is_stk_var(): + offset = cfunc.mba.stacksize - var.location.stkoff() + stack_vars[str(offset)] = { + "name": var.name, + "type": str(var.type()) + } - # function arguments info - func_args = {} - for arg, idx in zip(cfunc.arguments, cfunc.argidx): - if not arg.name: - continue + # register variables + elif var.is_reg_var(): + regnum = var.get_reg1() + reg_name = idaapi.get_mreg_name(regnum, var.width) - func_args[str(idx)] = { - "name": arg.name, - "type": str(arg.type()) - } + reg_vars[var.name] = { + "reg_name": reg_name, + "type": str(var.type()) + } + pass - resp["args"] = func_args resp["stack_vars"] = stack_vars + resp["reg_vars"] = reg_vars return resp @@ -230,6 +230,9 @@ def global_vars(self): known_segs = [".data", ".bss"] for seg_name in known_segs: seg = idaapi.get_segm_by_name(seg_name) + if not seg: + continue + for seg_ea in range(seg.start_ea, seg.end_ea): xrefs = idautils.XrefsTo(seg_ea) try: diff --git a/install.sh b/install.sh index 05e330c..733033d 100755 --- a/install.sh +++ b/install.sh @@ -59,7 +59,7 @@ install_ida() { return else echo "INSTALLING: IDA plugin WITH linking to ${IDA_PATH}" - ln -s "${LOC}/decompilers/d2d_ida/decomp2dbg_ida.py" "$IDA_PATH" && \ + ln -s "${LOC}/decompilers/d2d_ida/d2d_ida.py" "$IDA_PATH" && \ ln -s "${LOC}/decompilers/d2d_ida/d2d_ida/" "$IDA_PATH" && \ echo "IDA install was successful!" && \ return