鹏程杯
开始先小小的吐槽一下这个比赛时间跟四六级撞了一天,难受啊啊啊啊啊.还好是有出解
下面是分享re部分的一些wp
babyconnet
Server.exe 有主逻辑

使用XOR 解密的
flag_dll_check(buf); 验证flag

WASD实现移动
SMC:解密

inside.dll的check,2是终点,1是正常
mov eax, 0; ret 是可通过
mov eax, [eax] (eax=0 时崩溃 ) 不可通过
mov dword_10014AC8, 1 终点

这里patch了53
下面patch了85

这里是用来nop的
这里是大概的迷宫
T是指的传送门,*是可以移动的墙
求解
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 from collections import deque
def solve_maze():
# 初始通路 + 特殊位置(传送门)
initial_paths = {1, 11, 13, 15, 16, 17, 18, 21, 23, 25, 28, 31, 33, 35, 38,
41, 42, 43, 45, 46, 48, 56, 58, 61, 62, 63, 64, 66, 68,
71, 74, 76, 78, 81, 82, 84, 86, 88}
start, end = 1, 88
queue = deque([((start, frozenset()), "D")])
visited = {(start, frozenset())}
while queue:
(pos, opened), path = queue.popleft()
if pos == end:
return path
current_paths = initial_paths | opened
for direction, delta in [('W', -10), ('S', 10), ('A', -1), ('D', 1)]:
new_pos = pos + delta
# 边界检查...
if new_pos in current_paths:
new_opened = set(opened)
if new_pos == 13: new_opened.add(53) # 打开位置53
if new_pos == 82: new_opened.add(85) # 打开位置85
new_state = (new_pos, frozenset(new_opened))
if new_state not in visited:
visited.add(new_state)
queue.append((new_state, path + direction))
return None
# 结果
path = "DSSSSDDWWWSSSSSAASSDAWWDDDSSDDWWWWAWWWDDDSSSSSSS"
flag.dll里面是主要的检查那么看这里

按照后面四个字节来求解,密文在&unk_10015000里面是
1
0x50,0x73,0x65,0xCC,0x0,0xC,0x11,0x2E,0x2,0x26,0x2,0x3,0xD,0x7A,0x7A,0x1B,0x36,0x61,0x4C,0x6,0x18,0x4C,0xF,0x46,0x58,0x30,0x30,0x53,0x62,0x58,0x5A,0x68,0xE,0x34,0x55,0x5,0x5B,0x6C,0x4A,0x44,0x5E,0x36,0x42,0x7D
然后就是exp了
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 maze_path = "DSSSSDDWWWSSSSSAASSDAWWDDDSSDDWWWWAWWWDDDSSSSSSS"
# flag.dll 的目标密文
target = bytes([
0x50, 0x73, 0x65, 0xCC, 0x00, 0x0C, 0x11, 0x2E,
0x02, 0x26, 0x02, 0x03, 0x0D, 0x7A, 0x7A, 0x1B,
0x36, 0x61, 0x4C, 0x06, 0x18, 0x4C, 0x0F, 0x46,
0x58, 0x30, 0x30, 0x53, 0x62, 0x58, 0x5A, 0x68,
0x0E, 0x34, 0x55, 0x05, 0x5B, 0x6C, 0x4A, 0x44,
0x5E, 0x36, 0x42, 0x7D,
])
print(f"目标密文 ({len(target)} 字节): {target.hex()}")
# 分析 nullsub_1 的 XOR 逻辑
# 看起来是: data[i] ^= data[i+1] 的循环
# 尝试逆向 XOR 操作
def reverse_xor(data):
"""逆向 XOR 操作: 从后往前"""
result = bytearray(data)
for i in range(len(result) - 2, -1, -1):
result[i] ^= result[i + 1]
return bytes(result)
# 尝试多次逆向(因为代码中有3个类似的循环)
decrypted = target
for round_num in range(3):
decrypted = reverse_xor(decrypted)
try:
text = decrypted.decode('ascii')
if text.startswith('flag') or text.startswith('PCC') or 'ctf' in text.lower():
print(f"\n第 {round_num + 1} 轮解密后: {text}")
except:
pass
print(f"第 {round_num + 1} 轮: {decrypted.hex()}")
# 检查是否有可打印字符
printable = ''.join(chr(b) if 32 <= b < 127 else '.' for b in decrypted)
print(f" 可打印: {printable}")
More more flower
里面的字节码是
1 | |
密文是
1 | |
根据VM得到指令码是
1 | |
反VM得到
1 | |
根据这个可以得到算法
1 | |
那么exp是
1 | |
Get_My_Emoji_wp
在emoji_encoder里面的
这里是标准的RC4加密
exp
1 | |
meddddgo
DIE查
GO语言的,无壳.根据Input your flag: 定位到 sub_140001A20()里面
可以看到是处理了\r和\n.
检查位置sub_1400B3740()
汇编里面test rsi, 0xf,要求了是16倍数
输出正确
1 | |
里面有个魔改的SM4
在sub_1400B32A0()
这里是s-box
1 | |
SM4是K[i] = MK[i] ^ FK[i]这里是K[i] = MK[i] ^ FK[i] ^ MAGIC[i]
可以从里面找到seed是10 23 45 67 89 ab cd ef 01 35 79 bd f0 22 44 66
exp是
1 | |