Z3基础学习 (二) 基础语法
Z3基础学习 (二) 基础语法
一.设置变量
Int - 整数型
# 声明单个变量
x = Int('x')
# 声明多个变量
y,z = Ints('y z')
- | 运算需要初始化为Int变量
Real - 实数型
# 声明单个变量
x = Real('x')
# 声明多个变量
y,z = Reals('y z')
BitVec - 向量(位运算)
# 声明单个 16 位的变量
x = BitVec('x',16)
# 声明多个 16 位的变量
y,z = BitVecs('y z',16)
- 只有 BitVec 变量可以进行异或
python solver.add(BitVec('x',8)^BitVec('y',8)==5)
- BitVec 变量值之间可进行>或<或=或>=或<=的比较
BitVec('a',8)>=BitVec('b',8)
BitVec('a',8)<=BitVec('b',8)
BitVec('a',8)<=9 BitVec('a',8)==9
- BitVecVal 值之间不能进行>或<比较,只能转换成 python 认识的类型才可以比较
if BitVecVal(98,8)>BitVecVal(97,8)#错误,不是python类型
if BitVecVal(98,8)==98:
if BitVecVal(98,8).as_long()>97
if BitVecVal(98,8).as_long()>BitVecVal(97,8).as_long()
变量设置的类型可能会影响到最后求解的结果。可以先 check 一下看看有没有解,然后再判断是否需要切换变量的类型。
二.Solver 对象
实际做题时,约束条件肯定不会想上面例子这么少,所以需要实例化一个 Solver() 对象,方便我们添加更多的约束条件。
创建约束求解器:
solver = Solver()
三.添加约束条件
一行一个约束条件,这里的约束条件就是方程等式:
solver.add(x**2+y**2==74)
solver.add(x**5-y==z)
# [y = -7, x = 5, z = 3132]
z3 中不允许列表与列表之间添加==约束条件:
from z3 import *
prefix=[ord(each) for each in "flag{"]
plain_line=[Int('x%d' % i) for i in range(5)]
s=Solver()
z=0
#s.add(plain_line[z:z+5]==prefix) 列表==列表-->错误
s.add(plain_line[z]==prefix[0])
s.add(plain_line[z+1]==prefix[1])
s.add(plain_line[z+2]==prefix[2])
s.add(plain_line[z+3]==prefix[3])
s.add(plain_line[z+4]==prefix[4])
s.check()
print(s.model())
四.判断是否有解
if solver.check() == sat:
print("solver")
else:
print("no solver")
五.求解并输出
ans = solver.model()
print(ans)
六.限制结果为可见字符
通常如果是做题的话,解密出来很可能是 flag ,也就是 ascii 码,所以为了进一步约束范围可以给每一个变量都加上额外的一条约束,约束其结果只能在可见 ascii 码范围以内:
solver.add(x < 127)
solver.add(x >= 32)
七.快速添加变量
添加 50 个 Int 变量 s :
s=[Int('s%d' % i) for i in range(50)]
添加 50 个 Real 变量 s :
s=[Real('s%d' % i) for i in range(50)]
添加 50 个 16 位 BitVec 变量 s :
s=[BitVec ('s%d' % i,16) for i in range(50)]
在约束条件中用下标索引使用:
solver.add(s[18] * s[8] == 5)
solver.add(s[4] * s[11] == 0)
将结果按顺序打印出来:
这是使用列表管理变量的好处,如果不使用列表 print(answer) 输出的结果是无序的。
answer=solver.model()
#print(answer)
result="".join([str(answer[each]) for each in s])
print(result)