用z3py解决裂缝

时间:2016-10-06 10:28:50

标签: z3py

我想用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()

现在,我有一些问题:

  • s.check()说'sat'所以我至少有一个解决方案?
  • 有更好的方法来定义数组吗?
  • 有没有办法直接使用这些字符?
  • 如何在解决方案后只获得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]

这似乎与约束相矛盾(??)我做错了什么,但在哪里?

由于

1 个答案:

答案 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升级到最新版本,以便工作。