IDAPython实战项目——DES算法识别
在CTF的逆向中我们需要的是找到加密的主函数,结合了yara的识别原理,通过对常量数组的引用的查找,一步步递归构建调用树。调用树根部就是可能的密码算法主函数。
由于这种办法需要常量分布于算法的各个步骤中,所以尝试选取DES算法
一、DES算法识别的主要流程
1.1 背景介绍
密码学算法识别在很早之前就已经有成熟的实现。我遇到过的实现有如下几种:
对于内嵌的代码,典型的有PEiD的KryptoAnalyzer插件。原理很简单,一般的密码学算法都有特定的常量数组,例如MD5的state(0123456789ABCDEFFE…10),DES的P_Box等等。找到该算法的一个常量数组就可以判定存在该密码学算法。
对于使用第三方库,典型的有使用IDA的FILRT签名的快速识别,将常见的密码学库做成签名。那么调用的这个第三方库的所有加密函数都会被识别。
这篇文章主要讨论了第一种算法的实现与优化(因为KryptoAnalyzer只针对Windows平台,所以该算法实现对于辅助elf文件分析是有意义的)。
1.2 实现原理
对于第一种算法,以KryptoAnalyzer为例,它只会给出一个p_box识别的位置以及调用该常量的位置
而事实上例如DES之类的算法存在非常多的常量,我们完全可以尝试根据这些常量的位置,调用关系构建调用树,最终找到可能的主函数。
例如常量const1,const2,const3被addr1,addr2,addr3处的代码引用,这三处代码分别属于func1,func2,func3,而三个函数调用关系为func3调用func2,func1,我们可以根据常量、调用常量的位置(所属函数)以及调用这些调用常量的函数的函数构建关系图,最终找到可能的主函数func3。
1.3 实现流程
那么我们的实现流程如下:
选择需要的常量
查找各个常量所在位置
查找引用各个常量的代码地址,查找这些地址所属函数,以及调用这些函数的地址以及其所属函数,构建调用树
1.4 思路局限性
当前思路由于需要大量常量,所以目前只适用于常量较多且分布于算法实现各个步骤的算法,因此本次实现选择了DES。
另外,即使构建了调用树,也无法百分百确定这个调用树的根就是算法的主函数,例如根为func,则主函数有可能是调用func的func1,需要使用者自行动态调试判断。且存在算法被篡改的可能性,此时就需要具体分析以寻找被篡改部分了。
需要注意的是,验证过程中注意输入类型,输入类型可能是一个String格式,有可能是自定义类型,一切需要具体情况具体分析。
二、DES算法
2.1 DES算法简介
DES算法为密码体制中的对称密码体制,又被称为美国数据加密标准。
DES是一个分组加密算法,典型的DES以64位为分组对数据加密,加密和解密用的是同一个算法。
密钥长64位,密钥事实上是56位参与DES运算(第8、16、24、32、40、48、56、64位是校验位,使得每个密钥都有奇数个1),分组后的明文组和56位的密钥按位替代或交换的方法形成密文组。
对于DES算法,我将其简单分为两大部分:秘钥处理部分和密文加密部分
1.2 秘钥处理流程
第一步是秘钥初始变换,输入的秘钥按照下文的常量表来完成一个变换
之后变换完输出的秘钥拆分成左右两部分C0与D0,C0与D0按照下表分别进行移位
移位完成后得到16个左右变换后的子秘钥C0-C15,D0-D15,将C0与D0,C1与D1…Ci与Di合并,按照下表压缩
这样我们得到的16个结果就是最终需要的16个子秘钥。
最终用伪代码阐释一遍流程
# 秘钥初始变换,输出结果拆分为
2.3 密文处理流程
首先我们扩充密文到64位
之后我们将输出结果拆分为左右两部分L0与R0,进行16轮运算
第一步是使用下表扩展Ri
之后引入子秘钥$subkey[i]$,与扩展后的Ri进行异或运算
之后将异或结果拆分为$8*6$bit分组,每个分组用下面S盒变换后组合
最终将8个s盒输出重新组合,输入下表处理
最终输出的就是Li+1,也就是说将Ri进行三个变换后作为下一轮Li+1输入
经过16轮运算后,将最终的L15与R15组合,进行一次置换
用伪代码阐释一下
# 初始置换L[0],R[0]=sub_key_permutation(plaintext)# 16轮循环处理for i in range(16): # message_expansion扩展
exp_r=message_expansion(Ri) # 与子秘钥异或
xor_r=exp_r^subkey[i] # S盒变换
s_r=S[xor_r] # 处理S盒输出
L[i+1]=right_sub_message_permutation(s_r)
R[i+1]=L[i]# 最终逆变换final_message_permutation(L[15],R[15])
三、常量查找
在第一部分的DES算法简介中,我们已经了解了DES算法中涉及到的所有常量。那么我们接下来就是在IDA中查找对应的数据了。
3.1 为什么是IDA Python
在这边我们首先要搞明白一个虚拟内存和磁盘的概念。一般我们的可执行文件在操作系统中是以文件形式存在的,也就是存储在磁盘中。而运行时操作系统会将其装载到虚拟内存中(真正执行还需要装载到物理内存中,但与本文无关,此处也不做讨论)。在虚拟内存和磁盘中文件内容是不变的,但是占用大小发生了改变。如下图:
最主要的改变就是对齐大小发生改变。原先在磁盘中每个区会被补全为$FileAligmnetn$大小,而在内存中则补全为$SectionAlignmentn$的大小(n为正整数)。因此我们可以在磁盘中以文件形式读取可执行文件查找,但是查找到的常量位置是文件偏移。需要转换为虚拟内存地址后才能使用。
而在IDA中,可执行文件直接按照内存中的排列显示。因此省去了转换虚拟内存地址的过程。
此外,我们需要查找引用这些常量的代码地址,因此我们需要使用到IDA的查找交叉引用过程,这个是IDA的一个非常强大的功能,能够定位所有显式调用的代码地址。(例如 call 0x401000就是显示调用,而call eax,eax=0x401000则无法在静态分析中得到)
IDA Python并非IDA的原生脚本语言,但是IDA Python支持所有IDA原生语言idc的特性,并且可以使用所有Python 2的库(建议添加系统路径):
关于IDA python的基础知识,此处就不再赘述了,有兴趣的可以找一下IDA Python-Book的文档查看一下
3.2 确定查找范围
对于查找范围,简单粗暴的办法就是用MinEA()到MaxEA(),也就是最小的虚拟地址到最大的虚拟地址。不过这种方法效率不是很高,而且存在误报风险。
一般常量存放在.rdata段,也有少量在.data段,因此搜索两个段足以。注意,此处可能存在文件将段名修改的情况,例如.data段换为DATA段,所以建议先查看下段名之后指定
3.3 编写查找常量
查找函数非常简单,但是有一些点需要注意:
常量存储不一定都是BYTE格式,有很大可能是WORD、DWORD乃至QWORD,因此需要能够支持指定数据格式类型的匹配。
在密码学中我们的索引下标(压缩或扩展变换中使用的数组)都是从1开始的,而在C语言中是从0开始的,所以匹配时需要注意可能存在一个单位的偏移。
def findCrypt(pattens,size=1):
# 目前已支持搜索data,rdata段,支持由于C语言数组下标造成的偏移的矫正,支持Crypto的单个数据单位大小指定
四、构建调用树
那么在先前我们找到了所有的常量数组的地址。之后就是查找交叉引用了。
IDAPython 对此提供了DataRefsTo的API,表示查找调用此处的代码地址,并将代码地址所属的函数地址保存,下面代码中func_dict的key是函数地址,而键值是该函数调用的常量数组
之后我们可以进一步使用CodeRefsTo来查找调用这些函数的代码地址以及这些代码地址所属的函数来构建调用树,其中CodeRefsTo的第二个参数0表示正常流顺序。调用树结构用list的嵌套来表示从属关系。
最终我们得到调用树结构,并将其打印出来
# 绘制树状图格式'''
href http://paste.ubuntu.org.cn/104713
'''blank=[chr(183)]##此处为空格格式;Windows控制台下可改为chr(12288) ;linux系统中可改为chr(32)【chr(32)==' ' ;chr(183)=='·' ;chr(12288)==' '】tabs=['']def tree(lst):
l=len(lst) if l==0:print('─'*3) else: for i,j in enumerate(lst): if i!=0: print tabs[0], if l==1:
s='─'*3
elif i==0:
s='┬'+'─'*2
elif i+1==l:
s='└'+'─'*2
else:
s='├'+'─'*2
print s, if type(j)==type([]) or isinstance(j,tuple): if i+1==l:
tabs[0]+=blank[0]*3
else:
tabs[0]+='│'+blank[0]*2
tree(j) else: try:
j='sub_%08x'%j; except: 1+1;
print(j);
tabs[0]=tabs[0][:-3]
tree(final_tree)
最终成功得到图的结构,得到调用图如下:
┬── ┬── sub_004026a0
│ └── ┬── sub_00402590
│ └── ┬── sub_00402140
│ ├── ─── initial_message_permutation
│ ├── ┬── sub_004023b0
││ └── ┬── sub_00402280
││ └── ─── right_sub_message_permutation
│ ├── ┬── S
││ └── message_expansion
│ ├── sub_004021e0
│ └── ─── final_message_permutation
│ └── ┬── sub_00402310
│ └── ┬── sub_key_permutation
│ ├── initial_key_permutaion
│ └── initial_key_permutaion
最终判断出各个函数的调用关系。
五、总结
通过IDA Python实现了调用图生成,完成了对DES的识别与分析。
六、参考文献
FLIRT 常见库地址
https://github.com/Maktm/FLIRTDB
https://github.com/push0ebp/sig-database
IDA Python-book 翻译版地址
https://bbs.pediy.com/thread-225920.htm
DES 算法参考
https://github.com/dhuertas/DES
调用图绘制
http://paste.ubuntu.org.cn/104713
IDAPython实战项目——DES算法识别的更多相关文章
- 基于DES算法加密的防撞库密码系统项目总结
项目内容:基于DES算法加密的防撞库密码系统 小组名:zqhzkzkj 目标:1.对用户输入的8位字符进行DES加密,要求用户输入8位密钥 2.对于不同的网站,不同的用户名生成不同的密码 小组成员:周 ...
- 再一波Python实战项目列表
前言: 近几年Python可谓是大热啊,很多人都纷纷投入Python的学习中,以前我们实验楼总结过多篇Python实战项目列表,不但有用还有趣,最主要的是咱们实验楼不但有详细的开发教程,更有在线开发环 ...
- 深度学习之PyTorch实战(3)——实战手写数字识别
上一节,我们已经学会了基于PyTorch深度学习框架高效,快捷的搭建一个神经网络,并对模型进行训练和对参数进行优化的方法,接下来让我们牛刀小试,基于PyTorch框架使用神经网络来解决一个关于手写数字 ...
- KNN (K近邻算法) - 识别手写数字
KNN项目实战——手写数字识别 1. 介绍 k近邻法(k-nearest neighbor, k-NN)是1967年由Cover T和Hart P提出的一种基本分类与回归方法.它的工作原理是:存在一个 ...
- Python实战项目网络爬虫 之 爬取小说吧小说正文
本次实战项目适合,有一定Python语法知识的小白学员.本人也是根据一些网上的资料,自己摸索编写的内容.有不明白的童鞋,欢迎提问. 目的:爬取百度小说吧中的原创小说<猎奇师>部分小说内容 ...
- MFC 简单实现 DES 算法
前言 徐旭东老师说过学者就应该对知识抱有敬畏之心,所以我的博客的标题总喜欢加上"简单"二字,就是为了提醒自己,自己所学知识只是皮毛,离真理还远矣. DES 算法 DES算法是密码体 ...
- FaceRank,最有趣的 TensorFlow 入门实战项目
FaceRank,最有趣的 TensorFlow 入门实战项目 TensorFlow 从观望到入门! https://github.com/fendouai/FaceRank 最有趣? 机器学习是不是 ...
- TensorFlow 中文资源全集,官方网站,安装教程,入门教程,实战项目,学习路径。
Awesome-TensorFlow-Chinese TensorFlow 中文资源全集,学习路径推荐: 官方网站,初步了解. 安装教程,安装之后跑起来. 入门教程,简单的模型学习和运行. 实战项目, ...
- [深度应用]·实战掌握Dlib人脸识别开发教程
[深度应用]·实战掌握Dlib人脸识别开发教程 个人网站--> http://www.yansongsong.cn/ 项目GitHub地址--> https://github.com/xi ...
随机推荐
- Day9作业:socket之FTP工具
代码传的太累,直接发个github的链接吧! https://github.com/ccorzorz/Socketserver_FTP 上两张图给抛砖引玉下吧: 后台管理: FTP程序,包括客户端和s ...
- 在Win7环境下搭建Geant4工作平台
本物理专业小硕,现在材料实验室工作,研究方向大概是核屏蔽材料的软件模拟吧.其实实验室里大多数师兄弟都是搞焊接的,平时能接触到这类直接给源码自己编译的软件的机会基本为零,所以一切都靠自己探索,成功搭建了 ...
- python介绍,计算机组成。内存分布,进制,操作系统介绍
学习小方法 三个W一个Hwwwh:what(是什么) why(为什么) where(怎么用) how(如何用) 来思考知识点多练,多写,多敲代码增加熟练度与代码量 Python 是一门面向后台的编 ...
- OpenGL学习笔记 之一 (基本的图形绘制)
参考网址:http://www.cnblogs.com/FredCong/archive/2012/10/13/2722893.html #include <glut.h> #includ ...
- 【miscellaneous】视频浓缩摘要简介
视频摘要,就是以自动或者半自动的方式,通过分析视频的结构和内容存在的时空冗余,从原始视频中提取有意义的片段,将它们以某种特点的方式重新组合成紧凑的.能够充分表现视频语义内容的浓缩视频. 一.静态视频摘 ...
- 1、4 前后端分离,写静态HTML文件,通过ajax 返回数据
1.html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <ti ...
- mac 已损坏 移至废纸篓
1.问题描述: 从网页下载的安装包,总是提示“已损坏,移至废纸篓”这类的信息 2.原因: 系统版本过高,对安全性进行了校验. 3.解决方案:命令行输入以下命令,然后输入密码 sudo spctl -- ...
- docker下部署服务
一.zabbix部署 需求: 因最近项目过多,人力监控耗费时间,打算部署一个zabbix,但又不想部署在宿主机上,就想起了docker,docker快速的移植性是最大的亮点,好了,言归正传开始干. 部 ...
- [转帖]新手必读,16个概念入门 Kubernetes
新手必读,16个概念入门 Kubernetes https://www.kubernetes.org.cn/5906.html 2019-09-29 22:13 中文社区 分类:Kubernetes教 ...
- ORA-12514错误分析
ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务 的解决方法 ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务 有同事遇到这个问题,现总结一下,原因如下: ...