重新定义struct成员以使其成为函数指针的通常的手动方法是,按下该按钮,然后单击“ Y”,然后在弹出框中输入正确的声明。例如,对于struct成员fncQuery,我将字符串更改为:BOOL (__cdecl *fncQuery)(char *cmdID)

这将很有帮助;当我接下来确定对该函数指针的调用时,我会将相应的call [reg+offset]行标记为该函数指针,IDA将为我重新分析并注释参数。具有至少一个这样的函数指针成员,以及这些函数的参数和返回值的描述的对应列表。可以理解的是,我想通过IDAPython脚本而不是手工来匹配它们。但是,我找不到脚本的“ Y”按钮的等效项:据我所知,struct并没有将其切掉-我可以声明一个成员成为指针通过给它一个AddStrucMember来连接到一个struct,但这不是我所需要的。代码部分所独有的,所以我无法使用structID来触及结构成员定义。检测SetMemberType成员是否具有与已知函数相同的名称,如果存在,则“获取”该函数的类型并将其“设置”到该成员上。具体来说,看到了这样可怕的调用(从其定义的上下文中删除,当我说这可以正常运行并且第一个函数调用用有意义的值填充了其许多参数时,您必须信任我): />
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),
            )


SetType”幕后的工作使我难以捉摸,并且调查其来源(并为我使用以制作一些东西)可能是头脑坚定和为时过早。

您知道可以满足我的需求的简便方法吗?我只需要将结构成员定义为IDAPython脚本中的函数指针。请帮忙!

#1 楼

等效的Y键确实是SetType(或更确切地说是ApplyType)函数,并且它通常接受地址。但是,您实际上可以将结构成员ID传递为“地址”以设置成员的类型信息。

评论


我尝试过并且无法成功。除非类型语法需要从根本上有所不同,否则SetType(memberid,“ int”)将失败,而SetType(linear_address_of_some_data,“ int”)将成功。编辑:ApplyType()至少似乎返回True而不是SetType(),但是当我在代码中检测到此类fptr调用并将其标记为此类时,它仍不会自动将参数标记为我给他们的ID。编辑:尽管返回值为False(以及声称失败的文档),但SetType()成功。谢谢。

–睡眠时间
2014年7月2日在13:54

#2 楼

有一种更好的方法,它不涉及为结构成员设置特定类型。

您可以创建具有相应结构定义的头文件,并通过调用

将其导入
idc.ParseTypes(filename, idc.PT_FILE | idc.PT_PAK1)
idc.Til2Idb(-1, strname)


此外,您可以尝试查看Milan Bohacek的hexrays_tools插件的源代码,并尝试将相应的函数导出到您自己的python模块中。此处,来自hex-rays插件竞赛页面的链接

可以在hexrays博客中找到有关如何将Hexrays内部导出为python调用的说明,但您应特别注意GIL(请参阅此处)