在日常分析工作中, 面对一个全新的样本, 分析师们总是喜欢首先进行初级的静态分析来熟悉样本功能, 这其中就包含了对字符串、资源、导入表等数据的观察. 恶意代码编写者们为了混淆分析师的视线, 经常将一些敏感的字符串、资源数据进行各式各样的加密后进行存储, 在代码运行时再通过解密函数进行解密
因此, 对于一个分析师而言 , 熟悉常见的加密解密方式是十分必要的, 这可以帮助分析师快速分辨哪些是加密数据哪些是正常的乱码, 从而提取出关键的信息.
本次笔记仅简单的记录一下常见加密的特征,方便以后查找,想要对加密解密比较熟练还是建议多多逆向一些包含加密算法的样本
对于恶意代码编写者而言, 加密的目的仅仅是为了拖慢分析进度或逃避自动化引擎, 因此他们不会采用特别牢固的加密算法(勒索病毒除外), 只要能隐藏原数据, 即使最简单的x=x+1也可以作为加密算法
凯撒密码是历史上第一个加密算法, 如上, 只是将每个字符对应的Ascii码加3, 这样就能达到最简单的加密, 如果一个引擎的检测逻辑是ABCDE
, 那么这种凯撒密码就达到了最简单的免杀
功能
xor这个指令之所以能被用作常用的加密, 是因为亦或存在一个特点, 一个数A对B进行两次亦或,结果仍然是A
, 正是这种密钥相同, 算法相同的特征, 使xor加密十分简单且有效, 但解密也十分简单. xor在一个程序中常用于清空寄存器, 因此当xor指令包含立即数或两个操作寄存器不同时, 就需要留意了, 很可能是xor解密处的代码
由于xor单字节加密很容易被发现, 因此也衍生出了变种算法,下面列举一些:
非0非密钥的单字节亦或加密
即当被加密的字节为0或密钥本身时, 不进行亦或处理
连锁xor ,即当前字节的xor所用密钥为上一字节xor后的密文
xor由于其基础指令简单 因此想要扩展也很容易, 对于分析师而言, 只需关注xor所在函数的整体流程, 参数即可快速识别出解密函数
Base64加密经常在恶意代码中出现, 其最大特点是在字符串中包含一段64个字符长度的密钥,通常为A-Za-z0-9+/
, 其密文长度必然为4的整数倍
, 大部分密文结尾会跟1~3个=
进行位数填充, 且密文全部为密钥内的字符, 排序无规则, 很好识别, 如下:
对于Base64的解密, 如果是常规密钥, 则使用notepad++自带的解密即可
但是当Base64加密使用的密钥不是常用的A-Za-z0-9+/
, 而是作者自己修改后的密钥(如将某两个字符换个位置), 那么使用notepad++就无法直接还原明文,因此在我们基本确定算法为Base64后, 也要留意字符串列表中的64位密钥
一些恶意代码编写者不满足于简单的加密, 他们会选择更为安全的标准加密, 虽然这种加密具备了安全性, 但由于其具备很多特征, 使其很容易被识别出来
字符串特征
一些加密库在被编译到程序中时, 会留下一些版本号 说明信息等字符串, 如SSL
导入表特征
当程序引用了加密库中的一些函数时, 可以通过导入表进行识别
大部分涉及加密的微软函数都以Crypt或Cert为前缀
常量特征
通过使用FindCrypt2插件 (IDA插件,PYG的IDA 7.5已集成), 可以帮我们识别出某些密钥, 如下图, 插件帮我们识别到了Base64的密钥
对于某些恶意代码作者恶言, 他们会选择自行编写加密算法 而不是采用常见的库, 对于这种自写加解密, 我们无法在少量样本的条件下提取出有效的特征来定位加密算法,因此我们需要换一种思路
对于任意一个程序而言(恶意或非恶意), 识别自写加密都要围绕两个方向进行输入和输出
, 无论加密算法多么强大, 解密算法多么隐蔽, 其在输入或输出功能的前后必然会进行加解密的操作, 如send writeFile
在网络交互中, 为了防止数据包被窃取, 通常会采用加密封包的形势进行传输, 这时我们站在开发者的角度去思考, 若我们想要对封包进行加密, 则通常会在send函数前进行加密, recv函数后进行解密, 这就是输入输出的概念,因此当我们想定位加密算法或查看明文时, 则可以通过定位输入输出函数位置, 通过观察其前后代码来获取我们所需的信息
下面我们来看书中给出的一个例子,我们目前已知该程序会创建一个文件存储一份被加密的数据, 通过种种特征我们无法匹配到已知的加密方式, 这时我们可以通过输入输出原理, 来确定该程序在writeFile之前必然会进行加密的操作
因此我们定位WriteFile函数的调用, 看到了上图中的代码
右侧loc_40122A代码块为写文件操作, 此时的数据已经被加密, 在这段代码之前我们看到了一个循环结构(左侧), 该结构包含了一个xor指令, 其操作的内存也包含了文件buffer的数据, 那么到这里我们就可以确定WriteFile之前的这段循环就是在对数据进行加密
这章讲的东西不是很多, 主要讲解在面对一个具有密文的样本时, 如何定位、还原或绕过其加解密函数, 这种思想在其他技术上也有应用 , 总结为连带
当你无法定位某个行为的代码时, 可以通过定位该行为的附加行为或附加行为的附加行为来定位至该行为. 这也要求分析师们有基本的正向代码开发思维
通过火绒剑的行为捕捉,我们可以发现样本对url进行了base64的加密
利用IDA搜索字符串 ,看到了一个用于拼接url字符串的模板
我们对该字符串进行交叉引用, 发现了要拼接的字符串其中一个来源于sub_401300的返回值
该函数内部进行了资源的取出后调用了sub_401190,参数为资源的数据
经查看资源中包含乱码, 推测为密文
401190处的代码为循环xor解密 , 密钥为0x3B, 利用010进行解密后发现明文为一段url, 所以得出结论, 该样本将url通过0x3B亦或的方式存储在资源节中
比较恶意代码中的字符串(字符串命令的输出)与动态分析提供的有用信息,基于这些比较,哪
些元素可能被加密?
使用IDA Pro搜索恶意代码中字符串‘xor’,以此来查找潜在的加密,你发现了哪些加密类型?
恶意代码使用什么密钥加密,加密了什么内容?
使用静态工具FindCrypt2、Krypto ANALyzer(KANAL)以及IDA嫡插件识别一些其他类型的加
密机制,你发现了什么?
什么类型的加密被恶意代码用来发送部分网络流量?
Base64编码函数在反汇编的何处?
恶意代码发送的Base64加密数据的最大长度是什么?加密了什么内容
恶意代码中,你是否在 Base64加密数据中看到了填充字符(=或者==)
这个恶意代码做了什么?
使用动态分析,确定恶意代码创建了什么?
使用静态分析技术,例如xor指令搜索、FindCrypt2、KANAL 以及IDA 嫡插件,查找潜在的加
密,你发现了什么?
基于问题1的回答,哪些导入函数将是寻找加密函数比较好的一个证据?
加密函数在反汇编的何处?
从加密函数追溯原始的加密内容,原始加密内容是什么?
你是否能够找到加密算法?如果没有,你如何解密这些内容?
使用解密工具,你是否能够恢复加密文件中的一个文件到原始文件?
ABCDE
=
=
=
> DEFGH
Z2V0aG9zdGJ5bmFtZQ
=
=
/
/
密文不是
4
的倍数, 需要在尾部补齐
2
个
=
MTIzNDU2Nzg5
/
/
密文是
4
的倍数 无需补齐
=
Z2V0aG9zdGJ5bmFtZQ
=
=
/
/
密文不是
4
的倍数, 需要在尾部补齐
2
个
=
MTIzNDU2Nzg5
/
/
密文是
4
的倍数 无需补齐
=
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)