# 使用z3约束器解决CTF中的题目

Z3是什么？Z3由微软开发的一套约束求解器，你可以简单的理解它是解方程的神器。在CTF题目中，我们经常遇到一些给定的条件，或是算法难以逆向、或是涉及到未知的数学技巧又或是爆破时间过长，而在我们学会使用z3后，一类问题便迎刃而解了。想了解更多关于z3知识的，这里有篇专栏：点我

>>> from z3 import *
>>> x = Int('x')
>>> y = Int('y')
>>> solve(x+y==4)
[y = 0, x = 4]

>>> solve(x==3,x+y==4)
[y = 1, x = 3]

>>> from z3 import *
>>> x = Real('x')
>>> y = Real('y')
>>> solve(x**2 + y**2 == 3, x**3 == 2)
[x = 1.2599210498?, y = -1.1885280594?]

OK，大概了解到它是干嘛的我们就开始看一道例题吧。二进制文件可以在这里下载。

  v1 = 0;
gets(flag);
for ( i = 0; i <= 35; ++i )
{
if ( !flag[i] )
{
flag[i] = 1;
++v1;
}
}
if ( v1 != 9 )
exit(0);
convert(a);
Transposition(a);
Multi(a, b);
for ( j = 0; j <= 5; ++j )
{
for ( k = 0; k <= 5; ++k )
{
if ( c[0][k + 6 * j] != d[0][k + 6 * j] )
exit(0);
}
}
printf("congratulations!you have gottern the flag!");

Transposition(a)是把a的转置矩阵赋值给b

Multi(a,b)是把a和b的乘积赋值给c

#coding:utf-8
'''
@DateTime: 	2017-11-28 10:19:29
@Version: 	1.0
@Author: 	Unname_Bao
'''
from z3 import *
import time
t1 = time.time()
#创建一个解决方案实例
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[i+6*j] = a[6*i+j]
#运算a*b
for i in range(6):
for j in range(6):
for k in range(6):
c[j+6*i] = c[j+6*i] + a[6*i+k]*b[6*k+j]
#添加约束，正确flag的运算结果
#添加约束，除了尾部，flag的字符一定在可见字符范围内
for i in range(6,36-10):
#添加约束，由于flag有格式，前6位一定为whctf{
for i in range(6):
#添加约束，flag的尾部为9个1
for i in range(36-9,36):
#添加约束，flag的最后一个肯定是}
#这里一定要有，不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('error')
t2 = time.time()
print(t2-t1)

D:\2017_WEB_Test\ulb_manager\backend\spider>python z3test.py
b'whctf{Y0u_ar3_g00d_a7_m4th}\x01\x01\x01\x01\x01\x01\x01\x01\x01'
4.042840003967285

05-26 3242
04-22
10-29
04-24
03-22 3392
06-08
10-22 1162
03-28 4502