Skip to content

Commit

Permalink
Add variables to Context and ctx_menus
Browse files Browse the repository at this point in the history
  • Loading branch information
mahaloz committed Jul 22, 2024
1 parent 36a5665 commit f38e95c
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 41 deletions.
20 changes: 15 additions & 5 deletions libbs/artifacts/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,27 @@ class Context(Artifact):
__slots__ = Artifact.__slots__ + (
"addr",
"func_addr",
"screen_name"
"screen_name",
"variable"
)

def __init__(self, addr: int = None, func_addr: Optional[int] = None, screen_name: str = None, **kwargs):
self.addr: Optional[int] = addr
self.func_addr: Optional[int] = func_addr
self.screen_name: str = screen_name
def __init__(
self,
addr: Optional[int] = None,
func_addr: Optional[int] = None,
screen_name: Optional[str] = None,
variable: Optional[str] = None,
**kwargs
):
self.addr = addr
self.func_addr = func_addr
self.screen_name = screen_name
self.variable = variable
super().__init__(**kwargs)

def __str__(self):
post_text = f" screen={self.screen_name}" if self.screen_name else ""
post_text += f" var={self.variable}" if self.variable else ""
if self.func_addr is not None:
post_text = f"@{hex(self.func_addr)}" + post_text
if self.addr is not None:
Expand Down
51 changes: 40 additions & 11 deletions libbs/decompilers/ida/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

import libbs
from libbs.artifacts import (
Struct, FunctionHeader, FunctionArgument, StackVariable, Function, GlobalVariable, Enum, Artifact
Struct, FunctionHeader, FunctionArgument, StackVariable, Function, GlobalVariable, Enum, Artifact, Context
)

from PyQt5.Qt import QObject
Expand All @@ -30,6 +30,16 @@

_l = logging.getLogger(__name__)

FORM_TYPE_TO_NAME = {
idaapi.BWN_PSEUDOCODE: "decompilation",
idaapi.BWN_DISASM: "disassembly",
idaapi.BWN_FUNCS: "functions",
idaapi.BWN_STRUCTS: "structs",
idaapi.BWN_ENUMS: "enums",
}

FUNC_FORMS = {"decompilation", "disassembly"}

#
# Wrappers for IDA Main thread r/w operations
# a special note about these functions:
Expand Down Expand Up @@ -1080,6 +1090,28 @@ def has_older_hexrays_version():

return not vers.startswith("8.2")

def view_to_bs_context(view, get_var=True) -> Optional[Context]:
form_type = idaapi.get_widget_type(view)
if form_type is None:
return None

view_name = FORM_TYPE_TO_NAME.get(form_type, "unknown")
ctx = Context(screen_name=view_name)
if view_name in FUNC_FORMS:
ctx.addr = idaapi.get_screen_ea()
func = idaapi.get_func(ctx.addr)
if func is not None:
ctx.func_addr = func.start_ea
if get_var and view_name == "decompilation":
# get lvar info at cursor
vu = idaapi.get_widget_vdui(view)
if vu and vu.item:
lvar = vu.item.get_lvar()
if lvar:
ctx.variable = lvar.name

return ctx


#
# IDA Classes
Expand Down Expand Up @@ -1108,25 +1140,22 @@ def term(self):


class GenericAction(idaapi.action_handler_t):
def __init__(self, action_target, action_function):
def __init__(self, action_target, action_function, deci=None):
idaapi.action_handler_t.__init__(self)
self.action_target = action_target
self.action_function = action_function
self.deci: IDAInterface = deci

def activate(self, ctx):
if ctx is None or ctx.action != self.action_target:
return

dec_view = ida_hexrays.get_widget_vdui(ctx.widget)
# show a thing while we work
#prg = QProgressDialog("Querying...", "Stop", 0, 1, None)
#prg.show()

self.action_function()
ctx = view_to_bs_context(ctx.widget)
if ctx is None:
return

# close the panel we showed while running
#prg.setValue(1)
#prg.close()
dec_view = ida_hexrays.get_widget_vdui(ctx.widget)
self.action_function(ctx, deci=self.deci)

if dec_view is not None:
dec_view.refresh_view(False)
Expand Down
23 changes: 2 additions & 21 deletions libbs/decompilers/ida/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,6 @@
IDA_EXTRA_CMT = "extra"
IDA_CMT_TYPES = {IDA_CMT_CMT, IDA_EXTRA_CMT, IDA_RANGE_CMT}

FORM_TYPE_TO_NAME = {
idaapi.BWN_PSEUDOCODE: "decompilation",
idaapi.BWN_DISASM: "disassembly",
idaapi.BWN_FUNCS: "functions",
idaapi.BWN_STRUCTS: "structs",
idaapi.BWN_ENUMS: "enums",
}

FUNC_FORMS = {"decompilation", "disassembly"}


def while_should_watch(func):
@functools.wraps(func)
Expand Down Expand Up @@ -103,19 +93,10 @@ def view_click(self, view, event):
if not self.interface._artifact_watchers_started:
return

form_type = idaapi.get_widget_type(view)
#decomp_view = idaapi.get_widget_vdui(view)
if not form_type:
ctx = compat.view_to_bs_context(view)
if ctx is None:
return

view_name = FORM_TYPE_TO_NAME.get(form_type, "unknown")
ctx = Context(screen_name=view_name)
if view_name in FUNC_FORMS:
ctx.addr = idaapi.get_screen_ea()
func = idaapi.get_func(ctx.addr)
if func is not None:
ctx.func_addr = func.start_ea

ctx = self.interface.art_lifter.lift(ctx)
self.interface._gui_active_context = ctx
self.interface.gui_context_changed(ctx)
Expand Down
7 changes: 3 additions & 4 deletions libbs/decompilers/ida/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,15 @@ def gui_ask_for_choice(self, question: str, choices: list, title="Plugin Questio
return compat.ask_choice(question, choices, title=title)

def gui_register_ctx_menu(self, name, action_string, callback_func, category=None) -> bool:
# Function explaining action
explain_action = idaapi.action_desc_t(
action = idaapi.action_desc_t(
name,
action_string,
compat.GenericAction(name, callback_func),
compat.GenericAction(name, callback_func, deci=self),
"",
action_string,
199
)
idaapi.register_action(explain_action)
idaapi.register_action(action)
idaapi.attach_action_to_menu(
f"Edit/{category}/{name}" if category else f"Edit/{name}",
name,
Expand Down

0 comments on commit f38e95c

Please sign in to comment.