Z3方程求解器-位掩码操作

时间:2019-01-18 16:32:30

标签: python z3 z3py

对程序进行反向工程后,我发现了约束。

我必须找到两个这样的无符号数字:

x + y = 0xC0ED91BD

x * y = Z

在原始程序中,数字的乘法是使用imul指令进行的。

Z应该使得仅检查Z的低32位时,它应该小于60。

Z & 0x00000000ffffffff < 60

但是,当我添加第二个方程作为约束时,z3给了我一个错误。

这是我的代码:

#! /usr/bin/python

from z3 import *
import sys

s = Solver()
result = int(sys.argv[1], 16)

x = Int('x')
y = Int('y')

s.add(x + y == result)
s.add(x > 0, y > 0)
s.add((x * y) & 0x00000000ffffffff < 60)

while s.check() == sat:
    print s.model()
    s.add(Or(x != s.model()[x], y != s.model()[y]))

已更新:

以下是基于推荐解决方案的代码:

#! /usr/bin/python

from z3 import *
import sys

s = Solver()
x = BitVec('x', 32)
y = BitVec('y', 32)

result = BitVecVal(int(sys.argv[1], 16), 32)

s.add(x + y == result)
s.add(x > 0, y > 0)
s.add(x * y < 10)

print s.check()
print s.model()

二进制文件是64位的。

但是,乘法运算是使用32位整数执行的,如下所示:

mov     edx, [rbp+var_14]
mov     eax, [rbp+var_10]
imul    eax, edx

因此,如果eax = 0x425a95e5和edx = 0x7e92fbd8

然后使用imul指令相乘后,eax将存储:0x00000038。

EFLAGS寄存器中的进位标志位和溢出标志位都将被置位。

1 个答案:

答案 0 :(得分:1)

这里的问题是,您已将* def json = { id: 1, priority: 1, compRound: { id: 1, comp_id: 89 } } * def compRound = { id: '#number' } * match json == { id: '#number', priority: '#number', compRound: '#(^compRound)' } x声明为任意宽的整数,而不是固定长度的位向量。只需更改您的声明以匹配基础位大小即可。假设您希望算术以32位完成,您会说:

y

相反。您还应该类似地声明x = BitVec('x', 32) y = BitVec('y', 32)

result

进行这些更改后,您的程序应该可以正常运行。

请注意,在这种情况下,实际上不需要使用result = BitVecVal(int(sys.argv[1], 16), 32) 进行屏蔽。因为数字已经是32位宽。仅当0x00000000ffffffffx较大时才需要保留它;说64位。

通过上述更改,运行程序并使用y进行调用时,将得到以下输出:

0xC0ED91BD

这看起来似乎令人困惑,因为数字似乎比您认为的要大。但是请记住,对位向量进行算术运算是对[y = 2123561944, x = 1113232869] [y = 1440310864, x = 1796483949] [y = 1171875408, x = 2064919405] ... many other lines .. 进行模运算,其中2^n是位大小,因此结果实际上是正确的:

n