长亭百川云 - 文章详情

[系统安全] 五十六.恶意软件分析 (8)IDA Python基础用法及CFG控制流图提取详解[下]

娜璋AI安全之家

149

2024-07-14

2024年4月28日是Eastmount的安全星球 —— 『网络攻防和AI安全之家』正式创建和运营的日子,该星球目前主营业务为 安全零基础答疑、安全技术分享、AI安全技术分享、AI安全论文交流、威胁情报每日推送、网络攻防技术总结、系统安全技术实战、面试求职、安全考研考博、简历修改及润色、学术交流及答疑、人脉触达、认知提升等。下面是星球的新人券,欢迎新老博友和朋友加入,一起分享更多安全知识,比较良心的星球,非常适合初学者和换安全专业的读者学习。

该系列文章将系统整理和深入学习系统安全、逆向分析和恶意代码检测,文章会更加聚焦,更加系统,更加深入,也是作者的慢慢成长史。漫漫长征路,偏向虎山行。享受过程,一起奋斗~

前文介绍了IDA Python配置过程和基础用法。这篇文章将尝试利用IDA Python提取恶意软件的控制流图(CFG),再为后续的恶意软件家族分类或溯源提供帮助。由于作者是初学者,因此会遇到很多问题,欢迎各位大佬和读者指导,同时感谢李师弟的指导和交流。基础性基础,且看且珍惜。

文章目录:

  • 一.测试样本生成

  • 二.IDA手动提取CFG

  • 1.IDA概述

  • 2.IDA手动保存CFG

  • 三.IDA Python提取CFG

  • 1.函数提取

  • 2.样本提取

  • 四.CFG提取问题

  • 五.总结

作者的github资源:

声明:本人坚决反对利用教学方法进行犯罪的行为,一切犯罪行为必将受到严惩,绿色网络需要我们共同维护,更推荐大家了解它们背后的原理,更好地进行防护。(参考文献见后)


一.测试样本生成

首先,我们编写一段C语言程序并生成对应的可执行文件。如下图所示:

该程序逻辑比较简单,包含一个条件语句、一个循环语句和一个函数调用。

`#include <stdio.h>``   ``int sub_num(int a, int b) {`    `int s;`    `s = a + b;`    `printf("函数运算结果: %d\n",s);`    `return s;``}``   ``int main() {`    `int i,m,n;`    `int result=0;``   `    `scanf("%d %d",&m,&n);`    `printf("输入的数字为:%d %d",m,n);``   `    `//条件语句`    `if (m>10) {`        `printf("数字大于10\n");`    `}`    `else {`        `printf("数字小于等于10\n");`    `}``   `    `//循环语句`    `for (i=0; i<=10; i++) {`        `result += i;`        `i++;`    `}`    `printf("1 + 2 + ... + 10 = %d\n",result);`    `    //函数`    `result = result + sub_num(m,n);`    `printf("最终输出结果: %d\n",result);`    `return 0;``}`

输出结果如下图所示:

编译生成的中间文件如下所示:


二.IDA手动提取CFG

接着介绍IDA Python配置过程,并讲解如何实现IDA手动提取控制流图(CFG)。

1.IDA概述

IDA Pro(Interactive Disassembler Professional)简称“IDA”,是Hex-Rays公司出品的一款交互式反汇编工具,是目前最棒的一个静态反编译软件,为众多0day世界的成员和ShellCode安全分析人士不可缺少的利器。IDA Pro具有强大的功能,但操作较为复杂,需要储备很多知识,同时,它具有交互式、可编程、可扩展、多处理器等特点,可以通过Windows或Linux、MacOS平台来分析程序, 被公认为最好的逆向工程利器之一。

第一步,打开IDA Pro32软件选择一个exe文件载入,它将是我们要进行分析的程序,所分析的程序时上面撰写的C语言代码。

  • 在“Load a new file”窗口中选择装载PE文件,包括text(代码块)、data(数据块)、rsrc(资源块)、idata(输入表)和edata(输出表)等,也可以载入二进制文件。

IDA反汇编包括两个阶段,首先将程序的代码和数据分开,分别标记函数并分析参数调用、跳转、指令关系等;接着如果IDA能识别文件的编译类型,就装载对应的编译器特征文件,给各函数赋名。同时,IDA会创建一个数据库,其组件分别保存在“.id0”、“.id1”、“.nam”和“.til”的文件里。

第二步,在弹出确认窗口中选择“Don’t show this message again”选项,在“Check for Hex-Rays product updates”中点击“OK”。运行结果如下图所示,接着可以开始我们的逆向分析。

第三步,选择“_main_0”函数查看程序的控制流图,下图可以看到代码及部分注释。

第四步,按下F5能够查看对应的源代码,另一个自定义函数为,可以查看其加分操作。

  • v3 = sub_401005(v7, v6);

第五步,可以在Graph View和Text View中切换。

最后,关闭IDA Pro并保存数据库文件,下次载入时,可以直接加载数据库文件,获取之前分析的状态。


2.IDA手动保存CFG

函数调用图
在菜单栏中点击“view–>graphs–>Function calls”,查看函数调用图。

显示结果如下图所示:

  • 为啥显示这么复杂呢?

  • 如何提取关键函数的调用关系呢?

函数流程图
在菜单栏中点击“view–>graphs–>flowt chart”,查看函数流程图,其显示效果与IDA自带的反汇编流程视图相似。

在WinGraph中点击“file–>save as”,将调用关系另存为GDL(graph discription language)文本为test01.gdl。

保存的文件结果显示如下:


三.IDA Python提取CFG

该部分感谢李师弟的帮助,通过IDA Python批量提取样本的CFG,并生成gdl文件。整个工作目录如下所示:

`- get_cfg.py``- get_cfg_main.py``- get_sample_cfg.py``- sample`  `- test01.exe`

1.函数提取

首先定义主函数,通过主函数调用IDA软件和样本的路径,并构建analyse_module函数分析样本的CFG。关键代码如下所示:

`# coding: utf-8``# By:Eastmount & LJC 2024-05-10``import os``   ``#完整路径跨目录调用``IDA_PATH = r"C:\Software\IDAPro7.5\ida.exe"``IDA64_PATH = r"C:\Software\IDAPro7.5\ida64.exe"``analyser = r"D:\test_cfg\get_cfg.py"``   ``#命令行脚本批量获取样本cfg``def analyse_module(sample_list, sample_name):`    `ida_exe = IDA_PATH`    `for i in range(len(sample_list)):`        `sample = sample_list[i]`        `name = sample_name[i]`        `cmd = " ".join([ida_exe, f"-c -A -S" + '"' + analyser + ' ' + name + '"',  sample])`        `print(cmd)`        `os.system(cmd)``   `    `return True``   ``if __name__ == '__main__':`    `#批量样本地址`    `file_path = r'D:\test_cfg\sample'`    `sample_name = os.listdir(file_path)`    `sample_list = []`    `for i in range(len(sample_name)):`        `sample = file_path + '\\' + sample_name[i]`        `print(sample)`        `sample_list.append(sample)``   `    `analyse_module(sample_list, sample_name)`    `print("over!!!")`

接着调用get_cfg.py文件分别提取函数CFG信息,关键代码如下所示:

  • get_func_name
  • idaapi.get_func
  • idc.get_func_attr
  • gen_flow_graph
`#coding: utf-8``# By:Eastmount & LJC 2024-05-10``import idaapi``import ida_gdl``import idautils``import idc``   ``def main():``   `    `functions = idautils.Functions()`    `    for func_ea in functions:`        `func_name = idc.get_func_name(func_ea)`        `func = idaapi.get_func(func_ea)`        `start_ea = idc.get_func_attr(func_ea, FUNCATTR_START)`        `end_ea = idc.get_func_attr(func_ea, FUNCATTR_END)`        `gdl_file_name = "CFG_{}.gdl".format(func_name)`        `flowchart = idc.gen_flow_graph(gdl_file_name, "cfg", start_ea, end_ea, CHART_GEN_GDL)`        `if flowchart:`            `print("CFG for function {} has been saved as {}".format(func_name, gdl_file_name))`        `else:`            `print("Failed to save CFG for function {}".format(func_name))``   ``if __name__ == "__main__":`    `idaapi.auto_wait()`    `main()`    `idc.qexit(0)`

运行结果如下图所示:

该程序成功提取了各函数的CFG并生成gdl文件,然后部分函数是系统自带(未被使用)也被提取。


2.样本提取

接着调用get_sample_cfg.py文件分别提取样本的CFG信息,核心思想是捕获最大地址和最小地址之间的内容,关键代码如下所示:

`#coding: utf-8``# By:Eastmount & LJC 2024-05-10``import idautils``import ida_gdl``import idaapi``import idc``import time``   ``#根据样本最小地址和最大地址生成整个样本的cfg``def main(name):`    `start_ea = ida_ida.inf_get_min_ea()`    `end_ea = ida_ida.inf_get_max_ea()`    `print(start_ea)`    `print(end_ea)`    `filename = '{}_cfg.gdl'.format(name)`    `flowchart = idc.gen_flow_graph(filename, "cfg", start_ea, end_ea, CHART_GEN_GDL)`    `print(flowchart)`    `time.sleep(5)``   ``if __name__ == "__main__":`    `idaapi.auto_wait()`    `main(idc.ARGV[1])`    `idc.qexit(0)`

运行结果如下图所示:

并且生成和保存两个文件,文件内容如下所示。

  • test01.exe.idb

  • test01.exe_cfg.gdl

至此,成功利用IDA Python提取样本的CFG。


四.CFG提取问题

然后当前代码存在几个问题:

  • 提取了很多不关键的函数或系统函数,如何提取关键函数呢?
  • 是否能利用angr工具实现呢?
  • 如何将gdl文件转换为特征向量供模型学习呢?
  • 如何利用工具显示gdl文件(easy-graph转换成图)

如下图所示,IDA Python提取并生成的gdl文件远远大于导出的文件,并且包含大量系统函数,这些冗余信息会干扰实验分析。

  • test01.exe.idb

  • test01.exe_cfg.gdl(929KB):本文Python代码提取

  • test01.gdl(3.92KB):IDA手工导出

手工导出gdl文件。


五.总结

写到这里,这篇文章就介绍完毕,希望对您有所帮助。

  • 一.测试样本生成

  • 二.IDA手动提取CFG
    1.IDA概述
    2.IDA手动保存CFG

  • 三.IDA Python提取CFG
    1.函数提取
    2.样本提取

  • 四.CFG提取问题

  • 五.总结

『网络攻防和AI安全之家』目前收到了很多博友、朋友和老师的支持和点赞,尤其是一些看了我文章多年的老粉,购买来感谢,真的很感动,类目。未来,我将分享更多高质量文章,更多安全干货,真心帮助到大家。虽然起步晚,但贵在坚持,像十多年如一日的博客分享那样,脚踏实地,只争朝夕。继续加油,再次感谢!

(By:Eastmount 2024-05-13 夜于贵阳 )


参考文献如下,感谢师弟师妹们的帮助和耐心解答。

  • [1] 《The Beginner’s Guide to IDAPython》 by Alexander Hanel

  • [2] 项目地址:https://github.com/idapython

  • [3] 官方IDA Python手册:https://www.hexrays.com/products/ida/support/idapython\_docs/

  • [4] 《IDA pro权威指南》

  • [5] [安全工具][原创]保存IDA Pro中生成的函数调用关系(图)- GreatDane

  • [6] Easygraph:全面高效的图分析与社会计算开源工具 - PeppaRan

  • [7] Genius 二进制文件函数特征提取的复现 - Erio

  • [8] IDA Python安装与使用 - 17bdw

  • [9] ida运行python脚本 - 51cto

  • [10] 恶意功能定位 - 刘师妹

  • [11] 比较简单的IDAPython脚本 - 知乎

前文回顾(下面的超链接可以点击喔):

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2