
스트라이드 구간 분석을 통해 x86-64 바이너리 루프를 폐쇄형 SMT 제약 조건으로 변환하여 O(1) 기호 실행과 crackme 키 복구를 가능하게 합니다.
x86_64 바이너리 분석을 위한 고성능 $O(1)$ SMT 루프 리프팅 및 Strided Interval 도메인
전통적인 Symbolic Execution 및 DBI(Dynamic Binary Instrumentation) 엔진(angr, Triton, KLEE 등)은 악명 높은 **경로 및 루프 폭발 문제(Path & Loop Explosion Problem)**를 겪습니다. 루프를 만[...]
Strilight는 루프를 Strided Interval 도메인 내의 **폐쇄형 대수 점화식(closed-form algebraic recurrences)**으로 취급하여 이 문제를 근본적으로 해결합니다:
$$\vec{\mathbf{R}}(N) = \vec{\mathbf{R}}_0 + \vec{\boldsymbol{\Delta}} \cdot N$$
$N$번의 반복을 시뮬레이션하는 대신, Strilight는 반복 실행 트레이스를 계층적 LoopBlock 구조로 압축하고, 추상 아핀(affine) 및 다환(polycyclic) 단계를 평가한 다음, 루프를 [...]
graph LR
A[Raw Machine Code / Trace] --> B[sl.disassemble & sl.compress]
B --> C[sl.evaluate / LoopEvaluator]
C -->|Strided Interval Domain| D[LoopSummary + Invariant Contract]
D -->|O1 Closed-Form Lifting| E["Z3 SMT-LIB2 Solver"]
E --> F[Instant Solution in less than 100 ms]
LoopBlock 그래프로 압축합니다.Strilight는 독립적인 모듈형 프로파일로 패키징되어 있어, 파이프라인에 필요한 구성 요소만 포함할 수 있습니다:
# Profile 1: Core Engine (Pure Compressor + Embedded Def-Use Slicer + Capstone)
pip install strilight
# Profile 2: Symbolic Engine (Core Compressor + Z3 O(1) SMT Lifter)
pip install strilight[solver]
# Profile 3: Dynamic Slicing Suite (Core Compressor + Full PathTree Backward/Forward Tracker)
pip install strilight[tracker]
# Profile 4: Complete Bundle (All Engines + Full Tracker + Z3 Solver)
pip install strilight[all]
테스트 스위트는 분리된 계층 전반에 걸쳐 100% 테스트 통과율로 모든 모듈을 검증합니다:
strilight 필요)무거운 솔버 의존성 없음. 모든 플랫폼에서 $<1\text{ 초}$ 소요:
strilight[tracker] 필요)전체 동적 데이터 흐름 및 제어 의존성 추적을 검증합니다:
strilight[solver] 필요)BitVector 방정식 생성, 섀도 대체 및 Z3 제약 조건 해결을 검증합니다:
sl.analyze)모든 원시 x86-64 머신 코드 루프를 분석하고 폐쇄형 변환을 한 줄로 추출합니다:
import strilight as sl
# Loop bytecode: add eax, 8; sub ebx, 3; inc ecx; cmp ecx, 100000; jl 0x1000
loop_bytes = bytes.fromhex("83c008 83eb03 ffc1 81f9a0860100 7ced")
# ONE-LINE ANALYSIS:
summary = sl.analyze(loop_bytes, iterations=100000)
print(summary.deltas)
# Output: {'eax': 8, 'ebx': -3, 'ecx': 1}
# View the mathematical invariant contract:
print(summary.invariant_contract.to_dict())
import strilight as sl
# 1. Disassemble machine code bytes
instructions = sl.disassemble(loop_bytes, base_address=0x1000)
# 2. Package into a symbolic loop block
block = sl.LoopBlock(body=instructions, iterations=100000)
# 3. Extract closed-form mathematical steps (Deltas & Exit Predicates)
summary = sl.evaluate(block)
print(f"Exit Condition: {summary.exit_condition}")
목표 조건을 충족하는 데 필요한 반복 횟수($N$) 또는 입력 키를 $<100\text{ ms}$ 만에 해결합니다:
import strilight as sl
import z3
# Disassemble and evaluate
summary = sl.analyze(loop_bytes, iterations=100000)
# Initialize Z3 translator
translator = sl.Z3Translator()
translator.solver.add(translator.get_register('eax') == 0)
translator.solver.add(translator.get_register('ebx') == 500000)
translator.solver.add(translator.get_register('ecx') == 0)
# Lift loop summary in O(1) into Z3
translator.translate_loop_summary(summary, max_iterations=100000)
# Goal: When does EAX reach 800,000?
translator.solver.add(translator.get_register('eax') == 800000)
# Solve in milliseconds!
if translator.solver.check() == z3.sat:
model = translator.solver.model()
solved_N = model.eval(summary.loop_counter_var).as_long()
print(f"[+] Solved N = {solved_N:,} iterations in O(1) time!")
중첩 루프, 서브레지스터 슬라이싱 및 난독화된 스트라이드 패턴을 포함하는 복잡한 64비트 Windows 실행 파일(CrackMe Suite)로 테스트했습니다:
Ground-Truth 검증: 복구된 모든 키는 서브프로세스를 통해 네이티브 컴파일 바이너리(
.exe)를 실행하고ACCESS GRANTED응답을 확인하여 검증됩니다.
sl.analyze(code_bytes, iterations=1000, ...): 디스어셈블리 + 평가 원라이너.sl.disassemble(code_bytes, base_address=0x1000, bit_mode=64): Capstone을 통한 원시 바이트 디스어셈블러.sl.compress(trace, min_iterations=3): 계층적 트레이스 컴프레서.sl.evaluate(block_or_trace, k_passes=100): 추상 상태 및 불변 평가기.sl.Instruction: 통합 어셈블리 명령어 표현.sl.LoopBlock: 반복 경계를 포함하는 계층적 루프 노드.sl.LoopSummary: 델타, 순환 패턴 및 상수 집합을 포함하는 폐쇄형 변환 요약.sl.LoopInvariantContract: 형식적 구조적 탈출 불변 설명자 및 SMT 경계 규칙 생성기.sl.StridedInterval: 스트라이드 정렬 및 모듈러 합동을 포함한 수학적 구간 표현.sl.Z3Translator: 루프 요약을 Z3 BitVector 제약 조건으로 변환하는 심볼릭 SMT 리프터.이중 라이선스: MIT / 독점(Proprietary). 고성능 리버스 엔지니어링 및 바이너리 분석을 위해 ❤️로 개발되었습니다.
| 테스트 파일 | 설명 | 테스트 구성 요소 |
|---|
test_facade.py | 고수준 개발자 API (sl.analyze, sl.disassemble, sl.compress, sl.evaluate) | strilight 파사드 |
test_capstone_decoupling.py | 원시 머신 코드 바이트 디스어셈블리 및 커스텀 트레이서 브리지 등록 | Instruction, `[...] |
test_invariant_contract.py | 수학적 불변 계약 및 $N-1$ Iron Constraint 경계 설명자 | `LoopInvari[...] |
test_interval.py | 코어 구간 경계, 구간 산술 및 연산 | Interval |
test_disjoint_set.py | 분리 메모리 집합, 비연속 범위 산술 및 합집합 | DisjointIntervalSet |
test_strided_interval_notion.py | Strided Interval 도메인, GCD 합동 브리지 및 서브레지스터 비트마스크 | `Stri[...] |
test_circular_theorems.py | 순환 모듈러 산술 랩어라운드 정리 ($x \pmod{2^w}$) | StridedInterval 수학 |
test_loop_compressor.py | LoopBlock 트리로의 트레이스 폴딩 및 루프 백엣지 탐지 | TraceCompressor |
test_nested_loops.py | 다중 레벨 중첩 루프 압축 ($O(N \cdot M)$ 계층적 폴딩) | TraceCompressor 트리 |
test_vsa_evaluator.py | Value-Set Analysis 시뮬레이션 패스 및 아핀 델타 추출 | LoopEvaluator |
test_polycyclic.py | 메모리 및 레지스터의 다환 주기 패턴 ($P > 1$) | LoopEvaluator |
| 테스트 파일 | 설명 | 테스트 구성 요소 |
|---|
test_tracker.py | 역방향/정방향 명령어 슬라이싱, 레지스터/메모리 def-use 체인 | Tracker, BackwardTracker |
test_lazy_tracker.py | 지연 평가 및 무관한 루프 블록 건너뛰기 | Tracker 최적화 |
test_loop_taint.py | 루프 오염 전파 및 루프 탈출 제어 의존성 추적 | Tracker 오염 |
test_path_tree.py | 분기 결정 캐싱 및 막다른 경로 제거 | PathTree |
test_stop_dict.py | API 오염 경계 정의 | stop_dict |
test_hooks.py | 명령어 및 메모리 접근 인터셉트 콜백 | hooks |
| 테스트 파일 | 설명 | 테스트 구성 요소 |
|---|
test_translator.py | Z3 BitVector로의 전체 x86-64 명령어 변환 (산술, 플래그, 점프, 메모리) | Z3Translator |
test_translator_edge_cases.py | 깊은 AST 소진, 메모리 앨리어싱 체인 및 경계 제약 | `Z3Translato[...] |
test_deep_doubts.py | 부호 랩어라운드, 3차 뉴턴 귀납법 및 Bezout 합동 | 수학적 증명 |
| # | 대상 바이너리 | 슬라이스 크기 | Z3 상태 | 발견된 키 | 네이티브 실행 | 시간 | 결과 |
|---|
| 1 | crackme_boss.exe | 662 | SAT | 1729 | ACCESS GRANTED | ~60 ms | [PASS] |
| 2 | crackme_subregs.exe | 671 | SAT | 1337 | ACCESS GRANTED | ~75 ms | [PASS] |
| 3 | crackme_nested_loops.exe | 1369 | SAT | 1337 | ACCESS GRANTED | ~110 ms | [PASS] |
| 4 | crackme_pointers.exe | 859 | SAT | 1337 | ACCESS GRANTED | ~85 ms | [PASS] |
| 5 | crackme_license.exe | 657 | SAT | 1337 | ACCESS GRANTED | ~65 ms | [PASS] |
| 6 | crackme_strided_circular.exe | 829 | SAT | 1337 | ACCESS GRANTED | ~95 ms | [PASS] |