z3学习笔记

这HGAME的re真让我长见识了,逆着逆着还出来个线性方程组。。

即刻学习z3!

安装

上次安的virtualenvwrapper真的太好用辣

有了上次angr的配置前提,这次直接source ~/.bashrc然后mkvirtualenv --python=$(which python3) z3 && pip install z3-solver,就在名为z3的虚拟环境内安装好z3-solver辣

(直接pip install的话大概率会和angr冲突,所以建议在虚拟环境下安装)

简单的例子

比如说下面这个东西

from z3 import *

x = Int('x')
y = Int('y')
solve(x + y == 4)

输出了[y = 0, x = 4],显然,这是在x和y均为整数的情况下,\(x+y=4\)的一组解

如果我们想要在y = 3的情况下的解呢?

from z3 import *

x = Int('x')
y = Int('y')
solve(y == 3, x + y == 4)

输出了[x = 1, y = 3]

如果条件比较多的话,可以考虑下面这种写法

from z3 import *
x = Int('x')
y = Int('y')
solver = Solver() # 建立约束器
solver.add(x > 3) # 添加约束条件
solver.add(y < 5)
solver.add(x + y == 4)

if solver.check()==sat: # 判断是否有解
	print (solver.model())
	
else:
	print ("OOps!")

另外我们注意到,即使是存在多解的情况,z3也只会给出其中一种解

z3的用法实在是太多了,那就就遇到一种用法写一种在这吧,以后自己也好翻回来复习

求解矩阵乘法

会了矩阵乘法就相当于会了线性方程组的解法,线性代数不能白学(

摸一道例题吧,看dalao博客是whctf的一个题

其中convert()将flag赋值给一个6x6的矩阵a,Transposition()将a的转置矩阵赋值给b,Multi()将a*b赋值给c,d就是我们的c矩阵的目标状态

from z3 import *
# 建立约束器
solver = Solver()
# flag长度先设置为36,包括尾部的9个1
flag = [Int('flag%d'%i) for i in range(36)]
# 保存flag的矩阵
a = [i for i in flag]
# 保存flag的转置矩阵
b = [i for i in range(36)]
# 保存a * b的矩阵
c = [0 for i in range(36)]
# 正确的flag的运算结果
d = [0x12027, 0x0F296, 0x0BF0E, 0x0D84C, 0x91D8, 0x297,
	0x0F296, 0x0D830, 0x0A326, 0x0B010, 0x7627, 0x230,
	0x0BF0E, 0x0A326, 0x8FEB, 0x879D, 0x70C3, 0x1BD,
	0x0D84C, 0x0B010, 0x879D, 0x0B00D, 0x6E4F, 0x1F7,
	0x91D8, 0x7627, 0x70C3, 0x6E4F, 0x9BDC, 0x15C,
	0x297, 0x230, 0x1BD, 0x1F7, 0x15C, 0x6]
# 获得a的转置矩阵
for i in range(6):
	for j in range(6):
		b[6 * j + i] = a[6 * i + j]
# 运算a * b
for i in range(6):
	for j in range(6):
		for k in range(6):
			c[6 * i + j] = c[6 * i + j] + a[6 * i + k] * b[6 * k + j]
		# 添加约束,正确flag的运算结果
		solver.add(c[6 * i + j] == d[6 * i + j])

# 添加约束,除了尾部,flag的字符一定在可见字符范围内
for i in range(6,36 - 10):
	solver.add(flag[i] >= 32)
	solver.add(flag[i] <= 127)
# 添加约束,由于flag有格式,前6位一定为whctf{
for i in range(6):
	solver.add(flag[i] == ord('whctf{'[i]))
# 添加约束,flag的尾部为9个1
for i in range(36 - 9,36):
	solver.add(flag[i] == 0x1)
# 添加约束,flag的最后一个肯定是}
solver.add(flag[-10] == ord('}'))

# 添加约束,A*A的转置结果矩阵中A(i,i)一定是平方和


# 这里一定要有,不check的话会报错
if solver.check() == sat:
	m = solver.model()
	s = []
	# 获得结果
	for i in range(36):
		s.append(m[flag[i]].as_long())
	# 输出flag
	print(bytes(s))
else:
	print('OOps!')

这exp还差个约束没补齐,下次补一下

posted @ 2022-01-21 19:30  iPlayForSG  阅读(224)  评论(0编辑  收藏  举报