我想用Z3解决一个问题。 crackme非常庞大,但它可以简化为以下内容::
#! /usr/bin/python
import sys
T='Fguad2x-GP5_QqNi'
key=sys.argv[1]
if len(key) != 3:
print "Bad key length"
exit(1)
out=[]
for c in key:
out.append(T[ord(c)>>4 ])
out.append(T[ord(c) & 0xf])
if ''.join(out)=='--xPxN':
print "You win"
解决方案是“赢”。
我猜这种事情可以通过z3来解决。我从一个z3风格的crackme翻译所有逻辑开始:
#! /usr/bin/python
from z3 import *
#Preparing data
map_array='Fguad2x-GP5_QqNi'
T=Array('T',IntSort(),IntSort())
for i,j in enumerate(map_array):
T = Store(T, ord(j), i)
sol='--xPxN'
#We know input has 3 characters
a=BitVec('a',8)
b=BitVec('b',8)
c=BitVec('c',8)
#Ignite
s=Solver()
#String key is printable
s.add(BV2Int(a)>=65,BV2Int(a)<=122)
s.add(BV2Int(b)>=65,BV2Int(b)<=122)
s.add(BV2Int(c)>=65,BV2Int(c)<=122)
#Adding constraints
s.add(Select(T,BV2Int(a>>4))==ord(sol[0]))
s.add(Select(T,BV2Int(a&0xf))==ord(sol[1]))
s.add(Select(T,BV2Int(b>>4))==ord(sol[2]))
s.add(Select(T,BV2Int(b&0xf))==ord(sol[3]))
s.add(Select(T,BV2Int(c>>4))==ord(sol[4]))
s.add(Select(T,BV2Int(c&0xf))==ord(sol[5]))
#Verify solving
print s.check()
print s.model()
现在,我有一些问题:
如何在解决方案后只获得a,b和c? s.model()显示了一个非常奇怪的输出:
$ ./stovlfw.py
坐 [b = 1, a = 136, c = 0, T = [3 - > 78, 65 - &gt; 120, 2 - &gt; 80, 1 - &gt; 45, 0 - &gt; 45, 别的 - &gt; 45], k!0 = [3 - > 78, 65 - &gt; 120, 2 - &gt; 80, 1 - &gt; 45, 0 - &gt; 45, 别的 - &gt; 45]
这似乎与约束相矛盾(??)我做错了什么,但在哪里?
由于
答案 0 :(得分:0)
z3中的数组与C对应的行为不同。它们不应该用于模拟小的有限值集合。使用列表推导创建不同的变量通常效率更高。
这是我的替代方法。在z3中创建一个函数,允许您从字符串中选择第n个字符。
#! /usr/bin/python
from z3 import *
#Preparing data
nth = Function('nth', StringSort(), IntSort(), BitVecSort(8))
final = String('final')
sol='--xPxN'
#We know input has 3 characters
a=BitVec('a',8)
b=BitVec('b',8)
c=BitVec('c',8)
#Ignite
s=Solver()
#Adding constraints
for i,j in enumerate('Fguad2x-GP5_QqNi'):
s.add(nth(final,i)==ord(j))
s.add(nth(final,BV2Int(a>>4))==ord(sol[0]))
s.add(nth(final,BV2Int(a&0xf))==ord(sol[1]))
s.add(nth(final,BV2Int(b>>4))==ord(sol[2]))
s.add(nth(final,BV2Int(b&0xf))==ord(sol[3]))
s.add(nth(final,BV2Int(c>>4))==ord(sol[4]))
s.add(nth(final,BV2Int(c&0xf))==ord(sol[5]))
#String key is printable
s.add((a)>=65,(a)<=122)
s.add((b)>=65,(b)<=122)
s.add((c)>=65,(c)<=122)
#Verify solving Fguad2x-GP5_QqNi
print s.check()
print s.model()
print ''.join(chr(s.model()[i].as_long()) for i in [a,b,c])
s.model()
可用作dict来检索变量值。
PS:将z3升级到最新版本,以便工作。