I am trying to find out the password of a keygen algorithm hidden in a binary. So, I extracted the formula from the assembly and translated (correctly, hopefully) in a small Python script to solve it:
#!/usr/bin/env python
from z3 import *
# Password initialization
pwd = BitVecs('pwd0 pwd1 pwd2 pwd3 pwd4 pwd5', 8)
# Internal states
state = BitVecs('state0 state1 state2 state3 state4 state5 state6', 32)
# Building the formula
state[0] = (pwd[3] ^ 0x1337) + 0x5eeded
for i in range(6):
state[i+1] = (ZeroExt(24, pwd[i]) ^ state[i]) % 0xcafe
# Solving the formula under constraint
solve(state[6] == 0xbad1dea)
Unfortunately, the ZeroExt(n,a) seems to produce the following error message:
Traceback (most recent call last):
File "./alt.py", line 13, in <module>
state[i+1] = (ZeroExt(24, pwd[i]) ^ state[i]) % 0xcafe
File "/usr/lib/python2.7/dist-packages/z3.py", line 3115, in __xor__
return BitVecRef(Z3_mk_bvxor(self.ctx_ref(), a.as_ast(), b.as_ast()), self.ctx)
File "/usr/lib/python2.7/dist-packages/z3core.py", line 1743, in Z3_mk_bvxor
raise Z3Exception(lib().Z3_get_error_msg_ex(a0, err))
z3types.Z3Exception: Argument (bvadd (bvxor pwd3 #x37) #xed) at position 1 does not match declaration (declare-fun bvxor ((_ BitVec 32) (_ BitVec 32)) (_ BitVec 32))
What did I do wrong and how to workaround this problem ?
NOTE: I changed the constants of the challenge to avoid to be easily found by searching for it (no cheating!). So, this problem might have no satisfiable solution...
It doesn't matter that you initialize the state vector to be 32-bits Z3 expressions. Once you overwrite state[0] to be the expression you supply, it is not 32 bits. It is instead just 8 bits. Also your bit-vector constants are truncated to 8 bits because of the bit-width of pwd[3].
So, the effect of:
state[0] = (pwd[3] ^ 0x1337) + 0x5eeded
is that state[0] contains a bit-vector that has size 8.
Then when you take the xor of state[0] and (ZeroExt(24, pwd[0]) you get the type mismatch.
A fix is to zero-extend pwd[3] in the first occurrence.
Related
Algorithm:
if BitVecA > 0
BitVecB = Concat(BitVecA, BitVecB)
I want to Concat two conditional bitvec and with no else condition by using If
I want to using
BitVecB = Contact(BitVecA, If(BitVecA>0, BitVecA, EmptyBitVec )),
but len of BitVec cannot be zero
It isn't clear what your question is. But if you look at https://smtlib.cs.uiowa.edu/theories-FixedSizeBitVectors.shtml you'll see that SMTLib only allows bit-vectors that have strictly positive lengths. (i.e., zero-length bitvectors are not part of the logic.)
So, if you need to reason with 0-length bit vectors, you'll have to write your code to handle it outside of the SMTLib fragment; i.e., in your wrapper code. But without knowing what your context is, hard to answer in any further detail.
Can I save the constraints I created for a z3 solver and later reload them to continue looking for more solutions?
I have learned there is the SMT-LIB2 format for such things and that z3 and z3py have an API for saving and loading in that format. Unfortunately I cannot make it work.
Here's my example program which pointlessly saves and reloads:
import z3
filename = 'z3test.smt'
# Make a solver with some arbitrary useless constraint
solver = z3.Solver()
solver.add(True)
# Save to file
smt2 = solver.sexpr()
with open(filename, mode='w', encoding='ascii') as f: # overwrite
f.write(smt2)
f.close()
# Load from file
solver.reset()
solver.from_file(filename)
It fails with:
Exception has occurred: ctypes.ArgumentError
argument 3: <class 'TypeError'>: wrong type
File "C:\Users\Marian Aldenhövel\Desktop\FridgeIQ\z3\z3-4.8.4.d6df51951f4c-x64-win\bin\python\z3\z3core.py", line 3449, in Z3_solver_from_file
_elems.f(a0, a1, _to_ascii(a2))
File "C:\Users\Marian Aldenhövel\Desktop\FridgeIQ\z3\z3-4.8.4.d6df51951f4c-x64-win\bin\python\z3\z3.py", line 6670, in from_file
_handle_parse_error(e, self.ctx)
File "C:\Users\Marian Aldenhövel\Desktop\FridgeIQ\src\z3test.py", line 17, in <module>
solver.from_file(filename)
Is this a problem with my understanding or my code? Can it be done like this? Are sexpr() and from_file() the right pair of API calls?
I am using z3 and z3py 4.8.4 from https://github.com/z3prover/z3/releases on Windows 10 64bit.
More detail if required:
I am playing with z3 in Python to find solutions for a large disection-puzzle.
To find all solutions I am calling solver.check(). When it returns a sat verdict I interpret the model as image of my puzzle solution. I then add a blocking clause ruling out that specific solution and call solver.check() again.
This works fine and I am delighted.
The runtime to find all solutions will be on the order of many days or until I get bored. I am concerned that my machine will not be running continuously for that long. It may crash, run out of power, or be rebooted for other reasons.
I can easily recreate the initial constraints which is the whole point of the program. But the blocking clauses are a runtime product and a function of how far we have gotten.
I thought I could save the state of the solver and if at runtime I find such a file restart by loading that with the blocking clauses intact and go on finding more solutions instead of having to start over.
Thank you for taking your time reading and thinking.
Marian
With z3 4.4.1 and z3 4.8.5, I would dump (and reload) the constraints in smt2 format as follows:
import z3
filename = "z3test.smt2"
x1 = z3.Real("x1")
x2 = z3.Real("x2")
solver = z3.Solver()
solver.add(x1 != x2)
#
# STORE
#
with open(filename, mode='w') as f:
f.write(solver.to_smt2())
#
# RELOAD
#
solver.reset()
constraints = z3.parse_smt2_file(filename, sorts={}, decls={})
solver.add(constraints)
print(solver)
output:
~$ python t.py
[And(x1 != x2, True)]
file z3test.smt2:
(set-info :status unknown)
(declare-fun x2 () Real)
(declare-fun x1 () Real)
(assert
(and (distinct x1 x2) true))
(check-sat)
I have no idea whether the API changed in the version you are using. Feedback is welcome.
As per my knowledge, since z3 doesn't recognize transcendental functions its throwing me an error while conversion using following code.
def convertor(f, status="unknown", name="benchmark", logic=""):
v = (Ast * 0)()
if isinstance(f, Solver):
a = f.assertions()
if len(a) == 0:
f = BoolVal(True)
else:
f = And(*a)
return Z3_benchmark_to_smtlib_string(f.ctx_ref(), name, logic, status, "", 0, v, f.as_ast())
pi, EI, kA , kB, N = Reals('pi EI kA kB N')
s= Solver()
s.add(pi == 3.1415926525)
s.add(EI == 175.2481)
s.add(kA>= 0)
s.add(kA<= 100)
s.add(kB>= 0)
s.add(kB<= 100)
s.add(N>= 100)
s.add(N<= 200)
please change the path of the input file "beamfinv3.bch", which can be found at: link
continue_read=False
input_file = open('/home/mani/downloads/new_z3/beamfinv3.bch', 'r')
for line in input_file:
if line.strip()=="Constraints":
continue_read=True
continue
if line.strip()=="end":
continue_read=False
if continue_read==True:
parts = line.split(';')
if (parts[0]!="end"):
#print parts[0]
s.add(eval(parts[0]))
input_file.close()
file=open('cyber.smt2','w')
result=convertor(s, logic="None")
file.write (result)
error:
File "<string>", line 1, in <module>
NameError: name 'sin' is not defined
Any way out? or help?
Thanks.
The core of this problem is that eval tries to execute a Python script, i.e., all functions that occur within parts[0] must have a corresponding Python function of the same name, which is not the case for the trigonometric functions (the are neither in the Python API nor the C API, the former being based on the latter). For now you could try to add those functions yourself, perhaps with an implementation based on parse_smt2_string, or perhaps by replacing the Python strings with SMT2 strings altogether.
Z3 can represent expressions containing trigonometric functions, but it will refuse to do so when the logic is set to something; see arith_decl_plugin. I don't know Python well enough, but it might have to be None instead of "".
While Z3 can represent these expressions, it's probably not very good at solving them. See comments on the limitations in Can Z3 handle sinusoidal and exponential functions, Z3 supports for nonlinear arithmetics, and Z3 Performance with Non-Linear Arithmetic.
The problem is pretty simple.
I assert following statement in Z3 using the C API interface.
(assert(>= (xA 1) (- (yB 0) period))))
Now Sometimes, I need to check what kind of assertions have been fed and the result in the SatSolver. I do this, by generating a text file by using ast_to_string() API. This API returns me above statement as -
(assert(>= (xA 1) (+ (yB 0) (* -1 period))))
When I feed this file to the Sat Solver it complains me with the error -
(error "ERROR: line 150 column 56: could not locate id -1.")
So then, I have to manually fix all -1 in the code and run the sat solver.
Is there any other way where I can avoid this?
Remember to set:
Z3_set_ast_print_mode(ctx,Z3_PRINT_SMTLIB2_COMPLIANT);
before using ast_to_string() in order that that output formulas comply with SMTLIB 2.0 format.
I looked for the name of a procedure, which applies a tree structure of procedures to a tree structure of data, yielding a tree structure of results - all three trees having the same structure.
Such a procedure might have the signature:
(map-tree data functree)
Its return value would be the result of elementwise application of functree's elements on the corresponding data elements.
Examples (assuming that the procedure is called map-tree):
Example 1:
(define *2 (lambda (x) (* 2 x)))
; and similar definitions for *3 and *5
(map-tree '(100 (10 1)) '(*2 (*3 *5)))
would yield the result (200 (30 5))
Example 2:
(map-tree '(((aa . ab) (bb . bc)) (cc . (cd . ce)))
'((car cdr) cadr))
yields the result ((aa bc) cd)
However I did not find such a function in the SLIB documentation, which I consulted.
Does such a procedure already exist?
If not, what would be a suitable name for the procedure, and how would you order its arguments?
I don't have a very good name for the function. I'm pasting my implementation below (I've called it map-traversing; others should suggest a better name). I've made the argument order mirror that of map itself.
(define (map-traversing func data)
(if (list? func)
(map map-traversing func data)
(func data)))
Using your sample data, we have:
(map-traversing `((,car ,cdr) ,cadr) '(((aa . ab) (bb . bc)) (cc cd . ce)))
The second sample requires SRFI 26. (Allows writing (cut * 2 <>) instead of (lambda (x) (* 2 x)).)
(map-traversing `(,(cut * 2 <>) (,(cut * 3 <>) ,(cut * 5 <>))) '(100 (10 1)))
The most important thing is that your functions must all be unquoted, unlike your example.
I found that with the follwing definition of map-traversing, you don't need to unquote the functions:
(define (map-traversing func data)
(if (list? func)
(map map-traversing func data)
(apply (eval func (interaction-environment)) (list data))))
Note: in my installed version of Guile, due to some reason, only (interaction-environment) does not raise the Unbound variable error. The other environments i.e. (scheme-report-environment 5) and (null-environment 5) raise this error.
Note 2: Subsequently, I found in [1] that for (scheme-report-environment 5) and (null-environment 5) to work, you need first to (use-modules (ice-9 r5rs))
[1]: http://www.mail-archive.com/bug-guile#gnu.org/msg04368.html 'Re: guile -c "(scheme-report-environment 5)" ==> ERROR: Unbound variable: scheme-report-environment'