简体   繁体   English

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

[英]Z3 Equation Solver - Bitmask Operation

After reverse engineering a program, I found the constraints. 在对程序进行逆向工程之后,我发现了约束。

I have to find two unsigned numbers such that: 我必须找到两个这样的无符号数字:

x + y = 0xC0ED91BD

and

x * y = Z

In the original program, the multiplication of the numbers is performed using imul instruction. 在原始程序中,使用imul指令执行数字的乘法。

Z should be such that when only the lower 32-bits of Z are checked, it should be less than 60. Z应该使得仅检查Z的低32位时,它应该小于60。

Z & 0x00000000ffffffff < 60

However, when I add the second equation as a constraint, z3 gives me an error. 但是,当我将第二个方程式添加为约束时,z3给我一个错误。

Here's my code: 这是我的代码:

#! /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]))

Updated: 更新:

Here is the code based on the recommended solution: 这是基于推荐解决方案的代码:

#! /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()

The binary is 64-bit. 二进制是64位。

However, the multiplication operation is performed using 32-bit integers as shown below: 但是,乘法运算是使用32位整数执行的,如下所示:

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

So if eax = 0x425a95e5 and edx = 0x7e92fbd8 所以如果eax = 0x425a95e5和edx = 0x7e92fbd8

Then after multiplication using imul instruction, eax will store: 0x00000038. 然后,使用imul指令相乘后,eax将存储:0x00000038。

Both, the Carry Flag and Overflow Flag bits in the EFLAGS register will be set after it. 之后,EFLAGS寄存器中的进位标志位和溢出标志位都将被置1。

The issue here is that you have declared x and y to be arbitrarily wide integers, as opposed to bit-vectors of a fixed length. 这里的问题是,您已将xy声明为任意宽的整数,而不是固定长度的位向量。 Simply change your declarations to match what the underlying bit-size should be. 只需更改您的声明以匹配基础位大小即可。 Assuming you want your arithmetic to be done in 32 bits, you'd say: 假设您希望算术运算以32位完成,您会说:

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

instead. 代替。 You should also declare result similarly: 您还应该类似地声明result

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

Once you make these changes, your program should work just fine. 进行这些更改后,您的程序应该可以正常工作。

Note that in this case masking with 0x00000000ffffffff isn't really necessary; 请注意,在这种情况下,使用0x00000000ffffffff掩膜并不是必须的。 since the numbers are already 32-bits wide. 因为数字已经是32位宽。 You only need to keep it if your x and y are larger; 如果xy较大,则只需要保留它; say 64 bits. 说64位。

With the above changes, I get the following output when I run your program and call it with 0xC0ED91BD : 经过以上更改,运行程序并使用0xC0ED91BD调用时,将得到以下输出:

[y = 2123561944, x = 1113232869]
[y = 1440310864, x = 1796483949]
[y = 1171875408, x = 2064919405]
... many other lines ..

This might look confusing, as the numbers seem to be larger than what you think they should be. 这看起来有些混乱,因为数字似乎比您想象的要大。 But remember that arithmetic over bitvectors is done modulo 2^n where n is the bit-size, so the results are actually correct: 但是请记住,对位向量进行算术运算是对2^n模,其中n是位大小,因此结果实际上是正确的:

>>> 2123561944 + 1113232869 % 2**32 == 0xC0ED91BD
True
>>> 2123561944 * 1113232869 % 2**32 < 60
True

etc. 等等

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM