Mas0n
to be reverse engineer🐧
翻车鱼

第四届浙江省大学生网络与信息安全竞赛(决赛)

第四届浙江省大学生网络与信息安全竞赛(决赛)

开场宏定义逆向,直接傻眼了……不过好在后来静下心做出来了,整场比赛下来,带给我惊喜的是队友web ak了,短暂的冲上了No1,可惜的是队伍中Pwn和Crypto比较薄弱,没能保持住。

还是挂我做的一些题吧。

Re

preprocess

题目其实不是新题……

原题应该来自于今年GoogleCTF reverse的CPP

考点是C++的宏定义

clang-format --style='{IndentPPDirectives: AfterHash}'  preprocess.c > loveCTF.c

宏定义处(节选)

#define _COM(a0, a1, a2) (a0<<2 | a1<<1 | a2)
#define COM(a0, a1, a2, a3, a4, a5) (_COM(a3, a1, a5) << 3 | _COM(a0, a4, a2))
#define A COM(A7, A6, A5, A4, A3, A2)
#define B COM(A1, A0, B7, B6, B5, B4)
#define C COM(B3, B2, B1, B0, C7, C6)
#define D COM(C5, C4, C3, C2, C1, C0)
#define _CP(x, y) INPUT_ ## x ## _ ## y
#define CP(x, y) _CP(x, y)
#define _LK(l0, l1, l2, l3, l4, l5, l6, l7) l0 ## l1 ## l2 ## l3 ## l4 ## l5 ## l6 ## l7
#define LK(l0, l1, l2, l3, l4, l5, l6, l7) _LK(l0, l1, l2, l3, l4, l5, l6, l7)
#define L LK(l0, l1, l2, l3, l4, l5, l6, l7)
#define SUM (S0 | S1 | S2 | S3) // 0
#define F (R0 | R1 | R2 | R3 | R4 | R5 | R6 | R7 | R8 | R9) // 0

这边的l0~l7其实是索引

#ifdef l0
	#undef l0
#endif
#define l0 0
#ifdef l1
	#undef l1
#endif
#define l1 0
#ifdef l2
	#undef l2
#endif
#define l2 0
#ifdef l3
	#undef l3
#endif
#define l3 0
#ifdef l4
	#undef l4
#endif
#define l4 0
#ifdef l5
	#undef l5
#endif
#define l5 0
#ifdef l6
	#undef l6
#endif
#define l6 0
#ifdef l7
	#undef l7
#endif
#define l7 0
#ifdef A0
	#undef A0
#endif
// 00000000

通过CP(L, 0)得到INPUT_00000000_0,如果值为1则定义A00,其实就是一个取反的过程

#ifdef A0
	#undef A0
#endif
#if CP(L, 0)
	#define A0 0
#else
	#define A0 1
#endif

照此处理3个字节得到24位,再使用了A,B,C,D宏定义处理了二进制位即4*6

简单位移之后与对应数异或……所有数值归零算作成功

#if A ^ 13
	#define S0 1
#else
	#define S0 0
#endif
#if B ^ 27
	#define S1 1
#else
	#define S1 0
#endif
#if C ^ 50
	#define S2 1
#else
	#define S2 0
#endif
#if D ^ 53
	#define S3 1
#else
	#define S3 0
#endif
#if SUM
	#define R0 1
#else
	#define R0 0
#endif

结尾使用F宏定义check,意味着10组24位二进制字串经处理后都为0

#if F
	#error Failed to execute program
#else
	#warning Check completed
#endif

脚本跑出异或表

text = """// Please fill in your flag below
// run `gcc preprocess.c -o preprocess.out`
// Have fun~
#define FLAG_0 CHAR_Z
#define FLAG_1 CHAR_J
#define FLAG_2 CHAR_C
#define FLAG_3 CHAR_T
……省略了太长了,就是源文件内容
"""

data = text.splitlines()
arrs = []
tm = 0
ts = []
for i, v in enumerate(data):
    index = data[i].find(" ^ ")
    if index != -1:
        ts.append(eval(data[i][index + 2:]))

        if data[i].startswith("#if D ^ "):

            arrs.append(ts.copy())
            ts = []

print(arrs)

z3条件约束,求解

# -*- coding:utf-8 -*-
"""
@Author: Mas0n
@File: test10.py
@Time: 2021-10-30 10:53
@Desc: It's all about getting better.
"""

import z3


