IDAPython获取函数参数个数

admin 2022年11月3日18:36:25评论102 views字数 5580阅读18分36秒阅读模式
创建: 2022-11-02 22:08
更新: 2022-11-03 15:48
http://scz.617.cn:8/python/202211022208.txt

目录:

☆ 背景介绍
☆ idaapi.decompile
☆ FLARE IDA Decompiler Library (FIDL)
    1) 安装FIDL
    2) 用FIDL获取函数参数个数
    3) FIDLidaapi.decompile的封装
☆ 后记
☆ 参考资源

☆ 背景介绍

起因是在IDA中快速识别静态链接的OpenSSL库函数SSL_read、SSL_write,有很多搞法。参看

《IoT设备逆向工程中的函数识别》
http://scz.617.cn:8/misc/201905081756.txt

就此次原始需求而言,上文中各方案显得重型。bluerust用了一种轻型方案,基于特征字符串交叉引用定位多个函数,根据函数特征过滤出最终结果,这是逆向工程常见动作。函数特征包含但不限于对指定地址的交叉引用计数,call指令计数、block计数、参数个数等等。我卡在IDAPython获取函数参数个数这个问题上。

☆ idaapi.decompile

uid(5162883301)、uid(3907374211)指出可以借助idaapi.decompile获取函数参数个数,uid(7483708707)在后台直接给我下列完整实现。

#
# IDASDK77includetypeinf.hpp
#
# dos2unix CC_Map.txt
# awk -F' ' '{printf("%8s : "%s",n",tolower($3),$1);}' CC_Map.txt
#
CC_Map  = 
{
    0x00 : "CM_CC_INVALID",
    0x10 : "CM_CC_UNKNOWN",
    0x20 : "CM_CC_VOIDARG",
    0x30 : "CM_CC_CDECL",
    0x40 : "CM_CC_ELLIPSIS",
    0x50 : "CM_CC_STDCALL",
    0x60 : "CM_CC_PASCAL",
    0x70 : "CM_CC_FASTCALL",
    0x80 : "CM_CC_THISCALL",
    0x90 : "CM_CC_MANUAL",
    0xa0 : "CM_CC_SPOILED",
    0xb0 : "CM_CC_GOLANG",
    0xc0 : "CM_CC_RESERVE3",
    0xd0 : "CM_CC_SPECIALE",
    0xe0 : "CM_CC_SPECIALP",
    0xf0 : "CM_CC_SPECIAL"
}

#
# from uid(7483708707)
#
# generate_func_info( idc.here() )
#
def generate_func_info ( ea ) :
    func                = idaapi.get_func( ea )
    cfunc               = idaapi.decompile( func )
    #
    # 这两步有替代方案
    #
    func_type           = idaapi.tinfo_t()
    cfunc.get_func_type( func_type )
    #
    # IDASDK77includetypeinf.hpp
    #
    nargs               = func_type.get_nargs()
    arg_list            = []
    for i in range( nargs ) :
        arg_list.append( str( func_type.get_nth_arg(i) ) )
    rettype             = str( func_type.get_rettype() )
    fi                  = idaapi.func_type_data_t()
    func_type.get_func_details( fi )
    func_info           = {}
    func_info['args']   = arg_list
    func_info['ret']    = rettype
    func_info['cc']     = CC_Map[fi.cc]
    func_info['name']   = idc.get_func_name( ea )
    return func_info
#
# end of generate_func_info
#
#
# generate_func_info_1( idc.here() )
#
def generate_func_info_1 ( ea ) :
    func                = idaapi.get_func( ea )
    cfunc               = idaapi.decompile( func )
    nargs               = cfunc.type.get_nargs()
    arg_list            = []
    for i in range( nargs ) :
        arg_list.append( str( cfunc.type.get_nth_arg(i) ) )
    rettype             = str( cfunc.type.get_rettype() )
    fi                  = idaapi.func_type_data_t()
    cfunc.type.get_func_details( fi )
    func_info           = {}
    func_info['args']   = arg_list
    func_info['ret']    = rettype
    func_info['cc']     = CC_Map[fi.cc]
    func_info['name']   = idc.get_func_name( ea )
    return func_info
#
# end of generate_func_info_1
#

bluerust指出,对idc.get_type(idc.here())的返回值进行字符串解析也能得到一些信息,形如

'__int64 __fastcall(__int64, void *, int)'

显然idaapi.decompile更优雅,此处有其详解

