逆向中常常出现一些加密算法,如果我们能对这些加密算法进行快速识别则会大大减少我们逆向的难度,虽然IDA已有密码分析神器Findcrypt,但掌握手动分析方法能帮助我们应对更多的情况。这篇文章将介绍逆向中常见的单项散列算法和对称加密算法的识别方法。
0xFF. 前言
在很长一段时间里我经常发现自己面对复杂的加密算法无从下手,可能是因为还没有系统学过密码学吧orz,总之这个问题困扰了我很久。于是最近我花了一些时间来解决自己在密码学这块的薄弱点,写下这篇文章的目的之一也是为了巩固所学知识。
加密算法的部分没有涉及公钥加密算法(因为我不会hh)。每个算法都有一个例子,这些例子出自《加密与解密(第4版)》第6章的随书附带文件和各大比赛中的题目。
0x00. 目录
单向散列算法:
对称加密算法:
0X01. MD5
MD5(Message Digest Algorithm)消息摘要算法对输入的任意长度的消息进行运算,产生一个128位的消息摘要。
MD5的特征是会出现下图中 A,B,C,D 这四个常量。
这里我们直接用《加密与解密(第4版)》随书文件MD5KeyGenMe.exe来分析。
在导入表中找到GetDlgItemTextA函数定位关键代码,两次GetDlgItemTextA函数读取的应该分别是Name和Serial Number:
sub_4012B0函数我们点进去看看发现了MD5的几个特征常量:
还原一下符号,需要注意的一点是连续调用两次MD5_Update相当于把两次的输入拼接后调用一次MD5_Update的结果:
写出注册机:
from hashlib import md5
name = b'pediy'
digest = md5(name + b'www.pediy.com').digest()
a2345 = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ'
serial_number = ''
for b in digest:
serial_number += a2345[b % 32]
print(f'Serial Number('{name}')={serial_number[0:4]}-{serial_number[4:8]}-{serial_number[8:12]}-{serial_number[12:16]}')
Findcrypt插件能帮助我们快速找到这些常量,不过这里还是着重讲手动分析的方法。
0x02. SHA
安全散列算法(Secure Hash Algorithm,SHA)包括SHA-1、SHA-256、SHA-384和SHA-512,分别产生160位、256位、384位和512位的散列值。
类似于MD5,SHA算法使用了一系列的常数:
还是用随书文件SHA1KeyGenMe.exe来分析。
还是先通过导入表定位关键代码:
发现sub_401000函数中出现了SHA1算法用到的常量:
还原下符号:
写出注册机:
from hashlib import sha1
name = b'pediy'
digest = sha1(name).digest()
aPEDIY = b'PEDIY Forum'
apediy = b'pediy.com'
key = bytearray(digest)
for i in range(11):
key[i] ^= aPEDIY[i]
for i in range(12,17):
key[i] ^= key[i - 12]
for i in range(17,20):
key[i] ^= apediy[i - 17]
serial_number = ''
for i in range(10):
serial_number += hex(key[i] ^ key[i + 10])[2:].zfill(2).upper()
print(serial_number)
0x03. RC4
RC4是一种比较简单的流密码,该算法虽然没有用到特征常量,但是特征也比较容易识别。
分析RC4 Sample.exe文件。
还是通过导入表找到关键代码:
sub_401000函数明显具有RC4密钥调度算法(KSA)的特征: