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中,一个小加密。

Python带约束最优化 python 约束求解_初始化

图片来源于文章: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())

输出结果

Python带约束最优化 python 约束求解_Python带约束最优化_02

也可以换一种写法

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))

输出结果

Python带约束最优化 python 约束求解_Real_03

6、z3(python)如何获取求解结果/表达式中的值

ocs.microsoft.com/zh-cn/search/?scope=Desktop&terms=WinMain