通过脚本在结构中设置 IDA 函数指针

逆向工程 艾达 蟒蛇 结构
2021-06-21 03:16:09

struct成员重新定义为函数指针的普通手动方法是按下它,点击“ Y”,然后在弹出框中输入正确的声明。例如,对于structmember 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 脚本的函数指针。请帮忙 !

2个回答

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

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

您可以创建一个带有相应结构定义的头文件,并通过调用将其导入

idc.ParseTypes(filename, idc.PT_FILE | idc.PT_PAK1)
idc.Til2Idb(-1, strname)

另外你可以尝试查看 Milan Bohacek 的 hexrays_tools 插件的源代码,并尝试将相应的函数导出到你自己的 python 模块中。

插件的来源可 在此处获得,链接来自 hex-rays 插件竞赛页面

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