• Cybrics CTF 2019 Quals Writeup Revrse


    Cybrics CTF 2019 Quals Writeup Revrse

    上周末和天枢的大佬们一起打了 Cybrics 这个比赛,金砖国家 CTF 比赛,群里大佬们说是搬金砖 hhhh。场上做出了两个逆向题,这里做一下总结。

    Oldman Reverse

    难度:Baby

    链接:https://cybrics.net/tasks/oldman

    题目给出了一段汇编代码,很短,简单分析一下就能确定代码流程。

    .MCALL  .TTYOUT,.EXIT
    START:
        mov   #MSG r1 
        mov #0d r2
        mov #32d r3
    loop:       
        mov   #MSG r1 
        add r2 r1
        movb    (r1) r0
        .TTYOUT
        sub #1d r3
        cmp #0 r3
        beq     DONE
        add #33d r2
        swab r2
        clrb r2
        swab r2    
        br      loop      
    DONE: 
        .EXIT
    
    MSG:
        .ascii "cp33AI9~p78f8h1UcspOtKMQbxSKdq~^0yANxbnN)d}k&6eUNr66UK7Hsk_uFSb5#9b&PjV5_8phe7C#CLc#<QSr0sb6{%NC8G|ra!YJyaG_~RfV3sw_&SW~}((_1>rh0dMzi><i6)wPgxiCzJJVd8CsGkT^p>_KXGxv1cIs1q(QwpnONOU9PtP35JJ5<hlsThB{uCs4knEJxGgzpI&u)1d{4<098KpXrLko{Tn{gY<|EjH_ez{z)j)_3t(|13Y}"
    .end START
    

    这段代码加载 MSG 字符串到寄存器 r1 中,之后进一个循环,每轮循环输出 MSG[r2]。在每轮循环中,r2 先增加33,之后三个操作SWAB r2; CLRB r2; SWAB r2;不是太明白。经过一番百度 google,能够确定 SWAB 交换寄存器的字节顺序,CLRB 清除寄存器。可能没办法直接理解到这段代码的含义,不过结合 33 这个自增长度,还有 MSG 的总长是 256,基本就能猜到这是在模 256。写代码确认一下就得到了 flag。

    msg = "cp33AI9~p78f8h1UcspOtKMQbxSKdq~^0yANxbnN)d}k&6eUNr66UK7Hsk_uFSb5#9b&PjV5_8phe7C#CLc#<QSr0sb6{%NC8G|ra!YJyaG_~RfV3sw_&SW~}((_1>rh0dMzi><i6)wPgxiCzJJVd8CsGkT^p>_KXGxv1cIs1q(QwpnONOU9PtP35JJ5<hlsThB{uCs4knEJxGgzpI&u)1d{4<098KpXrLko{Tn{gY<|EjH_ez{z)j)_3t(|13Y}"
    
    def loop(s):
        r1 = s
        r2 = 0
        r3 = 32
        ans = ''
        while True:
            ans += r1[r2]
            r3 -= 1
            if r3 <= 0:
                break
            r2 += 33
            r2 %= 256
        
        return ans
        
    print len(msg)
    print loop(msg)
    

    cybrics{pdp_gpg_crc_dtd_bkb_php}

    ps. CTF time 的 wp 说这是 PDP11 的汇编代码。

    matreshka

    难度:Easy

    链接:https://cybrics.net/tasks/matreshka

    终于遇到了一道很典型的逆向题。拿到的是一个 .class 文件,拖进 jd-gui 直接能看到反编译的 java 代码。

    反编译代码

    分析一下代码的流程,首先加密Syste.getProperty("user.name"),加密的值和arrayOfByte2对比,如果相同,就进入下一步,否则程序结束。之后解密 data.bin,将结果保存到 stage2.bin。stage2.bin 显然是下一关的程序。这里通过百度能确定,Syste.getProperty("user.name")就是系统的用户名。

    再看一下 decode 和 encode 函数,可以看到单纯地做了 DES 加解密。

    加解密函数

    拿 python 模拟一下,就拿到了stage2.bin。注意这里的 DES 是 ECB 模式。

    from Crypto.Cipher import DES
    import binascii
    import base64
    
    key_1 = 'matreha!'
    cipher = [76, -99, 37, 75, -68, 10, -52, 10, -5, 9, 92, 1, 99, -94, 105, -18]
    cipher_s = ''
    for x in range(len(cipher)):
        cipher_s += '%02x' % (cipher[x] % 256)
    
    cipher_s = binascii.unhexlify(cipher_s)
    cipherX = DES.new(key_1, DES.MODE_ECB)
    y = cipherX.decrypt(cipher_s)
    
    fp = open("data.bin", "rb")
    fpp = open("steg2.bin", "wb")
    
    key_2 = "lettreha"
    print len(key_2)
    
    cipherXX = DES.new(key_2, DES.MODE_ECB)
    cipher = fp.read()
    print len(cipher)
    
    for cnt in range(len(cipher) / 16):
        res = cipherXX.decrypt(cipher[cnt*16:cnt*16+16])
        fpp.write(res)
    
    fp.close()
    fpp.close()
    

    stage2.bin 是一个 elf 文件,拖进 IDA 会发现特别混乱。做过这种题就能知道这是 go 语言的二进制程序,第一次的同学百度一下反编译出的函数名也就明白了。

    go 的二进制程序主函数在 main_main 中,反编译的结果虽然不是很清晰,但是能确定做了 RC4 加密,之后对比加密字符串,如果正确就进入下一步。下一步对另一段做 RC4 解密,解密结果保存在文件当中。

    stage2.bin逆向

    逆向到这里,函数参数的分析就很头疼了。很难一眼就确定 RC4 的密钥、明文是什么,这个时候动态调试往往能事半功倍。

    打开我无敌的 GDB,先在函数入口处下断点,断点下在 main.main 上,注意 IDA 反编译会把函数名的"."转成"_"。main.main函数一开始有很多跳转,直接下断点到 RC4 异或加密的地方。这下能够很明显的看出,第一步 RC4 加密的明文是当前目录的名字。同样的方法也能确定 RC4 的密钥。

    gdb动态调试

    写脚本解密 RC4 的密文,得到正确的目录名,之后运行程序就自动解密出了下一关的代码 result.pyc。

    import random, base64
    from hashlib import sha1
    
    def rc4_xor(data, key):
        """RC4 algorithm"""
        x = 0
        box = range(256)
        for i in range(256):
            x = (x + box[i] + ord(key[i % len(key)])) % 256
            box[i], box[x] = box[x], box[i]
        x = y = 0
        out = []
        for char in data:
            x = (x + 1) % 256
            y = (y + box[x]) % 256
            box[x], box[y] = box[y], box[x]
            out.append(chr(ord(char) ^ box[(box[x] + box[y]) % 256]))
    
        return ''.join(out)
    
    
    key = 'x01x03x03x07x03x03x08x01'
    data = 'x53xddxc5x87xe4x63x99x14x4fxa4x14x2dxc4x24x04xc0xb0'
    
    print rc4_xor(data, key)
    

    拿到 result.pyc 后,反编译的结果却很诡异。

    def decode(data, key):
        idx = 0
        res = []
    # WARNING: Decompyle incomplete
    
    flag = [
        40,
        11,
        82,
        58,
        93,
        82,
        64,
        76,
        6,
        70,
        100,
        26,
        7,
        4,
        123,
        124,
        127,
        45,
        1,
        125,
        107,
        115,
        0,
        2,
        31,
        15]
    print('Enter key to get flag:')
    key = input()
    if len(key) != 8:
        print('Invalid len')
        quit()
    res = decode(flag, key)
    # WARNING: Decompyle incomplete
    

    代码用输入的8位 key 和 flag 做某些操作,之后的结果应该就是 flag。最关键的 decode 函数反编译失败,是工具出了问题吗?用 010Editor 再去看 result.pyc,发现它本来就是不完整的。

    这个时候只能先猜了,最简单的就是逐位异或了,而且我们知道flag的前几位是 "cybrics{",正好是8位。拿 "cybrics{" 和 flag 的前8位异或,结果是"Kr0H4137",显然我们猜对了。最后异或整个flag,得到答案。

    import binascii
    
    flag = [
        40,
        11,
        82,
        58,
        93,
        82,
        64,
        76,
        6,
        70,
        100,
        26,
        7,
        4,
        123,
        124,
        127,
        45,
        1,
        125,
        107,
        115,
        0,
        2,
        31,
        15]
    
    fake_flag = "cybrics{"
    print len(flag)
    
    for x in range(len(flag)):
        print "%02x" % (flag[x]),
    print ""
    
    print binascii.hexlify(fake_flag)
    
    for i in range(8):
        print chr(flag[i] ^ ord(fake_flag[i]) ),
    
    
    def decode(key, data):
        ans = ''
        for x in range(len(data)):
            data[x] ^= ord(key[x % len(key)])
            ans += chr(data[x])
        return ans
    
    print decode("Kr0H4137", flag)
    

    cybrics{M4TR35HK4_15_B35T}

    Hidden Flag

    难度:hard

    链接:https://cybrics.net/tasks/hiddenflag

    TODO

  • 相关阅读:
    js输出
    mysql主从同步(4)-Slave延迟状态监控
    mysql主从同步(3)-percona-toolkit工具(数据一致性监测、延迟监控)使用梳理
    【故障】MySQL主从同步故障-Slave_SQL_Running: No
    什么是bgp线路
    F5负载均衡虚拟服务器配置FTP端口访问不了
    Python 拷贝对象(深拷贝deepcopy与浅拷贝copy)
    东风本田/XR-V/2017款
    mysqldump导出数据库导入数据库
    .htaccess设置301跳转及常用技巧整理
  • 原文地址:https://www.cnblogs.com/helica/p/11348740.html
Copyright © 2020-2023  润新知