国赛某逆向wp

国赛某逆向wp

拿到后发现是64位elf文件,拖入ida分析

123

在读入32位输入后,比较了前6位出入是否为CISCN{,不是则退出,然后用_将输入发给分隔成三部分,分别传入三个函数分析

点进去第一个,
123

发现整个加密部分与md5十分相像,前两个sub是md5四个幻数的初始化

123

123
后面紧跟着的是md5的update函数
123

最后md5final保存的是最后的散列结果,可以看到v10是md5结构体,v11里存着md5后的结果,后面一个sub不是很清楚作用是什么,于是跟进去调试了下,初步猜测是ToHex的

123
输入假码后,一步步跟
123
可以发现经过sub401285这个函数之后,md5final里的值被转成了hex,于是就可以判断下面部分是对md5值的加密
123
很容易写出逆向脚本
123
直接去somd5查询下
123
可以得出第一段的输入,再看第二段加密
123
可以发现和第一段相比多了个异或加密,依旧可以很轻松的得出解密脚本,有一部分要注意的是必须在解密前进行hex_decode操作,否则会出现超出ascii的情况
123
得到第二段输入的md5值,用hashlib或者直接去查询即可获得
123
总结下,目前所有的输入为CISCN{goog_dbfu_xxxxxxxxxxxxxxx},下面继续去看第三段
123
发现了是类似上面的操作,但是怎么同样的脚本跑出散列值之后发现无法解密得出,只要先去看看下面的操作,下面在判断结束后似乎生产了个文件,不管多少先让他生产文件看看再说,把上面一个cmp后的跳转nop掉就可以走到对文件操作的那几个Api
123
一直单步都结束之后就可以看到一个名为flag的二进制文件,去看下
123
发现文件开头有很多重复的部分,一般来说这部分应该是00,这里变成了58和4D,回头看下对文件的操作
123
对byte_6020E0这个数组进行单数位和双数位分别异或之后得到了加密后的文件,现在我们很容易得到异或的那个数值,直接把58和4D异或回去就行了,可以发现异或的那两个值是88和77,这样一来只需要对文件进行解密就行了,先把那个数组dump出来,然后写脚本解密
123
这里出现了一个很大的坑,把58和4D当成异或的key之后发现解密出来的东西不是文件,绝了,首先去确定下是什么文件比较好,
123
有了文件头第一位和第三位相同的特征之后就可以发现是jpeg文件,直接找个jpeg文件看下特征
123
我佛了,竟然重复的部分是01,这样就好办了,重新得到密钥是76和89写文件解密,我比较菜,先读取二进制文件写到一个txt里

def main():
f = open("flag","rb")
outfile = open("out.txt","wb")
i = 0
while 1:
    c = f.read(1)
    i = i + 1
    if not c:
        break
    if i%32 == 0:
        outfile.write("\n")
    else:
        if ord(c) <= 15:
            outfile.write(("0x0"+hex(ord(c))[2:])[2:])
        else:
            outfile.write((hex(ord(c)))[2:])
outfile.close()
f.close()

这样就得到了文件的十六进制表示,然后进行下解密就行了

def main():
f = open(r"F:\out4.txt", "rb")
outfile = open(r"F:\out.txt", "wb")
i = 0
j = 0
while 1:
    j =j+1
    c = f.read(2)
    d=int(c,16)
    if (j % 2) == 0:
        d ^= 76
    else:
        d ^= 89
    s=hex(d)[2:]
    s=s.zfill(2)
    #print(s)
    i = i + 1
    if not c:
        break
outfile.close()
f.close()

这样就可以获得解密后的jpeg的十六进制数据

123

123

可以发现正常的jpeg文件头ffd8已经成功完成了,到这里这题就差不多结束了,挺棒的说实话,再一次意识到了自己是多菜