Python_Z3学习
文章目录
- Python_Z3学习
- 0、简介
- 1、安装
- 2、整型(Int)方程求解
- 3、有理数(Real)型解方程求解
- 4、位向量(BitVec)求解(二进制位运算求解)
- 5、实际ctf中的位运算求解
- 6、z3(python)如何获取求解结果/表达式中的值
0、简介
利用python的Z3库可以进行约束求解,即解任何方程(只要有解),常用的包括整数求解、有理数求解、位向量求解(二进制位运算求解)。
1、安装
pip install z3_solver
注意不是安装z3,是z3_solver,两个不一样。
2、整型(Int)方程求解
网上贴的代码,我标注释
from z3 import *
#只定义一个int整形
n = Int('n')
#同时定义多个int整形。
a, s, d = Ints('a s d')#1、定义求解的数据类型为int整形
x = Solver()#2、初始化一个Solver类
x.add(a-d == 18)#3、对于数据进行约束、即写方程
x.add(a+s == 12)
x.add(s-d == 20)
check = x.check()#4、检测是否有解(有解sat、无解unsat)
print(check)
model = x.model()#5、取出所有结果,一个ModelRef类,
print(model)
#输出:
# sat
# [a = 5, d = -13, s = 7]
3、有理数(Real)型解方程求解
网上贴的代码,我标注释
from z3 import *
#只定义一个Real时
m = Real(m)
#同时定义多个Real时
x,y = Reals('x y')#1、定义求解的数据类型为real有理数
s = Solver()#2、初始化一个Solver类
s.add(x**2 + y**2 == 3)#3、对于数据进行约束、即写方程
s.add(x**3 == 2)
check = s.check()#4、检测是否有解(有解sat、无解unsat)
print(check)
model = s.model()#5、取出所有结果,一个ModelRef类,
print(model)
#输出:
# sat
# [y = -1.1885280594?, x = 1.2599210498?]
4、位向量(BitVec)求解(二进制位运算求解)
网上贴的代码,我标注释
from z3 import *
#只定义一个位向量时
m = BitVec('m',8)#8代表初始化位向量的bit位数,8位,即1个字节
#同时定义多个位向量时
x, y, z = BitVecs('x y z', 8)#1、定义求解的数据类型为real有理数
s = Solver()#2、初始化一个Solver类
s.add(x ^ y & z == 12)#3、对于数据进行约束、即写方程
s.add(y & z >> 3 == 3)
s.add(z ^ y == 4)
check = s.check()#4、检测是否有解(有解sat、无解unsat)
print(check)
model = s.model()#5、取出所有结果,一个ModelRef类,
print(model)
#输出:
# sat
# [z = 27, y = 31, x = 23]
5、实际ctf中的位运算求解
下述GACTF2021的逆向题目EazyRe中,一个小加密。
图片来源于文章:GACTF的几道逆向和MISC
同时这位师傅写的:一个有趣的加密小算法及其逆向。讲解也很不错
//开始:
a[1] = input;//四字节整数input
a1[1] = a1[1] ^ (a1[1] >> 13);
a1[1] = ((a1[1] << 9) & 0x78f39600) ^ a1[1];
a1[1] = ((a1[1] << 17) & 0x85d40000) ^ a1[1];
a1[1] = (a1[1] >> 19) ^ a1[1];
//后面给出了判断条件:
if(a[1]==0x26F8D100);
上述加密过程如果自己写代码逆的话,比较麻烦,这里就可以利用python的z3库进行约束求解。
下面给出z3求解input
代码。
from z3 import *
a,b,c,d,e= BitVecs('a b c d e',33)
s = Solver()
s.add(b == a ^ (a >> 13))
s.add(c == ((b << 9) & 0x78f39600) ^ b)
s.add(d == ((c << 17) & 0x85d40000) ^ c)
s.add(e == (d >> 19) ^ d)
s.add(e == 0x26F8D100)
print(s.check())
print(s.model())
输出结果
也可以换一种写法
from z3 import *
a,b,c,d,e= BitVecs('a b c d e',33)
s = Solver()
a ^= (a >> 13)
a ^= ((a << 9) & 0x78f39600)
a ^= ((a << 17) & 0x85d40000)
a ^= (a >> 19)
s.add(a == 0x26F8D100)
print(s.check())
print(s.model())
print(hex(4293442714))
输出结果
6、z3(python)如何获取求解结果/表达式中的值
ocs.microsoft.com/zh-cn/search/?scope=Desktop&terms=WinMain