-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathAPIRetypeGUI.py
121 lines (97 loc) · 3.29 KB
/
APIRetypeGUI.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import idaapi
import ida_hexrays
import ida_typeinf
import ida_kernwin
import ida_ida
API_TYPE_ACTION_NAME = "setAPIType"
API_TYPE_ACTION_DESC = "Re-type as API *..."
API_TYPE_ACTION_SHORTCUT = "CTRL-SHIFT-A"
# Look up the type signature for an API name.
def GetTypeSignature(apiName):
# Look up the prototype by name from the main TIL
o = ida_typeinf.get_named_type(None, apiName, ida_typeinf.NTF_SYMU)
# Found?
if o is not None:
code, type_str, fields_str, cmt, field_cmts, sclass, value = o
# Create a tinfo_t by deserializing the data returned above
t = ida_typeinf.tinfo_t()
if t.deserialize(None, type_str, fields_str, field_cmts):
# And change the prototype into a function pointer
ptrType = ida_typeinf.tinfo_t()
ptrType.create_ptr(t)
return ptrType
# On any failure, return None
return None
# Convenience function to set a type for a local variable
def ChangeVariableType(func_ea, lvar, tif):
lsi = ida_hexrays.lvar_saved_info_t()
lsi.ll = lvar
lsi.type = ida_typeinf.tinfo_t(tif)
if not ida_hexrays.modify_user_lvar_info(func_ea, ida_hexrays.MLI_TYPE, lsi):
ida_kernwin.warning("Could not modify lvar type for %s" % lvar.name)
return False
return True
def is_32bit():
return not ida_ida.inf_is_64bit()
PTR_SIZE = 4 if is_32bit() else 8
def IsPtrSizedLvar(vu):
lvar = vu.item.get_lvar()
if lvar is None:
return False
return lvar.width == PTR_SIZE
# The popup menu item handler
class api_ptr_type_setter(ida_kernwin.action_handler_t):
def __init__(self):
ida_kernwin.action_handler_t.__init__(self)
def activate(self, ctx):
vu = ida_hexrays.get_widget_vdui(ctx.widget)
if not IsPtrSizedLvar(vu):
return 1
lvar = vu.item.get_lvar()
name = ida_kernwin.ask_str("", ida_kernwin.HIST_IDENT, "Please enter the API name for which to set the type")
if name is None:
return 1
ptrTif = GetTypeSignature(name)
if ptrTif is None:
ida_kernwin.warning("Could not get type for \"%s\"" % name)
return 1
ChangeVariableType(vu.cfunc.entry_ea, lvar, ptrTif)
vu.cfunc.refresh_func_ctext()
return 1
def update(self, ctx):
vu = ida_hexrays.get_widget_vdui(ctx.widget)
if vu is None:
return ida_kernwin.AST_DISABLE_FOR_WIDGET
if IsPtrSizedLvar(vu):
return ida_kernwin.AST_ENABLE
return ida_kernwin.AST_DISABLE
def ApiPtrTypeSetInstall():
if ida_hexrays.init_hexrays_plugin():
ra = ida_kernwin.register_action(
ida_kernwin.action_desc_t(
API_TYPE_ACTION_NAME,
API_TYPE_ACTION_DESC,
api_ptr_type_setter(),
API_TYPE_ACTION_SHORTCUT))
else:
print("API * type setter: hexrays is not available.")
def ApiPtrTypeSetUninstall():
idaapi.unregister_action(API_TYPE_ACTION_NAME)
ApiPtrTypeSetUninstall()
ApiPtrTypeSetInstall()
# This class lets us only show the menu item when the cursor is currently over
# a pointer-sized local variable
class ApiPtrHooks(ida_hexrays.Hexrays_Hooks):
def populating_popup(self, widget, popup_handle, vu):
if IsPtrSizedLvar(vu):
ida_kernwin.attach_action_to_popup(widget,popup_handle,API_TYPE_ACTION_NAME)
return 0
# Convenience for development
try:
apiptrhooks.unhook()
del apiptrhooks
except NameError as e:
pass
finally:
apiptrhooks = ApiPtrHooks()
apiptrhooks.hook()