Md5扩展攻击的原理和应用

*本文原创作者:Guilty and Innocent,本文属FreeBuf原创奖励计划,未经许可禁止转载

做CTF题目的过程中遇到了md5扩展攻击,参考了几篇文章,感觉写的都有些小缺陷,再发一篇文章,理解md5扩展攻击首先需要了解md5的工作原理。

1)md5的工作原理

具体参考这两篇文章

http://blog.csdn.net/adidala/article/details/28677393,算法实现有误

https://www.rfc-editor.org/rfc/pdfrfc/rfc1321.txt.pdf,算法正确

md5的算法原理如下图所示

Md5的算法步骤是

1、填充

将数据进行填充,首先添加0×80,接着添加0×00使得 (数据字节数 + 8)%64 = 0

2、增加长度

将数据的长度放入8字节的数组中,把低字节放到前面,例如长度为1,8字节的数据长度表示为00 00 00 00 00 00 00 01,把这个长度值转化为低字节在前面变成了01 00 00 00 00 00 00 00,将这个数据加入到整体的数据中。

3、进行轮次变换

以64个字节为1组进行轮次变换,这一组中以4字节为1个单位分成16个数字。

首先准备A,B,C,D四个32位的字符,其中,    A = 0×67452301,B = 0xefcdab89

,C = 0x98badcfe,D = 0×10325476,   将ABCD作为种子,与16个数字进行一种复杂的运算(运算方式见后文),运算结果为A1 B1 C1 D1,以A1 B1 C1 D1为种子然后重复这个过程计算最后得到AnBnCnDn

4、输出hash值

将An进行类似于第二步的低字节顺序的排列An’,同理对Bn,Cn,Dn进行同样变换,An’,Bn’,Cn’,Dn’的简单拼接就是最后结果。

注:这里简单记录一下正确的复杂算法

文献1中的算法是错误的,正确的算法是

定义其中几个子算法

F = lambda x,y,z:((x&y)|((~x)&z))

G = lambda x,y,z:((x&z)|(y&(~z)))

H = lambda x,y,z:(x^y^z)

I = lambda x,y,z:(y^(x|(~z)))

def shift(a, count):

        return (((a << count) | (a >> (32 -count)))&0xffffffff)

常量表:

T_func = lambda i: int(4294967296*abs(math.sin(i))) & 0xffffffff

T = [T_func(i) for i in xrange(1, 65)]

T.insert(0 , 0)