def com(a0, a1, a2, a3, a4, a5):
    return (a3 << 2 | a1 << 1 | a5) << 3 | (a0 << 2 | a4 << 1 | a2)

# 01011010 01001010 01000011
# 101001
# 010110


arr = [[13, 27, 50, 53], [7, 31, 38, 32], [14, 9, 35, 50], [38, 9, 51, 11], [36, 21, 19, 4], [46, 13, 35, 11], [38, 5, 54, 19], [38, 23, 2, 61], [46, 5, 22, 19], [22, 49, 39, 2]]


tflag = ""

for i in range(0, 30, 3):
    flag = [z3.BitVec("f" + str(i), 8) for i in range(3)]
    slo = z3.Solver()
    tmp = arr[i // 3]
    a7 = flag[0] >> 7 & 1
    a6 = flag[0] >> 6 & 1
    a5 = flag[0] >> 5 & 1
    a4 = flag[0] >> 4 & 1
    a3 = flag[0] >> 3 & 1
    a2 = flag[0] >> 2 & 1
    a1 = flag[0] >> 1 & 1
    a0 = flag[0] >> 0 & 1
    slo.add(com(a7 ^ 1, a6 ^ 1, a5 ^ 1, a4 ^ 1, a3 ^ 1, a2 ^ 1) ^ tmp[0] == 0)

    b7 = flag[1] >> 7 & 1
    b6 = flag[1] >> 6 & 1
    b5 = flag[1] >> 5 & 1
    b4 = flag[1] >> 4 & 1
    b3 = flag[1] >> 3 & 1
    b2 = flag[1] >> 2 & 1
    b1 = flag[1] >> 1 & 1
    b0 = flag[1] >> 0 & 1
    slo.add(com(a1 ^ 1, a0 ^ 1, b7 ^ 1, b6 ^ 1, b5 ^ 1, b4 ^ 1) ^ tmp[1] == 0)

    c7 = flag[2 ] >> 7 & 1
    c6 = flag[2 ] >> 6 & 1
    c5 = flag[2 ] >> 5 & 1
    c4 = flag[2] >> 4 & 1
    c3 = flag[2] >> 3 & 1
    c2 = flag[2] >> 2 & 1
    c1 = flag[2] >> 1 & 1
    c0 = flag[2] >> 0 & 1
    slo.add(com(b3 ^ 1, b2 ^ 1, b1 ^ 1, b0 ^ 1, c7 ^ 1, c6 ^ 1) ^ tmp[2] == 0)

    slo.add(com(c5 ^ 1, c4 ^ 1, c3 ^ 1, c2 ^ 1, c1 ^ 1, c0 ^ 1) ^ tmp[3] == 0)

    # slo.add(122 >= flag[0])
    # slo.add(122 >= flag[1])
    # slo.add(122 >= flag[2])

    assert slo.check() == z3.sat
    solov = slo.model()
    tflag += "".join([chr(solov.eval(flag[i]).as_long()) for i in range(3)])

print(tflag)


print(((0 << 2 | 0 << 1 | 1) << 3 | (1 << 2 | 0 << 1 | 1)))
com(1, 0, 1, 0, 0, 1)
# ((0 << 2 | 0 << 1 | 1) << 3 | (1 << 2 | 0 << 1 | 1))

最简单的逆向

arr = [0x76, 0x73, 0x85, 0x75, 0x86, 0x78, 0xAD, 0x6B, 0x97, 0x68, 0x98, 0x67, 0x64, 0x64, 0x62, 0x97, 0x68, 0x98, 0x6B, 0x6B, 0x96, 0x67, 0x62, 0x69, 0x95, 0x96, 0x65, 0x96, 0x6A, 0x69, 0x69, 0x65, 0x66, 0x97, 0x68, 0x98, 0x6A, 0x95, 0x68, 0xAF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
print("".join([chr((i - 50) & 0xff) for i in arr]))

RE人三项

三段式加密,以_分隔

第一段是简单的字符ASCII变换

第二段就是标准sm4

第三段是个迷宫

# -*- coding:utf-8 -*-
"""
@Author: Mas0n
@File: zjctf4.py
@Time: 2021-10-30 11:09
@Desc: It's all about getting better.
"""
import pysm4

flag1 = [i for i in "E0gy3"]
maps = "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"
for i, v in enumerate(flag1):
    if ord("A") <= ord(v) <= ord("Z"):
        flag1[i] = chr(maps.index(v) + 0x41)
    elif ord("a") <= ord(v) <= ord("z"):
        flag1[i] = chr(maps.index(v) + 0x47)
    else:
        pass
flag1 = "".join(flag1)

encdata = int.from_bytes(bytes.fromhex("F27352FB8DF41D6DC233B5A5EEC160DA"), 'big')
key = 0x0123456789abcdeffedcba9876543210
flag2 = pysm4.decrypt(encdata, key)
flag2 = flag2.to_bytes(16, 'big')
print(flag2)

arrs = [
    [0x0077DF9E, 0x0077DFB1, 0x0077DF84, 0x0077DF84, 0x0077E2D6, 0x0077DF84, 0x0077DFAD],
    [0x0077DF84, 0x0077DFB2, 0x0077DF84, 0x0077DF84, 0x0077DF84, 0x0077DF98, 0x0077DF84],
    [0x0077DF84, 0x0077DFBC, 0x0077DF84, 0x0077DF84, 0x0077E06A, 0x0077DF84, 0x0077DF84],
    [0x0077DF84, 0x0077DFE4, 0x0077E017, 0x0077E066, 0x0077E069, 0x0077DF84, 0x0077DF84],
    [0x0077E06B, 0x0077DF84, 0x0077DF84, 0x0077DF84, 0x0077E0D9, 0x0077DF84, 0x0077DF84],
    [0x0077DF84, 0x0077DF84, 0x0077DFE8, 0x0077DF84, 0x0077E1B5, 0x0077E21A, 0x0077E291],
    [0x0077DF84, 0x0077DF84, 0x0077DF84, 0x0077DF84, 0x0077DF84, 0x0077DF84, 0x0077E36C]
]
mik = arrs.copy()
for i, v in enumerate(arrs):
    for j, v2 in enumerate(v):
        if v2 <= 0x0077DF9E:
            mik[i][j] = 1
        else:
            mik[i][j] = 0

print(mik)
# [
#     [s, 0, 1, 1, 0, 1, 0],
#     [1, 0, 1, 1, 1, 1, 1],
#     [1, 0, 1, 1, 0, 1, 1],
#     [1, 0, 0, 0, 0, 1, 1],
#     [0, 1, 1, 1, 0, 1, 1],
#     [1, 1, 0, 1, 0, 0, 0],
#     [1, 1, 1, 1, 1, 1, e]
# ]
# dsssdddssdds
# 'a'
flag3 = ""
awsd = [1, 7, -1, -7]
adds = -127
for i in "dsssdddssdds":
    if i == "d":
        adds = awsd.index(1)
    elif i == 'a':
        adds = awsd.index(-1)
    elif i == 's':
        adds = awsd.index(7)
    elif i == "w":
        adds = awsd.index(-7)
    flag3 += chr(adds + ord('a'))

print(flag3)

Misc

asoul_lover

签到题,题目给了hint

最近我旁边的灏妹天天上班第一句就是“Avaava”,还说要当安恒第一顶碗人。在他桌面上似乎发现了一个好康的压缩文件,想想他之前用过自己的名字+生日来做压缩密码,这把应该也能破解出来咯?对咯,他的压缩软件支持中文密码。flag的格式为 DASCTF{xxxxxx},提交时只需要提交括号内的字符串。

文件内包含了一个关于Ava的个人资料

那就直接生成下爆破

names = ["向晚"]
births = ["0612"]
import itertools
import zipfile

ttt = ""
for i in itertools.product(names, births):
    ttt += i[0] + i[1]
    ttt += "\n"
with open(r"D:\Downloads\Programs\1.txt", "w", encoding="utf-8") as f:
    f.write(ttt)
https://cdn.shi1011.cn/2021/10/689bf0bcd42fd6623696b7ac0e205ded.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

直接复制鍚戞櫄0612就能正确得到flag

本文链接:https://blog.shi1011.cn/ctf/1743
本文采用 CC BY-NC-SA 4.0 Unported 协议进行许可
# #
首页      ctf      第四届浙江省大学生网络与信息安全竞赛(决赛)

Mas0n

文章作者

回复 Mas0n 取消回复

textsms
account_circle
email

翻车鱼

第四届浙江省大学生网络与信息安全竞赛(决赛)
开场宏定义逆向,直接傻眼了……不过好在后来静下心做出来了,整场比赛下来,带给我惊喜的是队友web ak了,短暂的冲上了No1,可惜的是队伍中Pwn和Crypto比较薄弱,没能保持住。 还是挂我…
扫描二维码继续阅读
2021-10-30