https://buuoj.cn/challenges#[GXYCTF2019]simple%20CPP
64 c 艹
程序比较复杂,需要使用动调看程序的逻辑(终于来了,结构分析)
GXY{114514}
动态调试进去看不出来具体内容的时候要进入汇编层面看看才行,在反编译界面看准是哪个寄存器,在汇编界面进入寄存器指的值,Ctrl+E
导出
整个程序的逻辑是先把输入和一个数组循环异或,再把异或后的数据存在 i64 数组里面(大小为 4,大端的方式去存),通过 5 个方程验证数组里的数字是否符合要求
这种一般能 angr 就秒了,奈何实在 Win 下,只能用 z3 一点点往回推了
from z3 import *
data_48 = [0x69, 0x5F, 0x77, 0x69, 0x6C, 0x6C, 0x5F, 0x63, 0x68, 0x65,
0x63, 0x6B, 0x5F, 0x69, 0x73, 0x5F, 0x64, 0x65, 0x62, 0x75,
0x67, 0x5F, 0x6F, 0x72, 0x5F, 0x6E, 0x6F, 0x74, 0x00]
d0, d1, d2, d3 = BitVecs('d0 d1 d2 d3', 64)
s = Solver()
s.add(d2 & ~d0 == 1176889593874)
s.add(d2 & ~d1 & d0 | d2 & (d1 & d0 | d1 & ~d0 | ~(d1 | d0)) == 577031497978884115)
s.add(d2 & ~d0 | d1 & d0 | d2 & ~d1 | d0 & ~d1 == 4483974544037412639)
s.add(d3 == 842073600)
s.add(d2 & ~d0 | d1 & d0 | d1 & d2 == ~d0 & d2 | 864693332579200012)
# 用十六进制输出所有结果
while s.check() == sat:
m = s.model()
print(hex(m[d0].as_long()), hex(m[d1].as_long()), hex(m[d2].as_long()), hex(m[d3].as_long()))
s.add(Or(d0 != m[d0], d1 != m[d1], d2 != m[d2], d3 != m[d3]))
得到开始的 dump 为:
0x3e3a460533286f0d 0xc00020130082c0c 0x8020717153e3013 0x32310600
循环异或回去就行了
from z3 import *
data_48 = "i_will_check_is_debug_or_noi_wil"
d0, d1, d2, d3 = BitVecs('d0 d1 d2 d3', 64)
s = Solver()
s.add(d2 & ~d0 == 1176889593874)
s.add(d2 & ~d1 & d0 | d2 & (d1 & d0 | d1 & ~d0 | ~(d1 | d0)) == 577031497978884115)
s.add(d2 & ~d0 | d1 & d0 | d2 & ~d1 | d0 & ~d1 == 4483974544037412639)
s.add(d3 == 842073600)
s.add(d2 & ~d0 | d1 & d0 | d1 & d2 == ~d0 & d2 | 864693332579200012)
# 用十六进制输出所有结果
while s.check() == sat:
m = s.model()
print(hex(m[d0].as_long()), hex(m[d1].as_long()), hex(m[d2].as_long()), hex(m[d3].as_long()))
s.add(Or(d0 != m[d0], d1 != m[d1], d2 != m[d2], d3 != m[d3]))
# 0x3e3a460533286f0d 0xc00020130082c0c 0x8020717153e3013 0x000000032310600
# 大端
dump = [0x3e, 0x3a, 0x46, 0x05, 0x33, 0x28, 0x6f, 0x0d,
0xc, 0x00, 0x02, 0x01, 0x30, 0x08, 0x2c, 0x0c,
0x8, 0x02, 0x07, 0x17, 0x15, 0x3e, 0x30, 0x13,
0x32, 0x31, 0x06]
for i in range(len(dump)):
dump[i] ^= ord(data_48[i % 27])
print(''.join([chr(i) for i in dump]))
发现 dump1 部分是有很多个解的,在比赛的时候放出来是 e!P0or_a
We1l_D0ne!P0or_algebra_am_i