Crypto-hashcoll

先贴上源码

#!/usr/bin/env python2

FLAG = '*********************************'

h0 = 45740974929179720441799381904411404011270459520712533273451053262137196814399

# 2**168 + 355
g = 374144419156711147060143317175368453031918731002211L

def shitty_hash(msg):
    h = h0 
    msg = map(ord, msg)
    for i in msg:
        h = (h + i)*g 
        # This line is just to screw you up :))
        h = h & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
    
    return h - 0xe6168647f636


if __name__ == '__main__':
    try: 
        introduction = """
        .--.     .------------------------.
        | __\    |                        |
        | > <   <  Homies, Hash collision |
        |  \|    |                        |
        |/_//    `------------------------'
        |  / 
        `-'
        I never want to create challenges that people can grab random scripts to solve it. Nah
        """

        print introduction

        m1 = raw_input('m1 : ')
        m2 = raw_input('m2 : ')

        assert m1 != m2 

        #print "m1 = {!r}".format(m1)
        #print "m2 = {!r}".format(m2)

        hash1 = shitty_hash(m1)
        hash2 = shitty_hash(m2) 

        if hash1 == hash2:
            print "\nThe flag is simple, it is 'the flag' :)) "
            print FLAG
        else:
            print 'Wrong.'

    except:
        print "Take your time to think of the inputs."
        pass

先看main函数,发现就是将传进来的两个参数经过shitty_hash这个函数运行后,返回值如果相等就获取flag。所以此题的重点就只有一个,就是shitty_hash函数。

def shitty_hash(msg):
    h = h0 
    msg = map(ord, msg)
    for i in msg:
        h = (h + i)*g 
        # This line is just to screw you up :))
        h = h & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
    
    return h - 0xe6168647f636h

化简一下此函数。

此函数的意思就是将字符串转化成ascii 然后累加、累乘。

化简之后为下面式子

hash = (h0*g^n+x1*g^n+x2*g^(n-1)+x3*g^(n-2)+......+xn*g)%(2^256)

  

若想让输入的两个字符串经过处理后相等则需要满足

(h0*g^n+x1*g^n+x2*g^(n-1)+x3*g^(n-2)+......+xn*g)%(2^256)=(h0*g^n+y1*g^n+y2*g^(n-1)+y3*g^(n-2)+......+yn*g)%(2^256)
       (x1*g^n+x2*g^(n-1)+x3*g^(n-2)+......+xn*g)%(2^256)=(y1*g^n+y2*g^(n-1)+y3*g^(n-2)+......+yn*g)%(2^256)
                                                        0=(x1*g^n+x2*g^(n-1)+x3*g^(n-2)+......+xn*g)%(2^256)
                                                        0=((x1-y1)*g^n+(x2-y2)*g^(n-1)+(x3-y3)*g^(n-2)+......+(xn-yn)*g)%(2^256)

 设zi = xi-yi,得到

(z1*g^n+z2*g^(n-1)+z3*g^(n-2)+......+zn*g)%(2^256)=0

 也就是说此问题可已转化为在2^256有限域上寻找一组解的情况。也就是最短向量问题。

直接用LLL算法。

from sage.all import *

mod = 2**256
h0 = 45740974929179720441799381904411404011270459520712533273451053262137196814399

g = 2**168 + 355

K = 2**256

base = map(ord, "S4tan"*9)
base  = (list(base))
N = len(base)

m = matrix(ZZ, N + 1, N + 2)
for i in range(N):
    ge = pow(g, N-i, mod)
    m[i,0] = ge
    m[i,1+i] = 1
m[N,0] = mod
for i in range(N+1):
    m[i,0] *= K

ml = m.LLL()

ttt = ml.rows()[0]
print("result:", ttt)
if ttt[0] != 0:
    print("Error")
    exit()
if not base:
    base = [BASE] * N
msg = []
for i in range(N):
    msg.append(base[i] + ttt[1+i])
    if not (0 <= msg[-1] <= 255):
        print("Need more bytes!")
        quit()


def shitty_hash(msg):
    h = h0
    for i in msg:
        h = (h + i)*g 
        # This line is just to screw you up :))
        h = h & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff#mod2**256
        #print h

    return h - 0xe6168647f636

def pure_hash(msg):
    h = 0
    for i in msg:
        h = (h + i)*g 
        # This line is just to screw you up :))
        h = h & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff#mod2**256
    return h

print(base)
print("m1:", "".join(map(chr, base)))
print(hex(shitty_hash(base)), shitty_hash(base))
print(msg)
diff = [i-j for i,j in zip(msg,base)]
print(diff)
print(hex(pure_hash(diff)))
print("m2:", "".join(map(chr, msg)))
print(hex(shitty_hash(msg)), shitty_hash(msg))

利用pwntools发送即可。

 

posted @ 2020-03-30 15:15  S4tan  阅读(500)  评论(0)    收藏  举报