如何使用 Z3 有效简化 QF_BV 逻辑中的混淆公式?

逆向工程 去混淆
2021-06-26 22:17:07

我想知道是否有有效的方法来简化Microsoft Z3位向量上的算术公式表达式但是,首先,我想解释一下这个问题。让我们从一个例子开始:

x + y == (x ^ y) + 2 * (x & y)

这两个x + y(x ^ y) + 2 * (x & y)的,实际上,编码加入了位向量。当然,当在二进制程序中找到时,右手公式用于混淆逆向器。我尝试寻找工具和技术来简化混淆的公式并找到更简单的公式形式(左手)。

为此,我查看了 Z3 的 Python 界面,试图看看我能从中得到什么。因此,定义混淆公式是这样完成的:

>>> from z3 import *
>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> fun1 = (x ^ y) + 2 * (x & y)

现在,让我们尝试借助内置函数简化此函数simplify

>>> simplify((x ^ y) + 2 * (x & y))
(x ^ y) + 2*~(~x | ~y)

不是很令人信服......但是,让我们尝试证明与以下等价x + y

>>> prove((x ^ y) + 2 * (x & y) == x + y)
proved
>>> prove((x ^ y) + 2 * (x & y) == x - y)
counterexample
[y = 2164268032, x = 2139094080]

我添加了一个否定结果以表明也可以取消公式的资格。

因此,如果该simplify函数不是真正令人信服,仍然可以尝试以蛮力的方式将未知公式与一系列更简单和常用的公式一个接一个地进行比较。但是,这种方式对我来说似乎效率极低。我想我缺少一些更智能的算法来简化公式。

我想知道是否有一些现有的工具或众所周知的技术可以比蛮力方法更有效地执行。因此,如果有人对此有一些提示或评论,那将是非常受欢迎的。

1个回答

Z3 是 SMT 求解器。它的工作是决定用户传入的公式的可满足性,其中公式可能混合了 Z3 支持的各种理论的术语。巧合的是,为了通过生成一个比用户传入的“更简单”的公式来使自己的工作更容易,它实现了一个在技术上不是很复杂的简化器,主要由术语重写规则组成。

尽管用户可以对两个表达式的等价性提出疑问,但 Z3 的唯一参与将是求解公式。即 Z3 不会为您生成候选人。作为用户,您的工作是提供候选对象并询问 SMT 求解器的可满足性。

一般来说,综合功能是程序综合中的一项具有挑战性的任务。这些查询自然是在二阶逻辑中提出的,但现代 SMT 求解器仅支持一阶逻辑的限制。为了避免这个问题,一些已发表的工作采取了提前排除大多数候选者的方法,从而使等价查询的数量保持在较小的范围内。例如,参见这篇论文这篇论文另一种方法是指定一个模板,描述允许候选函数的外观;一个简单的例子是这篇论文这些方法使公式保持一阶逻辑,甚至不含量词。

一般来说,你应该研究程序综合。