0%

SCTF-2021 CplusExceptionEncrypt WP

  • 双击运行可以发现有缺失的 DLL。打开 IDA 大概看一下,程序流图比较大,有一堆的 throw 和 catch,F5 无法正常反编译,纯静态不好看
  • Findcrypt 看一眼有 AES 的 S 盒和逆 S 盒
  • 字符串可以看到编译信息,也可以用 DIE 之类的工具看一眼,GCC: (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0。于是安装环境,边调边看汇编逆(保留了符号信息,还算比较好看)
  • 结合 IDA 的程序流图,在 catch 的地方下断,防止跑飞
  • 第一步可以看出是一个 TEA 加密。首先取输入的前 16 个字节,组成 4 个 DWORD,两两同时进行加密。碰到函数可以直接步过看效果。魔改了两个地方,首先是改了 delta,另外是多异或了一个sum + i
  • TEA 加密结束后,4 个 DWORD 的最低字节与"SCTF"的一个字母异或
  • 然后进入 AES 加密
    • 通过 S 盒和密钥扩展常量可以识别密钥扩展部分
    • 第一次轮密钥加之后还与 0x66 进行了一次异或
    • 通过使用逆 S 盒可以判断是在做逆 S 盒变换
    • 逆行移位给了函数名
    • 剩下就是列混淆了,不用步进,步过看效果验证猜想
  • 至此整个逻辑就比较清晰了:程序分两次对输入进行加密,每次取 16 个字节,经过魔改 TEA、异或、魔改 AES 得到密文。最后与程序开头的正确密文进行比较
  • 另外学习 Windows SEH 可以参考《加密与解密》第八章
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    import ctypes
    from pwn import p32, u32
    from aeskeyschedule import key_schedule
    from phoenixAES import MC, InvMC, InvSBox, SBox, InvShiftRow, ShiftRow, AddKey

    def tea_encrypt(plain, key):
    y, z = [ctypes.c_uint32(x) for x in plain]

    sum_val = ctypes.c_uint32(0)
    delta = 0x73637466

    for i in range(32):
    sum_val.value += delta
    y.value += ((z.value << 4) + key[0]) ^ (z.value + sum_val.value) ^ ((z.value >> 5) + key[1]) ^ (sum_val.value + i)
    z.value += ((y.value << 4) + key[2]) ^ (y.value + sum_val.value) ^ ((y.value >> 5) + key[3]) ^ (sum_val.value + i)

    return [y.value, z.value]

    def tea_decrypt(cipher, key):
    y, z = [ctypes.c_uint32(x) for x in cipher]
    sum_val = ctypes.c_uint32(0x6C6E8CC0)
    delta = 0x73637466

    for i in range(31, -1, -1):
    z.value -= ((y.value << 4) + key[2]) ^ (y.value + sum_val.value) ^ ((y.value >> 5) + key[3]) ^ (sum_val.value + i)
    y.value -= ((z.value << 4) + key[0]) ^ (z.value + sum_val.value) ^ ((z.value >> 5) + key[1]) ^ (sum_val.value + i)
    sum_val.value -= delta

    return [y.value, z.value]

    def AES_encrypt(plain, round_keys):
    cipher = plain
    cipher = AddKey(cipher, round_keys[0])
    for i in range(16):
    cipher[i] ^= 0x66

    for j in range(1, 10):
    cipher = InvSBox(cipher)
    cipher = InvShiftRow(cipher)
    cipher = MC(cipher)
    cipher = AddKey(cipher, round_keys[j])

    cipher = SBox(cipher)
    cipher = ShiftRow(cipher)
    cipher = AddKey(cipher, round_keys[10])

    return cipher

    def AES_decrypt(cipher, round_keys):
    plain = cipher

    plain = AddKey(plain, round_keys[10])
    plain = InvShiftRow(plain)
    plain = InvSBox(plain)

    for j in range(9, 0, -1):
    plain = AddKey(plain, round_keys[j])
    plain = InvMC(plain)
    plain = ShiftRow(plain)
    plain = SBox(plain)

    for i in range(16):
    plain[i] ^= 0x66
    plain = AddKey(plain, round_keys[0])

    return plain

    TEA_key = [0] * 4
    TEA_key[1] = 0x21667463
    TEA_key[0] = 0x735F6F74
    TEA_key[3] = 0x5F656D6F
    TEA_key[2] = 0x636C6557

    cipher = b"\xBE\x1C\xB3\xF3\xA1\xF4\xE4\x63\x11\xE1\x1C\x6B\x54\x0A\xDF\x74\xF2\x93\x55\xDA\x48\xFC\xA2\x3C\x89\x63\x2E\x7F\x8D\xA4\x6D\x4E"

    delta = [0x66, 0x74, 0x63, 0x73][::-1]

    AES_key = b'Welcome_to_sctf!'
    round_keys = key_schedule(AES_key)
    assert AES_key == round_keys[0]

    # 0: 57656c636f6d655f746f5f7363746621
    # 1: c4569198ab3bf4c7df54abb4bc20cd95
    # 2: 71ebbbfddad04f3a0584e48eb9a4291b
    # 3: 3c4e14abe69e5b91e31abf1f5abe9604
    # 4: 9adee6157c40bd849f5a029bc5e4949f
    # 5: e3fc3db39fbc803700e682acc5021633
    # 6: b4bbfe152b077e222be1fc8eeee3eabd
    # 7: e53c843dce3bfa1fe5da06910b39ec2c
    # 8: 77f2f516b9c90f095c130998572ae5b4
    # 9: 892b784d30e277446cf17edc3bdb9b68
    # 10: 063f3daf36dd4aeb5a2c343761f7af5f

    flag = b''
    for i in range(2):
    AES_cipher = cipher[i * 16: i * 16 + 16]
    AES_plain = AES_decrypt(AES_cipher, round_keys)
    for i in range(4):
    AES_plain[i * 4] ^= delta[i]
    TEA_cipher = AES_plain
    TEA_plain = []
    TEA_plain += tea_decrypt([u32(TEA_cipher[0:4]), u32(TEA_cipher[4:8])], TEA_key)
    TEA_plain += tea_decrypt([u32(TEA_cipher[8:12]), u32(TEA_cipher[12:16])], TEA_key)
    for num in TEA_plain:
    flag += p32(num)
    print(flag)
---------------感谢您的阅读---------------