一、问题产生的原因
之前打比赛的时候尝试angr强力求解tea加密,发现跑不出来,以为是angr编写有误,赛后直接尝试使用z3解tea,发现z3一直处于运行状态,他也不报unsat无解,就搁哪一直运行
我感觉可能是z3的速度受到了某种逻辑运算的限制
遂来研究一下到底是什么影响了z3的速度
二、浅浅的实验一下
tea中的逻辑运算有: >> , << , ^ , & , 常规的加减乘除
测试代码如下:
# from ctypes import *
# 实验原因,使用 & 0xffffffff 代替使用 ctypes
def encrypt(v, k):
v0, v1 = v[0], v[1]
delta = 0x9e3779b9
k0, k1, k2, k3 = k[0], k[1], k[2], k[3]
total = 0
for i in range(4):
total += delta
total = total & 0xffffffff
v0 += ((((v1<<4)&0xffffffff) + k0)&0xffffffff) ^ ((v1 + total)&0xffffffff) ^ (((v1>>5) + k1) & 0xffffffff)
v0 = v0 & 0xffffffff
v1 += ((((v0<<4)&0xffffffff) + k2)&0xffffffff) ^ ((v0 + total)&0xffffffff) ^ (((v0>>5) + k3) & 0xffffffff)
v1 = v1 & 0xffffffff
return v0, v1
def decrypt(v, k):
v0, v1 = c_uint32(v[0]), c_uint32(v[1])
delta = 0x9e3779b9
k0, k1, k2, k3 = k[0], k[1], k[2], k[3]
total = c_uint32(delta * 32)
for i in range(32):
v1.value -= ((v0.value<<4) + k2) ^ (v0.value + total.value) ^ ((v0.value>>5) + k3)
v0.value -= ((v1.value<<4) + k0) ^ (v1.value + total.value) ^ ((v1.value>>5) + k1)
total.value -= delta
return v0.value, v1.value
# test
if __name__ == "__main__":
# 待加密的明文,两个32位整型,即64bit的明文数据
value = [0x12345678, 0x78563412]
# 四个key,每个是32bit,即密钥长度为128bit
key = [0x1, 0x2, 0x3, 0x4]
print("Data is : ", hex(value[0]), hex(value[1]))
res = encrypt(value, key)
print("Encrypted data is : ", hex(res[0]), hex(res[1]))
res = decrypt(res, key)
print("Decrypted data is : ", hex(res[0]), hex(res[1]))
from z3 import *
import time
def encrypt(v, k):
v0, v1 = v[0], v[1]
delta = 0x9e3779b9
k0, k1, k2, k3 = k[0], k[1], k[2], k[3]
total = 0
for i in range(4):
total += delta
total = total & 0xffffffff
v0 += ((((v1<<4)&0xffffffff) + k0)&0xffffffff) ^ ((v1 + total)&0xffffffff) ^ (((LShR(v1,5)) + k1) & 0xffffffff)
v0 = v0 & 0xffffffff
v1 += ((((v0<<4)&0xffffffff) + k2)&0xffffffff) ^ ((v0 + total)&0xffffffff) ^ (((LShR(v0,5)) + k3) & 0xffffffff)
v1 = v1 & 0xffffffff
return v0, v1
# test
if __name__ == "__main__":
# 待加密的明文,两个32位整型,即64bit的明文数据
value = [BitVec('v[%d]' % i, 32) for i in range(2)]
# 四个key,每个是32bit,即密钥长度为128bit
key = [0x1, 0x2, 0x3, 0x4]
res = encrypt(value, key)
ti = time.time()
x = Solver()
x.add(res[0] == 0xa078b305)
x.add(res[1] == 0xb99977fd)
print(x.check())
print(x.model())
ti = time.time() - ti
print(ti)
实验发现,当循环取两重循环即以内的时候,z3会将tea加密其秒解,但当循环数等于三的时候 ,用时: 110.46944308280945 s.. 当循环数等于四时,用时: 1067.981635093689s 一千多秒,很夸张的...
猜测,可能是 & ffffffff 带来的问题
尝试把tea 加密中的 & 0xffffffff 去掉,再来实验
# from ctypes import *
def encrypt(v, k):
v0, v1 = v[0], v[1]
delta = 0x9e3779b9
k0, k1, k2, k3 = k[0], k[1], k[2], k[3]
total = 0
for i in range(4):
total += delta
total = total
v0 += ((((v1<<4)) + k0)) ^ ((v1 + total)) ^ (((v1>>5) + k1))
v1 += ((((v0<<4)) + k2)) ^ ((v0 + total)) ^ (((v0>>5) + k3) )
return v0, v1
def decrypt(v, k):
v0, v1 = c_uint32(v[0]), c_uint32(v[1])
delta = 0x9e3779b9
k0, k1, k2, k3 = k[0], k[1], k[2], k[3]
total = c_uint32(delta * 32)
for i in range(32):
v1.value -= ((v0.value<<4) + k2) ^ (v0.value + total.value) ^ ((v0.value>>5) + k3)
v0.value -= ((v1.value<<4) + k0) ^ (v1.value + total.value) ^ ((v1.value>>5) + k1)
total.value -= delta
return v0.value, v1.value
# test
if __name__ == "__main__":
# 待加密的明文,两个32位整型,即64bit的明文数据
value = [0x12345678, 0x78563412]
# 四个key,每个是32bit,即密钥长度为128bit
key = [0x1, 0x2, 0x3, 0x4]
print("Data is : ", hex(value[0]), hex(value[1]))
res = encrypt(value, key)
print("Encrypted data is : ", hex(res[0]), hex(res[1]))
res = decrypt(res, key)
print("Decrypted data is : ", hex(res[0]), hex(res[1]))
from z3 import *
import time
def encrypt(v, k):
v0, v1 = v[0], v[1]
delta = 0x9e3779b9
k0, k1, k2, k3 = k[0], k[1], k[2], k[3]
total = 0
for i in range(4):
total += delta
total = total
v0 += ((((v1<<4)) + k0)) ^ ((v1 + total)) ^ (((LShR(v1,5)) + k1) )
v1 += ((((v0<<4)) + k2)) ^ ((v0 + total)) ^ (((LShR(v0,5)) + k3) )
return v0, v1
# test
if __name__ == "__main__":
# 待加密的明文,两个32位整型,即64bit的明文数据
value = [BitVec('v[%d]' % i, 32) for i in range(2)]
# 四个key,每个是32bit,即密钥长度为128bit
key = [0x1, 0x2, 0x3, 0x4]
res = encrypt(value, key)
ti = time.time()
x = Solver()
x.add(res[0] == 0xa078b305)
x.add(res[1] == 0xb99977fd)
print(x.check())
print(x.model())
ti = time.time() - ti
print(ti)
循环为数1: 0.12765717506408691 循环数为2 : 1.7862217426300049 循环数为3: 471 s 寄
看来 &0xffffffff 是对z3求解影响不大
猜测,应该只能是堆叠的逻辑特别多的原因,这可能只能从z3源码、从其本质上找了....
而当我尝试把tea加密中的移位运算全换成加法 运算
3重循环用时 0.9733951091766357s 10重循环用时 6.563446521759033s 20重循环: 8.32275104522705s 32重循环: 14.628233671188354 s,可以发现,z3的效率极高
而但我们把tea加密中的 ^ 换掉,换成 + 3重循环用时: 3h+(运行三小时没出结果)...
三、最终结论
导致z3 求解爆炸的主要原因是 层层嵌套 ,而移位操作和其他逻辑操作产生的化学反应或许是影响z3求解速率的根本原因
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现