开场宏定义逆向,直接傻眼了……不过好在后来静下心做出来了,整场比赛下来,带给我惊喜的是队友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
则定义A0
为0
,其实就是一个取反的过程
#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)
直接复制鍚戞櫄0612
就能正确得到flag
发表回复