Teilen Sie Ihre Hacking-Tricks, indem Sie PRs an dieHackTricks und HackTricks CloudGitHub-Repositories senden.
Grundlegend hilft uns dieses Tool, Werte für Variablen zu finden, die bestimmte Bedingungen erfüllen müssen, und das manuelle Berechnen dieser Werte wäre sehr lästig. Daher können Sie Z3 die Bedingungen angeben, die die Variablen erfüllen müssen, und es wird einige Werte finden (falls möglich).
#pip3 install z3-solverfrom z3 import*s =Solver()#The solver will be given the conditionsx =Bool("x")#Declare the symbos x, y and zy =Bool("y")z =Bool("z")# (x or y or !z) and ys.add(And(Or(x,y,Not(z)),y))s.check()#If response is "sat" then the model is satifable, if "unsat" something is wrongprint(s.model())#Print valid values to satisfy the model
Ganzzahlen/Vereinfachen/Reelle Zahlen
SMT-Lösungssysteme wie Z3 können nicht nur mit booleschen Ausdrücken umgehen, sondern auch mit ganzen Zahlen (Integers) und reellen Zahlen (Reals). Dies ermöglicht es uns, komplexe mathematische Probleme zu modellieren und zu lösen.
Ganzzahlen (Integers)
Z3 bietet eine Vielzahl von Funktionen und Operatoren, um mit ganzen Zahlen zu arbeiten. Wir können Ganzzahlen deklarieren, arithmetische Operationen durchführen und Bedingungen überprüfen. Hier sind einige Beispiele:
Deklaration einer ganzen Zahl: (declare-const x Int)
Addition: (assert (= x (+ 2 3)))
Subtraktion: (assert (= x (- 5 2)))
Multiplikation: (assert (= x (* 2 3)))
Division: (assert (= x (/ 10 2)))
Modulo: (assert (= x (mod 10 3)))
Vereinfachen (Simplify)
Z3 bietet auch eine Vereinfachungsfunktion, mit der wir komplexe Ausdrücke vereinfachen können. Dies kann nützlich sein, um redundante Teile zu entfernen und den Ausdruck übersichtlicher zu gestalten. Hier ist ein Beispiel:
Vereinfachen eines Ausdrucks: (simplify (+ 2 (* 3 4)))
Reelle Zahlen (Reals)
Z3 unterstützt auch reelle Zahlen und ermöglicht es uns, mit ihnen zu rechnen. Wir können reelle Zahlen deklarieren, arithmetische Operationen durchführen und Bedingungen überprüfen. Hier sind einige Beispiele:
Deklaration einer reellen Zahl: (declare-const y Real)
Addition: (assert (= y (+ 2.5 3.7)))
Subtraktion: (assert (= y (- 5.2 2.1)))
Multiplikation: (assert (= y (* 2.5 3.7)))
Division: (assert (= y (/ 10.5 2.5)))
Mit diesen Funktionen und Operatoren können wir komplexe mathematische Probleme modellieren und lösen, die sowohl Ganzzahlen als auch reelle Zahlen beinhalten.
from z3 import*x =Int('x')y =Int('y')#Simplify a "complex" ecuationprint(simplify(And(x +1>=3, x**2+ x**2+ y**2+2>=5)))#And(x >= 2, 2*x**2 + y**2 >= 3)#Note that Z3 is capable to treat irrational numbers (An irrational algebraic number is a root of a polynomial with integer coefficients. Internally, Z3 represents all these numbers precisely.)
#so you can get the decimals you need from the solutionr1 =Real('r1')r2 =Real('r2')#Solve the ecuationprint(solve(r1**2+ r2**2==3, r1**3==2))#Solve the ecuation with 30 decimalsset_option(precision=30)print(solve(r1**2+ r2**2==3, r1**3==2))
Modell ausgeben
To print the model, you can use the model method provided by the Z3 library. This method returns a string representation of the model, which can then be printed or used for further analysis.
print(s.model())
Um das Modell auszugeben, können Sie die model-Methode der Z3-Bibliothek verwenden. Diese Methode gibt eine Zeichenfolgenrepräsentation des Modells zurück, die dann gedruckt oder für weitere Analysen verwendet werden kann.
print(s.model())
from z3 import*x, y, z =Reals('x y z')s =Solver()s.add(x >1, y >1, x + y >3, z - x <10)s.check()m = s.model()print ("x = %s"% m[x])for d in m.decls():print("%s = %s"% (d.name(), m[d]))
Maschinenarithmetik
Moderne CPUs und gängige Programmiersprachen verwenden Arithmetik über Bit-Vektoren mit fester Größe. Maschinenarithmetik ist in Z3Py als Bit-Vektoren verfügbar.
from z3 import*x =BitVec('x', 16)#Bit vector variable "x" of length 16 bity =BitVec('y', 16)e =BitVecVal(10, 16)#Bit vector with value 10 of length 16bitsa =BitVecVal(-1, 16)b =BitVecVal(65535, 16)print(simplify(a == b))#This is True!a =BitVecVal(-1, 32)b =BitVecVal(65535, 32)print(simplify(a == b))#This is False
Vorzeichenbehaftete/unvorzeichenbehaftete Zahlen
Z3 bietet spezielle vorzeichenbehaftete Versionen von arithmetischen Operationen an, bei denen es einen Unterschied macht, ob der Bit-Vektor als vorzeichenbehaftet oder unvorzeichenbehaftet behandelt wird. In Z3Py entsprechen die Operatoren <, <=, >, >=, /, % und >> den vorzeichenbehafteten Versionen. Die entsprechenden unvorzeichenbehafteten Operatoren sind ULT, ULE, UGT, UGE, UDiv, URem und LShR.
from z3 import*# Create to bit-vectors of size 32x, y =BitVecs('x y', 32)solve(x + y ==2, x >0, y >0)# Bit-wise operators# & bit-wise and# | bit-wise or# ~ bit-wise notsolve(x & y ==~y)solve(x <0)# using unsigned version of <solve(ULT(x, 0))
Funktionen
Interpretierte Funktionen wie Arithmetik, bei denen die Funktion + eine feste Standardinterpretation hat (sie addiert zwei Zahlen). Uninterpretierte Funktionen und Konstanten sind maximal flexibel; sie erlauben jede Interpretation, die mit den Einschränkungen über die Funktion oder Konstante konsistent ist.
Beispiel: Wenn f zweimal auf x angewendet wird, ergibt dies wieder x, aber wenn f einmal auf x angewendet wird, ist es unterschiedlich von x.
from z3 import*x =Int('x')y =Int('y')f =Function('f', IntSort(), IntSort())s =Solver()s.add(f(f(x)) == x, f(x) == y, x != y)s.check()m = s.model()print("f(f(x)) =", m.evaluate(f(f(x))))print("f(x) =", m.evaluate(f(x)))print(m.evaluate(f(2)))s.add(f(x) ==4)#Find the value that generates 4 as responses.check()print(m.model())
Beispiele
Sudoku-Löser
from z3 import*defsolve_sudoku(grid):# Create a 9x9 grid of integer variables cells = [[Int(f"cell_{i}_{j}")for j inrange(9)] for i inrange(9)]# Add constraints for each cellfor i inrange(9):for j inrange(9):# Each cell must be between 1 and 9 cell = cells[i][j] cell_constraint =And(cell >=1, cell <=9)# Each row must contain distinct values row_constraint =Distinct(cells[i])# Each column must contain distinct values column_constraint =Distinct([cells[k][j] for k inrange(9)])# Each 3x3 subgrid must contain distinct values subgrid_constraint = Distinct([cells[m][n] for m in range(i - i % 3, i - i % 3 + 3) for n in range(j - j % 3, j - j % 3 + 3)])
# Combine all constraints for the cell cell_constraints = [cell_constraint, row_constraint, column_constraint, subgrid_constraint]# Add the constraints to the solver solver.add(cell_constraints)# Add the initial values to the solverfor i inrange(9):for j inrange(9):if grid[i][j] !=0: solver.add(cells[i][j] == grid[i][j])# Check if there is a solutionif solver.check()== sat:# Get the solution model = solver.model()# Print the solutionfor i inrange(9):for j inrange(9):print(model[cells[i][j]], end=" ")print()else:print("No solution found")# Example Sudoku gridgrid = [ [5,3,0,0,7,0,0,0,0], [6,0,0,1,9,5,0,0,0], [0,9,8,0,0,0,0,6,0], [8,0,0,0,6,0,0,0,3], [4,0,0,8,0,3,0,0,1], [7,0,0,0,2,0,0,0,6], [0,6,0,0,0,0,2,8,0], [0,0,0,4,1,9,0,0,5], [0,0,0,0,8,0,0,7,9]]# Create a solversolver =Solver()# Solve the Sudokusolve_sudoku(grid)
Dieser Code löst ein Sudoku-Rätsel mithilfe des Z3 SMT-Solvers. Der Code erstellt ein 9x9-Raster von Integer-Variablen und fügt für jede Zelle Einschränkungen hinzu. Jede Zelle muss einen Wert zwischen 1 und 9 haben. Jede Zeile, jede Spalte und jedes 3x3-Unterraster muss unterschiedliche Werte enthalten. Der Code fügt auch die anfänglichen Werte des Rätsels hinzu und überprüft, ob eine Lösung existiert. Wenn eine Lösung gefunden wird, wird sie ausgegeben. Andernfalls wird "Keine Lösung gefunden" angezeigt.
# 9x9 matrix of integer variablesX = [ [ Int("x_%s_%s"% (i+1, j+1))for j inrange(9) ]for i inrange(9) ]# each cell contains a value in {1, ..., 9}cells_c = [ And(1<= X[i][j], X[i][j] <=9)for i inrange(9)for j inrange(9) ]# each row contains a digit at most oncerows_c = [ Distinct(X[i])for i inrange(9) ]# each column contains a digit at most oncecols_c = [ Distinct([ X[i][j] for i inrange(9) ])for j inrange(9) ]# each 3x3 square contains a digit at most oncesq_c = [ Distinct([ X[3*i0 + i][3*j0 + j]for i inrange(3) for j inrange(3) ])for i0 inrange(3)for j0 inrange(3) ]sudoku_c = cells_c + rows_c + cols_c + sq_c# sudoku instance, we use '0' for empty cellsinstance = ((0,0,0,0,9,4,0,3,0),(0,0,0,5,1,0,0,0,7),(0,8,9,0,0,0,0,4,0),(0,0,0,0,0,0,2,0,8),(0,6,0,2,0,1,0,5,0),(1,0,2,0,0,0,0,0,0),(0,7,0,0,0,0,5,2,0),(9,0,0,0,6,5,0,0,0),(0,4,0,9,7,0,0,0,0))instance_c = [ If(instance[i][j] ==0,True,X[i][j] == instance[i][j])for i inrange(9)for j inrange(9) ]s =Solver()s.add(sudoku_c + instance_c)if s.check()== sat:m = s.model()r = [ [ m.evaluate(X[i][j])for j inrange(9) ]for i inrange(9) ]print_matrix(r)else:print"failed to solve"