社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

IDAPython获取函数参数个数

青衣十三楼飞花堂 • 2 年前 • 330 次点击  
创建: 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)在后台直接给我下列完整实现。

#
# IDASDK77\include\typeinf.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 )
    #
    # IDASDK77\include\typeinf.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:\work\FIDL
X:\temp\Python39\python.exe -m pip install .

"X:\temp\Python39"源自"X:\Green\Python\portable\Python39",此外还复制了一份"X:\temp\Python39_"。安装完FIDL,用BC进行目录比较,找出实际改动:

X:\temp\Python39\
  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:\temp\Python39\Lib\site-packages\"下的几项复制到"X:\Green\IDA\Lib\site-packages\"即可。此外,FIDL依赖bz2模块,需要复制_bz2.pyd到IDA目录。

X:\temp\Python39_bz2.pyd
X:\Green\IDA_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)

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/149000
 
330 次点击