2018年全国大学生信息安全竞赛 CISCN Writeup

逆向:

RE:

题目文件:链接:点击打开链接 密码:hyzy

这题当时做的时候陷入了出题人的陷阱,上来找到了“关键部分”就开始逆,但是遇到了很多问题,因为有很多函数,而且篇幅都不小,而且每个函数还要调用其他一大堆函数,这就大大增加了工作量,后面实在看不下去了,就放弃了。

后面找到一些大佬的writeup看了看,原来是思路的问题:

总结一下:

逆向赛题一般工作量不会大到让你逆不了,一下锁定了十七八个函数肯定是有问题的,换思路

在这里就记录一下自己的学习历程,偏基础一点,适用于刚入门的,比如我。

看题目:

首先用IDA分析:

main函数:(代码分析见图中注释

2018年全国大学生信息安全竞赛 CISCN Writeup_第1张图片

2018年全国大学生信息安全竞赛 CISCN Writeup_第2张图片

2018年全国大学生信息安全竞赛 CISCN Writeup_第3张图片


函数sub_4012DE(v12):

2018年全国大学生信息安全竞赛 CISCN Writeup_第4张图片

2018年全国大学生信息安全竞赛 CISCN Writeup_第5张图片

第一部分逆向脚本:

def check1(str0):
    flagmd5 = ''
    for i in range(len(str0)):
        temp = ord(str0[i])-i%10
        if temp <= ord('A') + 5 and temp >= ord('A'):
            flagmd5 += chr(temp)
        else:
            flagmd5 += str0[i]
    
    return flagmd5

得到的结果拿去在线解密 : yubu

函数sub_401411(v19):(与第一个检查函数同理)

关键部分如下:比上一个多了一点点
2018年全国大学生信息安全竞赛 CISCN Writeup_第6张图片
逆向脚本:
def change2(str0):
    byte_603860 = [0xd7,0xdb,0xb4,0x0e,0x1e,0x17,0x2b,0x76,0x34,0xcc,0x00,0x81,0xef,0x67,0x29,0xb3]
    flag_byte = ""
    for i in range(0,32,2):
        v5 = str0[i]
        v7 = str0[i+1]
        if ord(v5)>=0x41 and ord(v5)<=0x46:
            tmp = ord(v5)-0x41+10
        elif ord(v5)>=0x30 and ord(v5)<=0x39:
            tmp = ord(v5)-0x30
        else:
            print "Error"
            
        if ord(v7)>=0x41 and ord(v7)<=0x46:
            tmp1 = ord(v7)-0x41+10
        elif ord(v7)>=0x30 and ord(v7)<=0x39:
            tmp1 = ord(v7)-0x30
        else:
            print "Error"
        byte = str(bin(tmp)[2:]).rjust(4,"0")+str(bin(tmp1)[2:]).rjust(4,"0")
        flag_byte += hex(int(byte,2))[2:].rjust(2,"0")


    flagmd5 = ""
    for i in range(0,16,):
        flagmd5 += str( hex(int(flag_byte[2*i]+flag_byte[2*i+1],16) ^ byte_603860[i]).rjust(2,"0")[2:] )
    return flagmd5

得到的结果拿去在线解密 :  kulo

函数sub_401562(v20):

发现最下面将最后的结果写入了一个文件“flag”,前面未知量较多,不适合逆向尝试爆破,脚本如下:

2018年全国大学生信息安全竞赛 CISCN Writeup_第7张图片

这里我们从写入文件的一步开始倒着看,上面是一个循环,奇偶不同异或的值也不同,但只有v15,v16两个值。这里我们不管他之前的值是什么,只有两个字节我们可以爆破

爆破脚本:

def get_data():  
    f2 = open("result",'wb')  
    for i in range(256):  
        for j in range(256):  
            f1 = open("data",'rb')  
            for k in range(6047):  
                ori_byte = f1.read(1)  
                if k&1 ==0:  
                    f2.write(chr(ord(ori_byte)^i))  
                else:  
                    f2.write(chr(ord(ori_byte)^j))  
  
            f1.close()  
            f2.write('\n')  
    f2.close()  
  
get_data()  

写脚本的思路就是,因为v15、v16我们不知道,但是我们知道他们每个都是一个“char”类型的数,一个字节,那么范围就是从0到255,每一个v15,尝试256个v16,这时候每一种v15、v16的组合和一个大的数组byte_6020E0,做上述操作。一共会生成256*256*6047个字节的数据,这256*256次中一定有一次组合是正确的,是我们需要的数据。

我跑了大约有七八分钟的样子,得到了数据快400M

用HxD打开,这时候就需要我们脑洞了,这里出题人放的是一张 jpg,文件头为“FF D8 FF E0 00 10 4A 46 49 46 00 01”,搜索发现有头,再搜索“FF D9”文件尾,把这一部分数据截取出来单独保存成jpg后缀的文件。

打开图片就可以看到一个字符串,得到了第三部分数据。


我们将三部分的数据组合得到flag:

CISCN{yubu_kulo_JipCC%6&goFunMz}


前两段完整代码:

def change1(str0):

    str00 = ''
    for i in range(len(str0)):
        temp = ord(str0[i])-i%10
        if temp <= ord('A') + 5 and temp >= ord('A'):
            str00 += chr(temp)
        else:
            str00 += str0[i]
    
    return str00

def change2(str0):
    byte_603860 = [0xd7,0xdb,0xb4,0x0e,0x1e,0x17,0x2b,0x76,0x34,0xcc,0x00,0x81,0xef,0x67,0x29,0xb3]
    flag_byte = ""
    for i in range(0,32,2):
        v5 = str0[i]
        v7 = str0[i+1]
        if ord(v5)>=0x41 and ord(v5)<=0x46:
            tmp = ord(v5)-0x41+10
        elif ord(v5)>=0x30 and ord(v5)<=0x39:
            tmp = ord(v5)-0x30
        else:
            print "Error"
            
        if ord(v7)>=0x41 and ord(v7)<=0x46:
            tmp1 = ord(v7)-0x41+10
        elif ord(v7)>=0x30 and ord(v7)<=0x39:
            tmp1 = ord(v7)-0x30
        else:
            print "Error"
        byte = str(bin(tmp)[2:]).rjust(4,"0")+str(bin(tmp1)[2:]).rjust(4,"0")
        flag_byte += hex(int(byte,2))[2:].rjust(2,"0")

    flagmd5 = ""
    for i in range(0,16,):
        flagmd5 += str( hex(int(flag_byte[2*i]+flag_byte[2*i+1],16) ^ byte_603860[i]).rjust(2,"0")[2:] )

    return flagmd5

flag1 = ""
flag2 = ""
flag1_check = "762306GI890905GKL6887E5D75776382"
flag2_check = "762306GI890905GKL6887E5D75776382"
flag1 = change1(flag1_check)
print "flag1",flag1
flag2 = change2(change1(flag2_check))
print "flag2",flag2
flag1 762306AB890905CFF6887D5A75776382    在线解密之后为 : yubu
flag2 a1f8b2a5971e2eb9c2447ddb9a104a31    在线解密之后为 : kulo








你可能感兴趣的:(CTF)