单向散列算法之——MD5算法

MD5算法(Message-Digest Algorithm 5)属于单向散列算法的一种。它的功能是将任意长度的消息在经过处理后输出一个128位的信息,从而实现加密,此加密不可逆,即无法通过密文反推出输入的信息。

1、算法原理

(1)数据填充

填充待加密的消息使其长度与448512同余(即消息长度=448mod512byte=56mod64)。因此,消息的长度被拓展至N*512+448(位),即N*64+56(字节)。换句话说,填充后的消息长度比512的倍数小64位的数。注意,即使消息长度本身已经满足上述需求,仍然需要填充。

填充方法是在数的后面附一个1,然后用0来进行填充,直到满足填充要求。至少填充1位,至多填充512位。

(2)添加长度

在第一步的结果后添加64位长度的数据填充之前的消息长度(消息长度指位的长度)。如果填充前的消息长度大于264则取其低64位。在添加完长度后,最终消息长度是512的整数倍((N+1*512位)。

(3)初始化变量

用四个变量(ABCD)计算信息摘要。ABCD分别为一个32位的寄存器,用十六进制数初始化为A=01234567hB=89abcdefhC=fedcba98hD=76543210h。由于Intel x86系列都使用小端序进行存储,所以在程序初始化时要注意书写顺序。

(4)数据处理

512位分组位单位处理消息,首先定义4个辅助函数,每个都是以332位双字作为输入,输出为一个32位双字。

F(X,Y,Z)=(X&Y)|((~X)&Z)

G(X,Y,Z)=(X&Z)|(Y&(~Z))

H(X,Y,Z)=X^Y^Z

I(X,Y,Z)=Y^(X|(~Z))

其中&是与操作,|是或操作,~是非操作,^是异或操作。

4轮变换是对进入主循环的512位消息分组的1632位字(即每512位消息,再划分位1632位消息进行处理)分别进行如下操作:使用临时变量a,b,c,d中的三个经F,G,H,I变换后的结果与第4个相加,再加上32位字和一个32位字的加法常数,并将所得值循环左移若干位,最后将所得结果加上a,b,c,d之一,并返回A,B,C,D,由此完成一次循环。

所用的加法常数T[i]定义,其中i164的值,T[i]等于4294967296232)乘以abs(sin(i))所得结果的整数部分,其中i用弧度来表示。用于通过正弦函数和幂函数来消除线性。

(5)输出

当所有的512位分组都运算完毕后,ABCD的级联(映射关系)将被输出为MD5散列的结果。

2、MD5在加密解密中的应用

MD5的特点:将任意长度的字符变换成一个128位的大整数,并且不可逆。

MD5代码的特点:在数据初始化时必然会用到4个常数(A,B,C,D)。对于变形的MD5算法,常见由三种情况:一是改变初始化所用到的4个常数;二是改变填充的方法;三是改变Hash变换的处理过程。

3、实例分析

本实例使用《加密解密》的MD5KeyGenMe为例进行讲解。首先使用PEiD进行扫描,判断编程语言,是否加壳等。并且使用插件分析得知该文件中含有MD5常数,猜测可能使用了MD5算法,如图3.1所示。

 

3.1 PEiD的插件扫描目标程序的加密算法

OllDbg(使用的是吾爱的OD)打开实例MD5KeyGenMe.exe,在命令行中输入bpx GetDlgTextA对所有此函数下断,接着按F9运行,在弹出的界面中输入Name:xingzherufeng Serial Number0123456789ABCDEF,单击“Check”按钮,程序中断在第一个下断处,如图3.2所示。

 

3.2 程序中断在第一个GetDlgTextA处(0040116F

F8单步调试(不步入),观察寄存器窗口各个寄存器的变化可以读出以上有效信息。注意,在00401190处的条件判断,判断输入的密钥是否长度为13,我们一开始输入的密钥长度不符,因此需要修改判断,由于上一条语句cmp eax,0x13得知相等时标志位ZF=1ZF=0表示结果不为0ZF=1表示结果为0),而此时JNZ是当结果不为0时跳转,也就是长度不想等时跳转,因此我们需要修改符号为ZF=1。下面几个跳转类似。如图3.3所示。

 

3.3 修改标志位避免跳转

接着F8单步到004011E0发现有一个Call跳转,F7进入看一看,发现4个常数,很明显这是在进行MD5初始化。但是根据这一点并不能完全确定这就是MD5,需要进一步判定。如图3.4所示。

 

3.4 MD54个常量

继续单步,遇到Call进入观察,会发现在00401400这个段中(跳转来自00401338)疑似存在MD5转换代码,进入后会发现如图3.5所示代码。

 

3.5 MD5转化代码

0040142B开始发现由与、或、非、左移以及常量T[i]00401441处出现的常量0x28955B88猜测为正弦函数表达式中的一个元素)等相关信息,并且下面具有循环代码,由此推断这里就是MD5转化的代码所在地,也因此确定本应用使用了MD5加密。

最后,继续单步发现一个循环,循环下面出现IscmpA函数,猜测进行密钥比较,如图3.6所示。

 

3.6

发现字符串PCJGUM9BBVPUKDMV”以及我们输入的序列号的比较,同时出现让我们猜测是否这就是正确的序列号,复制下来,验证一下(要注意的是,由于前面进行了第51015位置的“-”符号判断,猜测每4个字符用“-”隔开)。如图3.7所示。

 

3.7 序列号验证

到此,此程序的分析暂告一段落。

有一个遗憾就是并未找出加密后的MD5码所保存的位置,可能由于分析不够细心,有的关键寄存器的值可能漏看,如有想法可以给我留言,我会修改。初玩逆向,分析很片面,作为一个记录,用于以后查阅,欢迎指正错误,共同进步。

参考资料:《加密与解密》第三版

 

 posted on 2018-01-18 12:13  行者如风  阅读(4238)  评论(0编辑  收藏  举报