[英]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. 这里的问题是,您已将
x
和y
声明为任意宽的整数,而不是固定长度的位向量。 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; 如果
x
和y
较大,则只需要保留它; 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.