复杂算法为

        INPUT_A = A

        INPUT_B = B

        INPUT_C = C

        INPUT_D = D

        M = [ (myord[i * 64 + j + 3] <<24) +  (myord[i * 64 + j + 2] << 16 )+ (myord[i * 64 + j + 1] << 8) + (myord[i * 64 + j + 0] )
             for j in xrange(0, 64, 4)]

        def shift(a, count):

            return (((a << count) | (a >> (32 -count)))&0xffffffff)

        #第一轮

        A = (B+ shift((A+F(B,C,D)+M[0]+T[1]) &0xffffffff,7) ) & 0xffffffff

        D = (A+shift((D+F(A,B,C)+M[1]+T[2]) &0xffffffff ,12) )& 0xffffffff

        C = (D+shift((C+F(D,A,B)+M[2]+T[3]) &0xffffffff,17) ) &0xffffffff

        B = (C+shift((B+F(C,D,A)+M[3]+T[4]) &0xffffffff,22) )&0xffffffff

        A = (B+shift((A+F(B,C,D)+M[4]+T[5]) &0xffffffff,7) )&0xffffffff

        D = (A+shift((D+F(A,B,C)+M[5]+T[6])&0xffffffff,12) )&0xffffffff

        C = (D+shift((C+F(D,A,B)+M[6]+T[7]) &0xffffffff,17) )&0xffffffff

        B = (C+shift((B+F(C,D,A)+M[7]+T[8]) &0xffffffff,22) )&0xffffffff 

        A = (B+shift((A+F(B,C,D)+M[8]+T[9])&0xffffffff,7) )&0xffffffff

        D = (A+shift((D+F(A,B,C)+M[9]+T[10])&0xffffffff,12) )&0xffffffff

        C = (D+shift((C+F(D,A,B)+M[10]+T[11])&0xffffffff,17) )&0xffffffff

        B = (C+shift((B+F(C,D,A)+M[11]+T[12])&0xffffffff,22) )&0xffffffff

        A = (B+shift((A+F(B,C,D)+M[12]+T[13])&0xffffffff,7) )&0xffffffff

        D = (A+shift((D+F(A,B,C)+M[13]+T[14])&0xffffffff,12) )&0xffffffff

        C = (D+shift((C+F(D,A,B)+M[14]+T[15])&0xffffffff,17) )&0xffffffff

        B = (C+shift((B+F(C,D,A)+M[15]+T[16])&0xffffffff,22) )&0xffffffff

        #第二轮

        A = (B+shift((A+G(B,C,D)+M[1]+T[17])&0xffffffff,5) )&0xffffffff

        D = (A+shift((D+G(A,B,C)+M[6]+T[18]) &0xffffffff,9) )&0xffffffff

        C = (D+shift((C+G(D,A,B)+M[11]+T[19])&0xffffffff,14) )&0xffffffff

        B = (C+shift((B+G(C,D,A)+M[0]+T[20])&0xffffffff,20) )&0xffffffff

        A = (B+shift((A+G(B,C,D)+M[5]+T[21])&0xffffffff,5) )&0xffffffff

        D = (A+shift((D+G(A,B,C)+M[10]+T[22])&0xffffffff,9) )&0xffffffff

        C = (D+shift((C+G(D,A,B)+M[15]+T[23])&0xffffffff,14) )&0xffffffff

        B = (C+shift((B+G(C,D,A)+M[4]+T[24])&0xffffffff,20) )&0xffffffff

        A = (B+shift((A+G(B,C,D)+M[9]+T[25])&0xffffffff,5) )&0xffffffff

        D = (A+shift((D+G(A,B,C)+M[14]+T[26])&0xffffffff,9) )&0xffffffff

        C = (D+shift((C+G(D,A,B)+M[3]+T[27])&0xffffffff,14) )&0xffffffff

        B = (C+shift((B+G(C,D,A)+M[8]+T[28])&0xffffffff,20) )&0xffffffff

        A = (B+shift((A+G(B,C,D)+M[13]+T[29])&0xffffffff,5) )&0xffffffff

        D = (A+shift((D+G(A,B,C)+M[2]+T[30])&0xffffffff,9) )&0xffffffff

        C = (D+shift((C+G(D,A,B)+M[7]+T[31])&0xffffffff,14) )&0xffffffff

        B = (C+shift((B+G(C,D,A)+M[12]+T[32])&0xffffffff,20))&0xffffffff

        #第三轮

        A = (B+shift((A+H(B,C,D)+M[5]+T[33])&0xffffffff,4) )&0xffffffff

        D = (A+shift((D+H(A,B,C)+M[8]+T[34])&0xffffffff,11) )&0xffffffff

        C = (D+shift((C+H(D,A,B)+M[11]+T[35])&0xffffffff,16) )&0xffffffff

        B = (C+shift((B+H(C,D,A)+M[14]+T[36])&0xffffffff,23) )&0xffffffff

        A = (B+shift((A+H(B,C,D)+M[1]+T[37])&0xffffffff,4) )&0xffffffff

        D = (A+shift((D+H(A,B,C)+M[4]+T[38])&0xffffffff,11) )&0xffffffff

        C = (D+shift((C+H(D,A,B)+M[7]+T[39])&0xffffffff,16) )&0xffffffff

        B = (C+shift((B+H(C,D,A)+M[10]+T[40])&0xffffffff,23) )&0xffffffff

        A = (B+shift((A+H(B,C,D)+M[13]+T[41])&0xffffffff,4) )&0xffffffff

        D = (A+shift((D+H(A,B,C)+M[0]+T[42])&0xffffffff,11) )&0xffffffff

        C = (D+shift((C+H(D,A,B)+M[3]+T[43])&0xffffffff,16) )&0xffffffff

        B = (C+shift((B+H(C,D,A)+M[6]+T[44])&0xffffffff,23) )&0xffffffff

        A = (B+shift((A+H(B,C,D)+M[9]+T[45])&0xffffffff,4) )&0xffffffff

        D = (A+shift((D+H(A,B,C)+M[12]+T[46])&0xffffffff,11) )&0xffffffff

        C = (D+shift((C+H(D,A,B)+M[15]+T[47])&0xffffffff,16) )&0xffffffff

        B = (C+shift((B+H(C,D,A)+M[2]+T[48])&0xffffffff,23))&0xffffffff

        #第四轮

        A = (B+shift((A+I(B,C,D)+M[0]+T[49])&0xffffffff,6) )&0xffffffff

        D = (A+shift((D+I(A,B,C)+M[7]+T[50])&0xffffffff,10) )&0xffffffff

        C = (D+shift((C+I(D,A,B)+M[14]+T[51])&0xffffffff,15) )&0xffffffff

        B = (C+shift((B+I(C,D,A)+M[5]+T[52])&0xffffffff,21) )&0xffffffff

        A = (B+shift((A+I(B,C,D)+M[12]+T[53])&0xffffffff,6) )&0xffffffff

        D = (A+shift((D+I(A,B,C)+M[3]+T[54])&0xffffffff,10) )&0xffffffff

        C = (D+shift((C+I(D,A,B)+M[10]+T[55])&0xffffffff,15) )&0xffffffff

        B = (C+shift((B+I(C,D,A)+M[1]+T[56])&0xffffffff,21) )&0xffffffff

        A = (B+shift((A+I(B,C,D)+M[8]+T[57])&0xffffffff,6) )&0xffffffff

        D = (A+shift((D+I(A,B,C)+M[15]+T[58])&0xffffffff,10) )&0xffffffff

        C = (D+shift((C+I(D,A,B)+M[6]+T[59])&0xffffffff,15) )&0xffffffff

        B = (C+shift((B+I(C,D,A)+M[13]+T[60])&0xffffffff,21) )&0xffffffff

        A = (B+shift((A+I(B,C,D)+M[4]+T[61])&0xffffffff,6) )&0xffffffff

        D = (A+shift((D+I(A,B,C)+M[11]+T[62])&0xffffffff,10) )&0xffffffff

        C = (D+shift((C+I(D,A,B)+M[2]+T[63])&0xffffffff,15) )&0xffffffff

        B = (C+shift((B+I(C,D,A)+M[9]+T[64])&0xffffffff,21))&0xffffffff

        A = (A + INPUT_A) & 0xffffffff

        B = (B + INPUT_B) & 0xffffffff

        C = (C + INPUT_C) & 0xffffffff

        D = (D + INPUT_D) & 0xffffffff

