ASIS CTF Finals 2020 - babymd5

给出了一个可以连接的地址,试着连接得

 让我们输入一字符串,长度要为15,且经过sha384加密后,最后六位字符为'd709bb',可根据这些写一个小小的脚本来找出符合这些条件的字符串

如下:

import hashlib
import string,random

for i in range(100000000000000,199999999999999):
    temp=hashlib.sha384(str(i).encode()).hexdigest()
    if temp[-6:]=='d709bb':
        print(str(i))
        break

结果如下:

 

 

 

输入字符串后,又显示

 

输入B后,显示代码如下:

def babymd5(m, n, x_head, y_head, x, y):
    if x.startswith(x_head) and y.startswith(y_head):
        for _ in range(m):
            xhash = md5(x.encode('utf-8')).hexdigest()
            x = xhash
        for _ in range(n):
            yhash = md5(y.encode('utf-8')).hexdigest()
            y = yhash
        if xhash == yhash:
            return True
    return False

输入C后,显示代码如下:

| (m, n, x_head, y_head) = (202, 201, 'nPz', 'dead')

输入R后,提示让我们输入x

总结一下,流程大概就是已知一个函数babymd5和参数条件,即函数的参数前4个为(202,201,'nPz','dead'),让我们输入让函数babymd5返回结果为True的x和y

分析下函数babymd5的大概流程:

①判断x是否以x_head开头,y是否以y_head开头,若此条件不通过,则直接返回false

②将x进行md5加密,并对每次的结果进行循环加密,总加密次数为m次,最后加密结果为xhash

③将y进行md5加密,并对每次的结果进行循环加密,总加密次数为n次,最后加密结果为yhash

④若最后xhash与yhash恒相等,那么函数会返回True,否则返回False

这里难点就是如何找到这样的x和y,使得它们经过不同次数的md5加密后,值会相等,(我就被难倒了!参考了下wphttps://github.com/TalaatHarb/ctf-writeups/blob/main/asisctf2020/babymd5,写的很详细!)

函数中,很特殊的一个过程就是对结果反复进行循环加密,而y_head='dead','dead'又是一个合法的十六进制表示,且x加密循环的次数m>对y循环加密的次数n,故,我们可以把y看成x循环md5加密n次后的一个中间结果,即只要找到这样的一个x,对它进行循环解密n次后,它的结果temphashx恰以'dead'开头,而这个结果temphashx也就是我们需要的y。脚本如下:

import hashlib
import string,random

def babymd5(m, n, x_head, y_head, x, y):
    if x.startswith(x_head) and y.startswith(y_head):
        for _ in range(m):
            xhash = hashlib.md5(x.encode('utf-8')).hexdigest()
            x = xhash
        for _ in range(n):
            yhash = hashlib.md5(y.encode('utf-8')).hexdigest()
            y = yhash
        if xhash == yhash:
            return True
    return False


dict=string.ascii_letters+string.digits+string.punctuation
print(dict)
counter=1
found=False
length=32
x_head='nPz'
y_head='dead'
m=202
n=201
while not found:
    tmp=x_head+''.join(random.choice(dict) for _ in range(length))
    possible_x=tmp
    res=tmp
    for _ in range(m-n):
        res=hashlib.md5(res.encode()).hexdigest()
    if res.startswith('dead'):
        possible_x=res
        x=tmp
        y=res
        print("x:",x)
        print("y:",y)
        found=babymd5(202, 201, 'nPz', 'dead',x,y)
        break
    if(counter%10000==0):
        print("attemp:"+str(counter)+'')
    if(counter%100000==0):
        print("attemp:"+str(counter)+'')
    counter=counter+1

得到结果:

 

 输入对应的x和y后,得到flag!

 

posted @ 2020-12-15 20:24  jane_315  阅读(431)  评论(0编辑  收藏  举报