【问题标题】:z3 python z3.If always False (keygen)z3 python z3.If 总是 False (keygen)
【发布时间】:2018-10-06 19:47:29
【问题描述】:

我想用z3在python中生成一个keygen。这是验证功能:

def f(a):
    a = ord(a)
    if a <= 47 or a > 57:
        if a <= 64 or a > 98:
            exit()
        else:
            return a - 55
    else:
        return a - 48


def validate(key):
    if len(key) != 16:
        return False

    for k in key:
        if f(k)%2== 0:
            return False
    return True

我试图为此编写一个求解器

from z3 import *
solver = Solver()

def f_z3(a):
    return If(
        Or(a<=47, a>57),
        If(
            Or(a<=64, a>98),
            False, #  exit()???
            a -55
        ),
        a -48
    )

key = IntVector("key", 16)
for k in key:
    solver.add(f_z3(k)%2==0)

solver.check()
print(solver.model())

这是输出

[key__1 = 48,
 key__10 = 48,
 key__9 = 48,
 key__15 = 48,
 key__6 = 48,
 key__8 = 48,
 key__4 = 48,
 key__0 = 48,
 key__14 = 48,
 key__11 = 48,
 key__7 = 48,
 key__5 = 48,
 key__2 = 48,
 key__12 = 48,
 key__13 = 48,
 key__3 = 48]

它返回键“0000000000000000”,但 validate("0000000000000000") 返回 False。

我知道问题出在f_z3 函数中,我不知道如何在if 中表达exit(),我想要的东西总是False。但我只是返回 False。

知道如何解决这个问题吗?

【问题讨论】:

    标签: python reverse z3 key-generator


    【解决方案1】:

    您的代码有两个问题:

    1. 正如您所观察到的,将 exit 替换为 False 是不正确的 在f_z3 函数中。 (python版本在这里很奇怪 在某些情况下它会返回一个布尔值,然后直接死掉 在别人。但这无关紧要。)在所有其他分支中 你返回一个整数,在那个你返回一个 布尔值。在 z3 中,您总是希望返回相同的类型;一个整数。 所以选择一些会导致该案例产生False的东西 最终。因为稍后你要检查均匀度,任何奇怪的 号码会做。说1;所以修改它以产生1 而不是 Falseexit 被调用时。

    2. 验证时,如果结果为偶数,Python 代码将返回 False;所以你需要正确地断言。目前你正在做solver.add(f_z3(k)%2==0),而不是你应该要求模数不是偶数,就像这样:solver.add(f_z3(k)%2!=0)

    通过这两个修改,您将拥有以下代码:

    from z3 import *
    solver = Solver()
    
    def f_z3(a):
        return If(
            Or(a<=47, a>57),
            If(
                Or(a<=64, a>98),
                1,
                a -55
            ),
            a -48
        )
    
    key = IntVector("key", 16)
    for k in key:
        solver.add(f_z3(k)%2!=0)
    
    solver.check()
    print(solver.model())
    

    运行时,会产生:

    [key__1 = 49,
     key__10 = 49,
     key__9 = 49,
     key__15 = 49,
     key__6 = 49,
     key__8 = 49,
     key__4 = 49,
     key__0 = 49,
     key__14 = 49,
     key__11 = 49,
     key__7 = 49,
     key__12 = 49,
     key__5 = 49,
     key__2 = 49,
     key__13 = 49,
     key__3 = 49]
    

    这表明了有效的密钥"1111111111111111"

    【讨论】:

      【解决方案2】:

      对于我没有注意到的第二点,我更专注于第一点。 返回 1 并不能解决我的问题,我只是用一个更小的例子简化了真正的问题。我想要这个模式的通用解决方案。

      def f(x):
         if condition(x):
             exit()
         else:
             return g(x) # return something in relation with x
      

      我发现这个模式现在可以工作了

      def f_z3(x):
          global solver
          solver.add(Not(condition(x))
          return g(x)
      

      所以我的第一个函数会是这样的

      def f_z3(a):
          global solver
          # sins we have two nested condition we have to add an And
          solver.add(
              Not(
                  And(
                      Or(a<=47, a>57),
                      Or(a<=64, a>98)
                  )
              )
          )
          return If(
              Or(a<=47, a>57),
              a-55,
              a - 48
          )
      

      我仍在寻找更好的方法来解决这种模式,即告诉 If 条件始终为 False。

      【讨论】:

      • 这听起来像您在何时可以调用函数 f 上有“先决条件”。这表明调用者有责任强制执行该操作;所以约束应该移动到调用者。
      猜你喜欢
      • 1970-01-01
      • 2012-04-15
      • 1970-01-01
      • 2015-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-20
      • 1970-01-01
      相关资源
      最近更新 更多