Md5算法实现python版本见第三节的中的my_md5>函数实现

理解的md5算法的原理,下面开始讲解md5扩展攻击

2)Md5攻击扩展攻击

首先可以参考这篇文章(http://www.freebuf.com/articles/web/69264.html),本文将对这篇文章进行补充说明。

从md5算法原理可以知道,每一轮次计算的ABCD将作为下一轮次计算的初始值,假设我们已知一个数字x的md5值为y,其中x为未知量,即y=md5(x),同时已知x的长度,那么我们就能进行md5扩展攻击,因为我们知道y为md5(x)计算完毕后的ABCD值的简单组合,通过md5的算法可知y = f(x + x的填充值),如果我们增加x1,计算y’=f( (x + x的填充值+x1 ) +  (x + x的填充值+x1 ) 的填充值 )则变得可能,应为y’可以使用y转化的AB

CD值同(x1 + (x + x的填充值+x1 ) 的填充值)再进行一轮次的计算既可以得出。

下图阐述了上述算法原理

其中标号1为原始数据x,标号2位原始数据x的填充长度,标号3表示新增加的数据,标号4为标号1,2,3的填充和长度。如果我们已知一个计算出来的hash值,同时知道明文的长度,则我们可以构造标号2的数据,标号3,计算未知数md5值的函数(如服务器端的程序),拿到我们构造的标号2和标号3的数据,会自动添加标号4的数据,计算完标号1和和标号2产生ABCD,接着会产生hash值,这时这个hash值就是可以预测。

攻击者可以计算出标号3和标号4,以ABCD作为输入进行计算本地产出的hash值和服务端计算出的hash值是一致的。

攻击者的视角如下图所示。

1、攻击者提供标号2,标号3,标号4的数据

2、服务端计算到标号2的位置刚好为ABCD这个已知数据

3、攻击者在本地根据标号3和标号4的数据和ABCD值计算hash值攻击成功

而服务端的视角是,攻击者提供了标号2和标号3的数据,服务端计算了标号4的数据,同时服务端产出ABCD,发现没有计算完成,接着运行md5算法,计算出的新的hash值和攻击者一致。

综上所述要想进行此类攻击需要知道两个条件

1、标号1数据的长度。

2、标号1数据的md5值。

最后总结一下攻击步骤

第一步:根据标号1的长度计算标号2的数据,提供标号3的数据,本地计算标号4 的数据,并计算加上标号3和标号4数据后的hash值。

第二步:发送计算出来的hash,和标号2,标号3的数据,攻击成功。

3)程序展示

展示python编写的MD5程序和md5扩展攻击的程序

#-*- coding=utf-8 -*-
import math

def my_md5_extend(salt_hash,  salt_length, added_message):
    #计算需要填充的数据
    added_data = [0x80];
    x = salt_length + 1;
    while (x + 8) % 64 != 0:
        x += 1;
        added_data.append(0x00);
    salt_length *= 8;
    salt_length = salt_length  % (2 ** 64);
    salt_length = hex(salt_length);
    salt_length = salt_length[2:len(salt_length)-1].rjust(16, ‘0‘);
    salt_length = [int(format(salt_length[i:i+2]), 16) for i in xrange(0, len(salt_length), 2)][::-1]
    #下面的数据用于加在payload后面
    added_data.extend(salt_length); #important
    #打印payload
    print ‘‘.join([‘%‘ + hex(item).replace(‘0x‘, ‘‘).rjust(2,‘0‘) for item in added_data])

    #增加新加的数据,然后使用已经md5的数据进行扩展计算,计算出来一个新的hash值
    myord = map(ord, added_message);
    myord.append(0x80);
    added_length = (x + 8 + len(added_message)) ;
    y = x + 8 + len(added_message) + 1;
    while (y + 8) % 64 != 0:
        y += 1;
        myord.append(0x00);

    added_length *= 8;
    added_length = added_length  % (2 ** 64);
    added_length = hex(added_length);
    added_length = added_length[2:len(added_length)-1].rjust(16, ‘0‘);
    added_length = [int(format(added_length[i:i+2]), 16) for i in xrange(0, len(added_length), 2)][::-1]
    myord.extend(added_length);

    #使用已经计算出来的hash
    myA, myB, myC, myD = ( int(salt_hash[i +6: i + 8] +salt_hash[i + 4: i + 6] +salt_hash[i + 2:i + 4] +salt_hash[i + 0 : i + 2], 16)  for i in xrange(0, len(salt_hash), 8));

    A = myA;
    B = myB;
    C = myC;
    D = myD;

    F = lambda x,y,z:((x&y)|((~x)&z))
    G = lambda x,y,z:((x&z)|(y&(~z)))
    H = lambda x,y,z:(x^y^z)
    I = lambda x,y,z:(y^(x|(~z)))  

    T_func = lambda i: int(4294967296*abs(math.sin(i))) & 0xffffffff

    T = [T_func(i) for i in xrange(1, 65)]
    T.insert(0 , 0)
    #进行hash计算
    for i in xrange(0, len(myord) / 64):
        INPUT_A = A
        INPUT_B = B
        INPUT_C = C
        INPUT_D = D

        M = [ (myord[i * 64 + j + 3] <<24) +  (myord[i * 64 + j + 2] << 16 )+ (myord[i * 64 + j + 1] << 8) + (myord[i * 64 + j + 0] )             for j in xrange(0, 64, 4)]

        def shift(a, count):
            return (((a << count) | (a >> (32 -count)))&0xffffffff)

        #第一轮
        A = (B+ shift((A+F(B,C,D)+M[0]+T[1]) &0xffffffff,7) ) & 0xffffffff
        D = (A+shift((D+F(A,B,C)+M[1]+T[2]) &0xffffffff ,12) )& 0xffffffff
        C = (D+shift((C+F(D,A,B)+M[2]+T[3]) &0xffffffff,17) ) &0xffffffff

        B = (C+shift((B+F(C,D,A)+M[3]+T[4]) &0xffffffff,22) )&0xffffffff

        A = (B+shift((A+F(B,C,D)+M[4]+T[5]) &0xffffffff,7) )&0xffffffff

        D = (A+shift((D+F(A,B,C)+M[5]+T[6])&0xffffffff,12) )&0xffffffff

        C = (D+shift((C+F(D,A,B)+M[6]+T[7]) &0xffffffff,17) )&0xffffffff

        B = (C+shift((B+F(C,D,A)+M[7]+T[8]) &0xffffffff,22) )&0xffffffff
        A = (B+shift((A+F(B,C,D)+M[8]+T[9])&0xffffffff,7) )&0xffffffff

        D = (A+shift((D+F(A,B,C)+M[9]+T[10])&0xffffffff,12) )&0xffffffff
        C = (D+shift((C+F(D,A,B)+M[10]+T[11])&0xffffffff,17) )&0xffffffff

        B = (C+shift((B+F(C,D,A)+M[11]+T[12])&0xffffffff,22) )&0xffffffff
        A = (B+shift((A+F(B,C,D)+M[12]+T[13])&0xffffffff,7) )&0xffffffff

        D = (A+shift((D+F(A,B,C)+M[13]+T[14])&0xffffffff,12) )&0xffffffff

        C = (D+shift((C+F(D,A,B)+M[14]+T[15])&0xffffffff,17) )&0xffffffff

        B = (C+shift((B+F(C,D,A)+M[15]+T[16])&0xffffffff,22) )&0xffffffff

        #第二轮
        A = (B+shift((A+G(B,C,D)+M[1]+T[17])&0xffffffff,5) )&0xffffffff

        D = (A+shift((D+G(A,B,C)+M[6]+T[18]) &0xffffffff,9) )&0xffffffff

        C = (D+shift((C+G(D,A,B)+M[11]+T[19])&0xffffffff,14) )&0xffffffff

        B = (C+shift((B+G(C,D,A)+M[0]+T[20])&0xffffffff,20) )&0xffffffff

        A = (B+shift((A+G(B,C,D)+M[5]+T[21])&0xffffffff,5) )&0xffffffff

        D = (A+shift((D+G(A,B,C)+M[10]+T[22])&0xffffffff,9) )&0xffffffff

        C = (D+shift((C+G(D,A,B)+M[15]+T[23])&0xffffffff,14) )&0xffffffff

        B = (C+shift((B+G(C,D,A)+M[4]+T[24])&0xffffffff,20) )&0xffffffff

        A = (B+shift((A+G(B,C,D)+M[9]+T[25])&0xffffffff,5) )&0xffffffff

        D = (A+shift((D+G(A,B,C)+M[14]+T[26])&0xffffffff,9) )&0xffffffff

        C = (D+shift((C+G(D,A,B)+M[3]+T[27])&0xffffffff,14) )&0xffffffff

        B = (C+shift((B+G(C,D,A)+M[8]+T[28])&0xffffffff,20) )&0xffffffff

        A = (B+shift((A+G(B,C,D)+M[13]+T[29])&0xffffffff,5) )&0xffffffff

        D = (A+shift((D+G(A,B,C)+M[2]+T[30])&0xffffffff,9) )&0xffffffff

        C = (D+shift((C+G(D,A,B)+M[7]+T[31])&0xffffffff,14) )&0xffffffff

        B = (C+shift((B+G(C,D,A)+M[12]+T[32])&0xffffffff,20))&0xffffffff

        #第三轮
        A = (B+shift((A+H(B,C,D)+M[5]+T[33])&0xffffffff,4) )&0xffffffff

        D = (A+shift((D+H(A,B,C)+M[8]+T[34])&0xffffffff,11) )&0xffffffff

        C = (D+shift((C+H(D,A,B)+M[11]+T[35])&0xffffffff,16) )&0xffffffff

        B = (C+shift((B+H(C,D,A)+M[14]+T[36])&0xffffffff,23) )&0xffffffff

        A = (B+shift((A+H(B,C,D)+M[1]+T[37])&0xffffffff,4) )&0xffffffff

        D = (A+shift((D+H(A,B,C)+M[4]+T[38])&0xffffffff,11) )&0xffffffff

        C = (D+shift((C+H(D,A,B)+M[7]+T[39])&0xffffffff,16) )&0xffffffff

        B = (C+shift((B+H(C,D,A)+M[10]+T[40])&0xffffffff,23) )&0xffffffff

        A = (B+shift((A+H(B,C,D)+M[13]+T[41])&0xffffffff,4) )&0xffffffff

        D = (A+shift((D+H(A,B,C)+M[0]+T[42])&0xffffffff,11) )&0xffffffff

        C = (D+shift((C+H(D,A,B)+M[3]+T[43])&0xffffffff,16) )&0xffffffff

        B = (C+shift((B+H(C,D,A)+M[6]+T[44])&0xffffffff,23) )&0xffffffff

        A = (B+shift((A+H(B,C,D)+M[9]+T[45])&0xffffffff,4) )&0xffffffff

        D = (A+shift((D+H(A,B,C)+M[12]+T[46])&0xffffffff,11) )&0xffffffff

        C = (D+shift((C+H(D,A,B)+M[15]+T[47])&0xffffffff,16) )&0xffffffff

        B = (C+shift((B+H(C,D,A)+M[2]+T[48])&0xffffffff,23))&0xffffffff

        #第四轮

        A = (B+shift((A+I(B,C,D)+M[0]+T[49])&0xffffffff,6) )&0xffffffff

        D = (A+shift((D+I(A,B,C)+M[7]+T[50])&0xffffffff,10) )&0xffffffff

        C = (D+shift((C+I(D,A,B)+M[14]+T[51])&0xffffffff,15) )&0xffffffff

        B = (C+shift((B+I(C,D,A)+M[5]+T[52])&0xffffffff,21) )&0xffffffff

        A = (B+shift((A+I(B,C,D)+M[12]+T[53])&0xffffffff,6) )&0xffffffff

        D = (A+shift((D+I(A,B,C)+M[3]+T[54])&0xffffffff,10) )&0xffffffff

        C = (D+shift((C+I(D,A,B)+M[10]+T[55])&0xffffffff,15) )&0xffffffff

        B = (C+shift((B+I(C,D,A)+M[1]+T[56])&0xffffffff,21) )&0xffffffff

        A = (B+shift((A+I(B,C,D)+M[8]+T[57])&0xffffffff,6) )&0xffffffff

        D = (A+shift((D+I(A,B,C)+M[15]+T[58])&0xffffffff,10) )&0xffffffff

        C = (D+shift((C+I(D,A,B)+M[6]+T[59])&0xffffffff,15) )&0xffffffff

        B = (C+shift((B+I(C,D,A)+M[13]+T[60])&0xffffffff,21) )&0xffffffff

        A = (B+shift((A+I(B,C,D)+M[4]+T[61])&0xffffffff,6) )&0xffffffff

        D = (A+shift((D+I(A,B,C)+M[11]+T[62])&0xffffffff,10) )&0xffffffff

        C = (D+shift((C+I(D,A,B)+M[2]+T[63])&0xffffffff,15) )&0xffffffff

        B = (C+shift((B+I(C,D,A)+M[9]+T[64])&0xffffffff,21))&0xffffffff
        A = (A + INPUT_A) & 0xffffffff
        B = (B + INPUT_B) & 0xffffffff
        C = (C + INPUT_C) & 0xffffffff
        D = (D + INPUT_D) & 0xffffffff

    def show_result(A, B, C, D):
        result = "";
        mya = [hex(A)[2:len(hex(A)[2:]) if hex(A).find(‘L‘) == -1 else -1].rjust(8, ‘0‘)[k:k+2] for k in xrange(0, 8, 2)][::-1]
        myb = [hex(B)[2:len(hex(B)[2:]) if hex(B).find(‘L‘) == -1 else -1].rjust(8, ‘0‘)[k:k+2] for k in xrange(0, 8, 2)][::-1]
        myc = [hex(C)[2:len(hex(C)[2:]) if hex(C).find(‘L‘) == -1 else -1].rjust(8, ‘0‘)[k:k+2] for k in xrange(0, 8, 2)][::-1]
        myd = [hex(D)[2:len(hex(D)[2:]) if hex(D).find(‘L‘) == -1 else -1].rjust(8, ‘0‘)[k:k+2] for k in xrange(0, 8, 2)][::-1]
        return ‘‘.join(mya + myb + myc + myd)
    return show_result(A, B, C, D);