IDAPython CTREE
https://gist.github.com/icecr4ck/9dea9d1de052f0b2b417abf0046cc0f6

generate_func_info_2与generate_func_info本质相同,取函数参数的办法略有不同,用到了cfunc.argidx,uid(3907374211)也提到这个点。

#
# generate_func_info_2( idc.here() )
#
def generate_func_info_2 ( ea ) :
    func                = idaapi.get_func( ea )
    cfunc               = idaapi.decompile( func )
    lvars               = cfunc.get_lvars()
    arg_list            = []
    for i in cfunc.argidx :
        tinfo   = lvars[i].type()
        arg_list.append( tinfo )
    rettype             = cfunc.type.get_rettype()
    fi                  = idaapi.func_type_data_t()
    cfunc.type.get_func_details( fi )
    func_info           = {}
    func_info['args']   = arg_list
    func_info['ret']    = rettype
    func_info['cc']     = CC_Map[fi.cc]
    func_info['name']   = idc.get_func_name( ea )
    return func_info
#
# end of generate_func_info_2
#

☆ FLARE IDA Decompiler Library (FIDL)

uid(5162883301)、bluerust分别提及FIDL的实现,我没用过这个IDA插件,简单测试之。

1) 安装FIDL

参看

《Portable Python》
http://scz.617.cn:8/python/202011191444.txt

《Portable IDA+IDAPython》
http://scz.617.cn:8/python/202011182246.txt

https://fidl.readthedocs.io/en/latest/installation.html

测试环境是"Portable Python + Portable IDA",FIDL严重依赖IDA,不想安装到"Portable Python"中,只想在"Portable IDA"环境中使用FIDL。

git clone https://github.com/mandiant/FIDL.git FIDL
cd /d X:workFIDL
X:tempPython39python.exe -m pip install .

"X:tempPython39"源自"X:GreenPythonportablePython39",此外还复制了一份"X:tempPython39_"。安装完FIDL,用BC进行目录比较,找出实际改动:

X:tempPython39
  share
    doc
      networkx-2.8.8
  Lib
    site-packages
      FIDL
      FIDL-1.3.dist-info
      networkx
      networkx-2.8.8.dist-info
      six-1.16.0.dist-info
      six.py

share目录下是文档,不需要;将"X:tempPython39Libsite-packages"下的几项复制到"X:GreenIDALibsite-packages"即可。此外,FIDL依赖bz2模块,需要复制_bz2.pyd到IDA目录。

X:tempPython39_bz2.pyd
X:GreenIDA_bz2.pyd

2) 用FIDL获取函数参数个数

在IDA的Python提示符中测试如下命令

import FIDL.decompiler_utils as fdu
c   = fdu.controlFlowinator( ea=idc.here(), fast=False )
dir(c)
c.args
len(c.args)
dir(c.args[0])
type(c.args[0].ti)
c.args[0]
c.args[0].name
c.args[0].type_name
c.args[0].size

3) FIDL对idaapi.decompile的封装

参看

https://github.com/mandiant/FIDL/blob/master/FIDL/decompiler_utils.py

就此次原始需求而言,主要查看这些类与函数

class controlFlowinator
def my_decompile
def get_function_vars
def get_return_type

由于uid(7483708707)珠玉在前,很容易看懂FIDL如何封装idaapi.decompile的,但说实话,无基础时直接看FIDL实现,这些封装没那么浅显易懂。

☆ 后记

非常感谢uid(7483708707)提供具体实现,bluerust看过其实现后大加赞赏,同时感谢uid(5162883301)、uid(3907374211)提供靠谱思路。此番微博请教技术问题,得到的全部是有效回复,实属罕见,真地是曲指可数的几次之一。

bluerust作为湾区人形蜘蛛Top 10,爬到了[2],与IDAPython有交集的逆向工程人员,不妨遍历之。事后与bluerust复盘时,有一段对话

scz: 哦,我想起来了,我应该直接召唤hume的!
brt: 我本来想说,这事情,天下没有比hume更强的
brt: 说来惭愧,从没遍历过IDA SDK文档
scz: hume干过
scz: 超级老司机
brt: 还是我勤奋不足!
scz: 是你精力发散
brt: 那可不,朝廷美女事事关心

☆ 参考资源

(略,见TXT)

原文始发于微信公众号(青衣十三楼飞花堂):IDAPython获取函数参数个数

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年11月3日18:36:25
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   IDAPython获取函数参数个数https://cn-sec.com/archives/1388472.html

发表评论

匿名网友 填写信息