BBRE#
主函数先调用 function2, 只检验了flag的前16字节。从另一个角度来看,它也只加密了16字节。
但是输入的要求是 %19s,而且还有一个始终没被调用的 function1,怎么想都觉得有点奇怪吧。
此事在deepseek中亦有记载

实际上是分段加密并检验。中间通过隐蔽的栈溢出来劫持返回地址,改变控制流。
分析 function0,其参数是经过 function2 加密后的字符串指针,内部调用包含漏洞的 strcpy 。简单分析一下栈帧,dst 在 ebp - 0x0c 的位置。

输入的16字节刚好覆盖完ebp,接下来4字节将覆盖返回地址。结合题目的各种暗示也能想到,这里应该返回到为调用的 function1,其地址 0x40223D 按小端序对应 ="@,刚好补齐19字节。
完整的调用流如下:
main
--function2 //encrypt-and-check
----function5 // RC4
------function3 // RC4 KSA
------function4 // RC4 PRGA
--function0
----(ret2)function1 // sub index
RC4解密,得到第一部分flag: We1com3ToReWorld="@
第二部分只需简单分析下 function1,逐字符与索引相减,写出逆运算求解:
data=[0x41,0x6D,0x62,0x4D,0x53,0x49,0x4E,0x29,0x28]
for i in range(len(data)):
data[i]+=i
print(bytes(data))
#b'AndPWNT00'
mineswepper#
sub_1277 对输入的字节重新编码,经过分析是通过 sub_122B 实现换表hex

abcdef0123456789
后面 sub_1432 是变种扫雷,给出每格以自身为中心3x3的雷数,用编码后的输入布雷。
感觉和算法题有点像,写一个z3脚本
from z3 import *
import hashlib
data = [
0x03, 0x04, 0xFF, 0xFF, 0xFF, 0x05, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x04, 0xFF, 0xFF, 0xFF,
0xFF, 0x02, 0xFF, 0xFF, 0x04, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x04, 0x06, 0x06, 0xFF, 0xFF, 0xFF,
0xFF, 0x06, 0x05, 0x06, 0x04, 0xFF, 0x05, 0xFF, 0x04, 0x07, 0xFF, 0x08, 0xFF, 0x06, 0xFF, 0xFF,
0x06, 0x06, 0x05, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x03, 0xFF, 0x03, 0xFF, 0x05, 0x06, 0x06,
0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x05, 0x04, 0x05, 0x07, 0x06, 0xFF, 0xFF, 0x04, 0xFF, 0x02, 0x01,
0xFF, 0xFF, 0xFF, 0x03, 0x04, 0xFF, 0xFF, 0x05, 0x04, 0x03, 0xFF, 0xFF, 0x07, 0x04, 0x03, 0xFF,
0xFF, 0x01, 0x01, 0xFF, 0xFF, 0x04, 0x03, 0xFF, 0x02, 0xFF, 0x04, 0x03, 0xFF, 0xFF, 0x02, 0xFF,
0x05, 0x04, 0xFF, 0xFF, 0x02, 0x02, 0xFF, 0xFF, 0x04, 0xFF, 0x04, 0xFF, 0x03, 0x05, 0x06, 0xFF,
0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0xFF, 0x01, 0x04, 0xFF, 0xFF, 0x07, 0x05, 0xFF,
0xFF, 0x03, 0x03, 0x02, 0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0x05, 0x07, 0xFF, 0x03, 0x02, 0x04, 0x04,
0xFF, 0x07, 0x05, 0x04, 0x03, 0xFF, 0xFF, 0x04, 0xFF, 0x02, 0x04, 0x05, 0xFF, 0xFF, 0x06, 0x05,
0x04, 0xFF, 0x02, 0xFF, 0xFF, 0x07, 0x04, 0xFF, 0xFF, 0x03, 0xFF, 0x04, 0x04, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x03, 0x02, 0x02, 0xFF, 0xFF, 0x02, 0x04, 0x03, 0x05, 0xFF, 0xFF,
0x05, 0xFF, 0x04, 0xFF, 0x06, 0xFF, 0xFF, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x03, 0xFF, 0x04,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x06, 0xFF, 0x06, 0x06, 0xFF, 0x07, 0x06, 0x04, 0xFF, 0x04, 0x03,
0xFF, 0x04, 0x03, 0x05, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x06, 0x07, 0xFF,
0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x05, 0xFF, 0x05, 0xFF, 0xFF, 0x06, 0x07, 0x07, 0xFF,
0x05, 0x06, 0x06, 0xFF, 0xFF, 0x02, 0x04, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x06, 0xFF, 0xFF,
0x07, 0x07, 0x06, 0xFF, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0x03, 0x05, 0xFF, 0x07, 0xFF,
0x05, 0xFF, 0x06, 0xFF, 0x05, 0xFF, 0xFF, 0x07, 0x08, 0xFF, 0xFF, 0x03, 0xFF, 0x03, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x06, 0x05, 0x03, 0xFF, 0x04,
0x05, 0x05, 0x03, 0xFF, 0xFF, 0x06, 0x05, 0x05, 0x06, 0xFF, 0x06, 0x05, 0x02, 0x04, 0x03, 0x04,
0xFF, 0xFF, 0x03, 0x04, 0x04, 0x06, 0x05, 0xFF, 0x03, 0xFF, 0x05, 0x05, 0x05, 0xFF, 0xFF, 0x05,
0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0x04, 0xFF, 0x07, 0x07, 0x08, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0x05,
0xFF, 0xFF, 0xFF, 0x04, 0xFF, 0x03, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x05, 0x03]
minemap = [0 for count in range(400)]
s = Solver()
for i in range(20):
for j in range(20):
minemap[20*i+j] = Int("x{:0>2d}_{:0>2d}".format(i,j))
s.add(minemap[20*i+j] >= 0)
s.add(minemap[20*i+j] <= 1)
def getElement(i,j):
if i>=0 and j>=0 and i<=19 and j<=19:
return minemap[20*i+j]
else:
return 0
def addEq(i,j):
eq = []
for x in range(-1,2,1):
for y in range(-1,2,1):
eq.append(getElement(i+x,y+j))
return sum(eq)
for i in range(20):
for j in range(20):
num = data[20*i+j]
if num != 0xFF:
s.add(addEq(i,j) == num)
if s.check() == sat:
byte_map = []
result = s.model()
for count in range(400):
minemap[count] = result[minemap[count]].as_binary_string()
for i in range(0,400,8):
byte_str = "".join(minemap[i:i+8])[::-1]
byte = int(byte_str,2)
byte_map.append(hex(byte)[2:].zfill(2))
hex_table = "0123456789abcdef"
new_table = "abcdef0123456789"
trans = str.maketrans(hex_table,new_table)
flag_input = "".join(byte_map)
flag_input = flag_input.translate(trans)
flag = hashlib.md5(flag_input.encode()).hexdigest()
print(flag_input)
print("SUCTF{" + flag + "}")