print my_md5_extend(‘571580b26c65f306376d4f64e53cb5c7‘, 15 + len(‘adminadmin‘), ‘nb‘); 

def my_md5(mystring):
    #第一步填充
    #mystring = ‘ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz‘
    myord =map(ord, mystring);#转化成为16进制的array
    myord_length = len(myord) * 8;
    myord.append(0x80);

    while (len(myord) * 8 + 64 )% 512 != 0:
        myord.append(0x00);

    #第二步增加长度
    myord_length = myord_length % (2 ** 64);

    myord_length = hex(myord_length);

    myord_length = myord_length[2:len(myord_length)-1].rjust(16, ‘0‘);

    myord_length = [int(format(myord_length[i:i+2]), 16) for i in xrange(0, len(myord_length), 2)][::-1]

    myord.extend(myord_length)

    #对每一个512位做处理
    A = 0x67452301
    B = 0xefcdab89
    C = 0x98badcfe
    D = 0x10325476

    F = lambda x,y,z:((x&y)|((~x)&z))
    G = lambda x,y,z:((x&z)|(y&(~z)))
    H = lambda x,y,z:(x^y^z)
    I = lambda x,y,z:(y^(x|(~z)))  

    T_func = lambda i: int(4294967296*abs(math.sin(i))) & 0xffffffff

    T = [T_func(i) for i in xrange(1, 65)]
    T.insert(0 , 0)#错误的位置

    for i in xrange(0, len(myord) / 64):
        INPUT_A = A
        INPUT_B = B
        INPUT_C = C
        INPUT_D = D

        M = [ (myord[i * 64 + j + 3] <<24) +  (myord[i * 64 + j + 2] << 16 )+ (myord[i * 64 + j + 1] << 8) + (myord[i * 64 + j + 0] )             for j in xrange(0, 64, 4)]

        def shift(a, count):
            return (((a << count) | (a >> (32 -count)))&0xffffffff)

        #第一轮
        A = (B+ shift((A+F(B,C,D)+M[0]+T[1]) &0xffffffff,7) ) & 0xffffffff
        D = (A+shift((D+F(A,B,C)+M[1]+T[2]) &0xffffffff ,12) )& 0xffffffff
        C = (D+shift((C+F(D,A,B)+M[2]+T[3]) &0xffffffff,17) ) &0xffffffff

        B = (C+shift((B+F(C,D,A)+M[3]+T[4]) &0xffffffff,22) )&0xffffffff

        A = (B+shift((A+F(B,C,D)+M[4]+T[5]) &0xffffffff,7) )&0xffffffff

        D = (A+shift((D+F(A,B,C)+M[5]+T[6])&0xffffffff,12) )&0xffffffff

        C = (D+shift((C+F(D,A,B)+M[6]+T[7]) &0xffffffff,17) )&0xffffffff

        B = (C+shift((B+F(C,D,A)+M[7]+T[8]) &0xffffffff,22) )&0xffffffff
        A = (B+shift((A+F(B,C,D)+M[8]+T[9])&0xffffffff,7) )&0xffffffff

        D = (A+shift((D+F(A,B,C)+M[9]+T[10])&0xffffffff,12) )&0xffffffff
        C = (D+shift((C+F(D,A,B)+M[10]+T[11])&0xffffffff,17) )&0xffffffff

        B = (C+shift((B+F(C,D,A)+M[11]+T[12])&0xffffffff,22) )&0xffffffff
        A = (B+shift((A+F(B,C,D)+M[12]+T[13])&0xffffffff,7) )&0xffffffff

        D = (A+shift((D+F(A,B,C)+M[13]+T[14])&0xffffffff,12) )&0xffffffff

        C = (D+shift((C+F(D,A,B)+M[14]+T[15])&0xffffffff,17) )&0xffffffff

        B = (C+shift((B+F(C,D,A)+M[15]+T[16])&0xffffffff,22) )&0xffffffff

        #第二轮
        A = (B+shift((A+G(B,C,D)+M[1]+T[17])&0xffffffff,5) )&0xffffffff

        D = (A+shift((D+G(A,B,C)+M[6]+T[18]) &0xffffffff,9) )&0xffffffff

        C = (D+shift((C+G(D,A,B)+M[11]+T[19])&0xffffffff,14) )&0xffffffff

        B = (C+shift((B+G(C,D,A)+M[0]+T[20])&0xffffffff,20) )&0xffffffff

        A = (B+shift((A+G(B,C,D)+M[5]+T[21])&0xffffffff,5) )&0xffffffff

        D = (A+shift((D+G(A,B,C)+M[10]+T[22])&0xffffffff,9) )&0xffffffff

        C = (D+shift((C+G(D,A,B)+M[15]+T[23])&0xffffffff,14) )&0xffffffff

        B = (C+shift((B+G(C,D,A)+M[4]+T[24])&0xffffffff,20) )&0xffffffff

        A = (B+shift((A+G(B,C,D)+M[9]+T[25])&0xffffffff,5) )&0xffffffff

        D = (A+shift((D+G(A,B,C)+M[14]+T[26])&0xffffffff,9) )&0xffffffff

        C = (D+shift((C+G(D,A,B)+M[3]+T[27])&0xffffffff,14) )&0xffffffff

        B = (C+shift((B+G(C,D,A)+M[8]+T[28])&0xffffffff,20) )&0xffffffff

        A = (B+shift((A+G(B,C,D)+M[13]+T[29])&0xffffffff,5) )&0xffffffff

        D = (A+shift((D+G(A,B,C)+M[2]+T[30])&0xffffffff,9) )&0xffffffff

        C = (D+shift((C+G(D,A,B)+M[7]+T[31])&0xffffffff,14) )&0xffffffff

        B = (C+shift((B+G(C,D,A)+M[12]+T[32])&0xffffffff,20))&0xffffffff

        #第三轮
        A = (B+shift((A+H(B,C,D)+M[5]+T[33])&0xffffffff,4) )&0xffffffff

        D = (A+shift((D+H(A,B,C)+M[8]+T[34])&0xffffffff,11) )&0xffffffff

        C = (D+shift((C+H(D,A,B)+M[11]+T[35])&0xffffffff,16) )&0xffffffff

        B = (C+shift((B+H(C,D,A)+M[14]+T[36])&0xffffffff,23) )&0xffffffff

        A = (B+shift((A+H(B,C,D)+M[1]+T[37])&0xffffffff,4) )&0xffffffff

        D = (A+shift((D+H(A,B,C)+M[4]+T[38])&0xffffffff,11) )&0xffffffff

        C = (D+shift((C+H(D,A,B)+M[7]+T[39])&0xffffffff,16) )&0xffffffff

        B = (C+shift((B+H(C,D,A)+M[10]+T[40])&0xffffffff,23) )&0xffffffff

        A = (B+shift((A+H(B,C,D)+M[13]+T[41])&0xffffffff,4) )&0xffffffff

        D = (A+shift((D+H(A,B,C)+M[0]+T[42])&0xffffffff,11) )&0xffffffff

        C = (D+shift((C+H(D,A,B)+M[3]+T[43])&0xffffffff,16) )&0xffffffff

        B = (C+shift((B+H(C,D,A)+M[6]+T[44])&0xffffffff,23) )&0xffffffff

        A = (B+shift((A+H(B,C,D)+M[9]+T[45])&0xffffffff,4) )&0xffffffff

        D = (A+shift((D+H(A,B,C)+M[12]+T[46])&0xffffffff,11) )&0xffffffff

        C = (D+shift((C+H(D,A,B)+M[15]+T[47])&0xffffffff,16) )&0xffffffff

        B = (C+shift((B+H(C,D,A)+M[2]+T[48])&0xffffffff,23))&0xffffffff

        #第四轮

        A = (B+shift((A+I(B,C,D)+M[0]+T[49])&0xffffffff,6) )&0xffffffff
        D = (A+shift((D+I(A,B,C)+M[7]+T[50])&0xffffffff,10) )&0xffffffff
        C = (D+shift((C+I(D,A,B)+M[14]+T[51])&0xffffffff,15) )&0xffffffff
        B = (C+shift((B+I(C,D,A)+M[5]+T[52])&0xffffffff,21) )&0xffffffff
        A = (B+shift((A+I(B,C,D)+M[12]+T[53])&0xffffffff,6) )&0xffffffff
        D = (A+shift((D+I(A,B,C)+M[3]+T[54])&0xffffffff,10) )&0xffffffff
        C = (D+shift((C+I(D,A,B)+M[10]+T[55])&0xffffffff,15) )&0xffffffff
        B = (C+shift((B+I(C,D,A)+M[1]+T[56])&0xffffffff,21) )&0xffffffff
        A = (B+shift((A+I(B,C,D)+M[8]+T[57])&0xffffffff,6) )&0xffffffff
        D = (A+shift((D+I(A,B,C)+M[15]+T[58])&0xffffffff,10) )&0xffffffff
        C = (D+shift((C+I(D,A,B)+M[6]+T[59])&0xffffffff,15) )&0xffffffff
        B = (C+shift((B+I(C,D,A)+M[13]+T[60])&0xffffffff,21) )&0xffffffff
        A = (B+shift((A+I(B,C,D)+M[4]+T[61])&0xffffffff,6) )&0xffffffff
        D = (A+shift((D+I(A,B,C)+M[11]+T[62])&0xffffffff,10) )&0xffffffff
        C = (D+shift((C+I(D,A,B)+M[2]+T[63])&0xffffffff,15) )&0xffffffff
        B = (C+shift((B+I(C,D,A)+M[9]+T[64])&0xffffffff,21))&0xffffffff
        A = (A + INPUT_A) & 0xffffffff
        B = (B + INPUT_B) & 0xffffffff
        C = (C + INPUT_C) & 0xffffffff
        D = (D + INPUT_D) & 0xffffffff

    def show_result(A, B, C, D):
        result = "";
        mya = [hex(A)[2:len(hex(A)[2:]) if hex(A).find(‘L‘) == -1 else -1].rjust(8, ‘0‘)[k:k+2] for k in xrange(0, 8, 2)][::-1]
        myb = [hex(B)[2:len(hex(B)[2:]) if hex(B).find(‘L‘) == -1 else -1].rjust(8, ‘0‘)[k:k+2] for k in xrange(0, 8, 2)][::-1]
        myc = [hex(C)[2:len(hex(C)[2:]) if hex(C).find(‘L‘) == -1 else -1].rjust(8, ‘0‘)[k:k+2] for k in xrange(0, 8, 2)][::-1]
        myd = [hex(D)[2:len(hex(D)[2:]) if hex(D).find(‘L‘) == -1 else -1].rjust(8, ‘0‘)[k:k+2] for k in xrange(0, 8, 2)][::-1]
        return ‘‘.join(mya + myb + myc + myd)
    return show_result(A, B, C, D);

