国赛上逆向有道题目要算 37 元一次方程,肯定不能用手算。解决方法是用 python Z3 库,这个库可以帮助我们解决方程的计算问题。
Z3 在工业应用中实际上常见于软件验证、程序分析等。然而由于功能实在强大,也被用于很多其他领域。CTF 领域来说,能够用约束求解器搞定的问题常见于密码题、二进制逆向、符号执行、Fuzzing 模糊测试等。此外,著名的二进制分析框架 angr 也内置了一个修改版的 Z3。
安装
简单使用
1 2 3 4 5 6
| from z3 import *
x = Int('x') y = Int('y') solve(x > 2, y < 10, x + 2*y == 7)
|
做题约束条件肯定不会这么少,所以需要实例化一个 Solver()
对象,方便我们添加更多的约束条件。
进阶使用
Solver 对象
创建约束求解器:
设置变量
Int - 整数型
1 2 3 4
| x = Int('x')
y,z = Ints('y z')
|
Real - 实数型
1 2 3 4
| x = Real('x')
y,z = Reals('y z')
|
BitVec - 向量(位与运算)
1 2 3 4
| x = BitVec('x')
y,z = BitVecs('y z')
|
变量设置的类型可能会影响到最后求解的结果。可以先 check 一下看看有没有解,然后再判断是否需要切换变量的类型。
添加约束条件
一行一个约束条件,这里的约束条件就是方程等式:
1 2 3
| solver.add(x**2+y**2==74) solver.add(x**5-y==z)
|
判断是否有解
1 2 3 4
| if solver.check() == sat: print("solver") else: print("no solver")
|
求解并输出
1 2
| ans = solver.model() print(ans)
|
额外补充
通常如果是做题的话,解密出来很可能是 flag ,也就是 ascii 码,所以为了进一步确定答案可以给每一个变量都加上额外的一条约束,约束其结果只能在可见 ascii 码范围以内:
1 2
| solver.add(x < 127) solver.add(x >= 32)
|
练习例题
参考文章