z3 Solver (Python API)
Sep 19, 2024
»
CyKor-Seminar
z3 Solver의 가장 큰 장점은 역산 코드를 일일이 짤 필요 없이 방정식만 넣어 주면 solver가 알아서 그 답을 찾아 준다는 점입니다.
즉 문제 상황만 파악하면 역산 방법을 고민할 필요 없이 문제 상황만 Solver에 대입하면 그 해를 얻을 수 있는 Solver입니다. 그렇기에 Reversing에서 범용성 높게 사용되는 강력한 역산 툴입니다.
주로 python 모듈 형태로 사용합니다.
설치
pip install z3-solver
사용 방법
from z3 import *
위의 방식으로 import하여 사용합니다.
기본적으로 솔버와 변수를 선언하고, 조건(수식)을 solver에 추가한 뒤 마지막으로 솔버에게 답을 찾으라고 지시하는 방식으로 코드가 구성됩니다.
# Solver 생성
s = Solver()
# 미지수 선언
# 정수형
x = Int('x')
y = Int('y')
# 실수형
x = Real('x')
y = Real('y')
# bool형
x = Bool('x')
y = Bool('y')
# 비트벡터형
x = BitVec('x', 16) # 16비트 크기의 미지수 x 선언
y = BitVec('y', 50) # 50비트 크기의 미지수 y 선언
# 여러 개의 미지수를 리스트 형태로 동시에 선언하기
A = list()
for i in range(100):
A.append(BitVec('a_{}'.format(i), 64))
B = [Int('b_{}'.format(i)) for i in range(64)]
비트벡터가 리버싱에서 굉장히 유용하게 사용됩니다. BitVec로 선언된 미지수끼리 연산할 때는 선언된 비트 수가 동일해야 에러가 안 납니다.
# 생성한 Solver에 수식 추가하기
s.add()
s.append()
s.Insert()
# 괄호 안에 추가할 수식을 넣어 주면 됩니다.
# 그 외에 push pop으로 수식을 넣었다가 뺐다가 할 수 있습니다.
s.push()
s.pop()
# 일반적인 python 코드와 거의 유사하게 수식을 추가하면 됩니다.
x = Int('x')
y = Int('y')
s.add(x + y == 15)
s.add(x ^ y == 0xDEADBEEF)
s.add(Or(x == 15, y == 10))
# 답을 얻기 위해서는 먼저 check()를 이용해 해가 있는지 없는지 알아야 합니다.
s.check()
# 이렇게 Solver에 check() 메소드를 호출하면 sat(해 존재) 혹은 unsat(해 존재 안함)을 반환합니다.
# 아니면 unknown을 반환하기도 합니다.
# check()을 호출했을 때 sat을 반환하면 해를 얻을 수 있습니다.
s.model()
대충 이런 형태로 사용할 수 있습니다.
개별 미지수에 접근하고 싶으면
s.model()[<선언한 변수명>]
형태로 접근할 수 있으나,
자료형 조심합시다.
좀 이상하죠..?
이렇게 .as_long()
을 이용하여 int형으로 변환할 수 있습니다.
그냥 연립 방정식 정도 푸는 건가…?? 싶을 수 있는데 생각보다 많은 것들을 할 수 있습니다.
while s.check() == sat:
print(s.model())
s.add(Or(x != s.model()[x], y != s.model()[y]))
# 미지수가 많아 지면 위에처럼 쓰면 엄청 지저분해지니까, 아래처럼 쓸 수 있음
# 모든 해를 구해서 출력하는 코드
while solver.check() == sat:
model = solver.model()
flag = [model[inp[i]].as_long() for i in range(64)]
for i in flag:
print(hex(i)[-1], end='')
print()
ex = False # Oring을 덮어 씌울 거니까 초기값은 False가 되야 하겠죠
for idx, i in enumerate(flag):
ex = Or(ex, inp[idx] != i)
solver.add(ex)
이렇게 해를 빠짐 없이 모두 구하는 것도 가능하며
스도쿠를 푸는 것도 가능합니다.
문제 상황 → 수식으로 변환
이렇게 된다면 z3는 정말 좋은 툴이 됩니다.