4)结语

在做ctf题目的时候加强对原理的理解,和动手实践,文字总结的方式可以帮助记忆。

参考文献:

【1】http://blog.csdn.net/adidala/article/details/28677393

【2】https://www.rfc-editor.org/rfc/pdfrfc/rfc1321.txt.pdf

【3】http://www.freebuf.com/articles/web/69264.html

时间: 2024-10-11 12:24:00

Md5扩展攻击的原理和应用的相关文章

哈希长度扩展攻击的简介以及HashPump安装使用方法

哈希长度扩展攻击(hash length extension attacks)是指针对某些允许包含额外信息的加密散列函数的攻击手段.该攻击适用于在消息与密钥的长度已知的情形下,所有采取了 H(密钥 ∥ 消息) 此类构造的散列函数.MD5和SHA-1等基于Merkle–Damgård构造的算法均对此类攻击显示出脆弱性. 如果一个应用程序是这样操作的: 准备了一个密文和一些数据构造成一个字符串里,并且使用了MD5之类的哈希函数生成了一个哈希值(也就是所谓的signature/签名) 让攻击者可以提交

实验吧——让我进去(hash长度扩展攻击)

题目地址:http://ctf5.shiyanbar.com/web/kzhan.php 在页面源码没发现什么,于是用burp进行抓包重放 看到有setcookie,于是重新刷新页面拦截数据包(这次才会带上cookie) 这个source=0 一看就很可疑,改成source=1,就得到了源码 1 <?php 2 $flag = "XXXXXXXXXXXXXXXXXXXXXXX"; 3 $secret = "XXXXXXXXXXXXXXX"; // This s

