The ordinary, manual way of redefining a struct
member to become a function pointer would be to press on it, hit 'Y', and enter the proper declaration in the popup box. For example, for struct
member fncQuery
, I would change the string to: BOOL (__cdecl *fncQuery)(char *cmdID)
This would be helpful; When I next identify a call to this function pointer, I would mark the appropriate call [reg+offset]
line as this function pointer, and IDA will re-analyze and comment the parameters for me.
I have a thousand struct
each with at least one such function pointer member, and corresponding lists of the descriptions of these functions' parameters and return values. Understandably, I want to match them up by an IDAPython script rather than by hand. However, I can't find an equivalent for the 'Y' button for scripts:
AddStrucMember
does not cut it as far as I know - I can declare a member to become a pointer to astruct
by giving it astructID
, but that's not what I need.SetMemberType
is the same as the previous.SetType
requires a linear address and a type string - which would be perfect except linear addresses are exclusive to the code section, so I can't touch structure member definitions withSetType
.
In my search I've found someone who conjured up dark magic, incorporating low level idaapi
into his IDAPython script, to detect if a struct
member has the same name as a known function, and if it does, "gets" the type of that function and "sets" it onto the member. Specifically, such horrible calls are seen (taken out of context of its definitions, you'll have to trust me when I say this runs properly and the first function call fills up its many outparameters with meaningful values):
get_named_type = g_dll.get_named_type
get_named_type.argtypes = [
ctypes.c_void_p, #const til_t *ti,
ctypes.c_char_p, #const char *name,
ctypes.c_int, #int ntf_flags,
ctypes.POINTER(ctypes.POINTER(ctypes.c_ubyte)), #const type_t **type=NULL,
ctypes.POINTER(ctypes.POINTER(ctypes.c_ubyte)), #const p_list **fields=NULL,
ctypes.POINTER(ctypes.POINTER(ctypes.c_ubyte)), #const char **cmt=NULL,
ctypes.POINTER(ctypes.POINTER(ctypes.c_ubyte)), #const p_list **fieldcmts=NULL,
ctypes.POINTER(ctypes.c_ulong), #sclass_t *sclass=NULL,
ctypes.POINTER(ctypes.c_ulong), #uint32 *value=NULL);
]
get_named_type(
til,
funcname,
idaapi.NTF_SYMM,
ctypes.byref(typ_type),
ctypes.byref(typ_fields),
ctypes.byref(typ_cmt),
ctypes.byref(typ_fieldcmts),
ctypes.byref(typ_sclass),
ctypes.byref(value)
type_arr = ctypes.create_string_buffer(0x400)
type_arr[0] = chr(idaapi.BT_PTR)
manualTypeCopy(type_arr, 1, len(type_arr), typ_type)
ret = g_dll.set_member_tinfo(
til,
struc,
memb,
ctypes.c_uint(0),
type_arr,
typ_fields,
ctypes.c_uint(0),
)
The work behind the scenes on "get_named_type
" eludes me, and looking into its source (and fashioning something from it for my use) may be strong headed and premature.
Do you know of an easier way my need can be fulfilled ? I just need to define structure members as function pointers from an IDAPython script. Please help !