将struct
成员重新定义为函数指针的普通手动方法是按下它,点击“ Y”,然后在弹出框中输入正确的声明。例如,对于struct
member fncQuery
,我会将字符串更改为:BOOL (__cdecl *fncQuery)(char *cmdID)
这会很有帮助;当我下次识别出对该函数指针的调用时,我会将相应的call [reg+offset]
行标记为该函数指针,IDA 会为我重新分析和注释参数。
我有一千个,struct
每个都有至少一个这样的函数指针成员,以及这些函数的参数和返回值的描述的相应列表。可以理解的是,我想通过 IDAPython 脚本而不是手工来匹配它们。但是,我找不到Y脚本的“ ”按钮的等效项:
AddStrucMember
据我所知,并没有削减它 - 我可以struct
通过给它 a来声明一个成员成为指向 a 的指针structID
,但这不是我需要的。SetMemberType
与前一个相同。SetType
需要一个线性地址和一个类型字符串 - 这将是完美的,除了线性地址是代码部分独有的,所以我不能用SetType
.
在我的搜索中,我发现有人idaapi
会变出暗魔法,将低级别合并到他的 IDAPython 脚本中,以检测struct
成员是否与已知函数同名,如果是,则“获取”该函数的类型并“设置”它到成员上。具体来说,可以看到这种可怕的调用(脱离其定义的上下文,当我说它运行正常并且第一个函数调用用有意义的值填充其许多输出参数时,您必须相信我):
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),
)
“ get_named_type
”的幕后工作让我望而却步,调查它的来源(并从中制作一些东西供我使用)可能是头脑清醒且为时过早。
你知道有什么更简单的方法可以满足我的需求吗?我只需要将结构成员定义为来自 IDAPython 脚本的函数指针。请帮忙 !