hash长度扩展攻击

这里面就放一张百度百科的解释吧,emmm 反正我是看不懂还是做一下题来巩固一下吧 CTF中的hash长度攻击 进入网页你会发现页面显示 ?? 我这里没有看到什么可以利用的,抓了一下包也没有什么有可以利用的东西,扫一下目录看看,这里面我用的是一个专门扫描敏感文件的工具.有兴趣的同学可以去看一下. 工具在这里 使用方法:python3 1.py url 16 32 OK通过扫描我们发现一个index.php~的文件,下载下来其实就是一个linux意外退出的一个交换文件,emmmmm. ? 在linu

hash哈希长度扩展攻击解析(记录一下,保证不忘)

起因 这是 ISCC 上的一道题目,抄 PCTF 的,并且给予了简化.在利用简化过的方式通过后,突然想起利用哈希长度扩展攻击来进行通关.哈希长度扩展攻击是一个很有意思的东西,利用了 md5.sha1 等加密算法的缺陷,可以在不知道原始密钥的情况下来进行计算出一个对应的 hash 值. 这里是 ISCC 中题目中的 admin.php 的算法: $auth = false; if (isset($_COOKIE["auth"])) { $auth = unserialize($_COOK

网站被CC攻击的原理与解决方法

作为站长或者公司的网站的网管,什么最可怕?显然是网站受到的DDoS攻击.大家都有这样的经历,就是在访问某一公司网站或者论坛时,如果这个网站或者论坛流量比较大,访问的人比较多,打开页面的速度会比较慢,对不?!一般来说,访问的人越多,网站或论坛的页面越多,数据库就越大,被访问的频率也越高,占用的系统资源也就相当可观. CC攻击是DDoS(分布式拒绝服务)的一种,相比其它的DDoS攻击CC似乎更有技术含量一些.这种攻击你见不到虚假IP,见不到特别大的异常流量,但造成服务器无法进行正常连接,一条ADSL

从零学习哈希长度扩展攻击

哈希长度扩展攻击,利用了md5.sha1等加密算法的缺陷,可以在不知道原始密钥的情况下来进行计算出一个对应的hash值. 引言 最开始出现好像是在PCTF2014上最近做题突然看见了先来看下代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <?php $auth = false; $role = "guest"; $salt = if (isset($_COOKIE["role"

分布式拒绝服务攻击(DDoS)原理及防范

DDoS攻击概念 DoS的攻击方式有很多种,最基本的DoS攻击就是利用合理的服务请求来占用过多的服务资源,从而使合法用户无法得到服务的响应. DDoS攻击手段是在传统的DoS攻击基础之上产生的一类攻击方式.单一的DoS攻击一般是采用一对一方式的,当攻击目标CPU速度低.内存小或者网络带宽小等等各项性能指标不高它的效果是明显的.随着计算机与网络技术的发展,计算机的处理能力迅速增长,内存大大增加,同时也出现了千兆级别的网络,这使得DoS攻击的困难程度加大了 – 目标对恶意攻击包的”消化能力”加强了不

中间人攻击的原理与实现

  看风云无忌一时有些迟疑.   那男子冷笑道:"你是新飞升的吧.妖魔吃人,人吃妖魔,这个道理你迟早会明白.莽莽大地,除却那植物之外,所有行走之物,均强于人类.你若是想不通,以后就和一些低等妖兽一般,去吃那树上的野果吧." --飞升之后 · 荧惑 风云无忌 下面是整篇文章的鸟瞰图:(读者应该了解局域网ARP协议) 上图便是局域网中的中间人攻击的大概思想,下面给出具体的实现方法: (备注:右键另存为 大图较清晰) 实现"中间人"的情景,有两个关键点: · ARP欺骗:

md5 32位 加密原理 Java实现md5加密

md5 32位 加密原理 简单概括起来,MD5 算法的过程分为四步:处理原文,设置初始值,循环加工,拼接结果. 第一步:处理原文 首先,我们计算出原文长度(bit)对 512 求余的结果,如果不等于 448,就需要填充原文使得原文对 512 求余的结果等于 448.填充的方法是第一位填充 1,其余位填充 0.填充完后,信息的长度就是 512*N+448. 之后,用剩余的位置(512-448=64 位)记录原文的真正长度,把长度的二进制值补在最后.这样处理后的信息长度就是 512*(N+1). 第