
Convertit les boucles de binaires x86-64 en contraintes SMT de forme fermée via une analyse par intervalles stridés, permettant une exécution symbolique en O(1) et la récupération de clés de crackme.
Lifting de boucles SMT $O(1)$ haute performance et domaine d'intervalles à pas pour l'analyse binaire x86_64
Les moteurs traditionnels d'exécution symbolique et d'instrumentation binaire dynamique (DBI) (tels que angr, Triton ou KLEE) souffrent du tristement célèbre problème d'explosion des chemins et des boucles. Lorsqu'ils rencontrent une l[...]
Strilight résout fondamentalement ce problème en traitant les boucles comme des récurrences algébriques de forme fermée au sein du domaine d'intervalles à pas :
$$\vec{\mathbf{R}}(N) = \vec{\mathbf{R}}_0 + \vec{\boldsymbol{\Delta}} \cdot N$$
Au lieu de simuler $N$ itérations, Strilight compresse les traces d'exécution répétitives en structures hiérarchiques LoopBlock, évalue leurs étapes abstraites affines et polycycliques, et effectue le lifting de l'e[...]
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 en $<1\text{ ms}$.Strilight est fourni sous forme de profils modulaires indépendants afin que vous n'embarquiez que les composants dont votre pipeline a besoin :
# 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]
La suite de tests valide chaque module avec un taux de réussite de 100 % dans les couches découplées :
strilight)Aucune dépendance lourde de solveur. S'exécute en $<1\text{ seconde}$ sur n'importe quelle plateforme :
strilight[tracker])Valide le suivi complet du flux de données dynamique et des dépendances de contrôle :
strilight[solver])Valide la génération d'équations BitVector, les substitutions fantômes et la résolution de contraintes Z3 :
sl.analyze)Analysez n'importe quelle boucle de code machine x86-64 brut et extrayez sa transformation de forme fermée en une seule ligne :
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}")
Résolvez le nombre d'itérations ($N$) ou la clé d'entrée requise pour satisfaire une condition objectif en $<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!")
Testé sur des exécutables Windows 64 bits complexes (CrackMe Suite) contenant des boucles imbriquées, du découpage de sous-registres et des motifs de pas obscurcis :
Vérification de vérité terrain : Toutes les clés récupérées sont vérifiées en exécutant le binaire compilé natif (
.exe) via subprocess et en confirmant la réponseACCESS GRANTED.
sl.analyze(code_bytes, iterations=1000, ...) : désassemblage + évaluation en une ligne.sl.disassemble(code_bytes, base_address=0x1000, bit_mode=64) : désassembleur d'octets bruts via Capstone.sl.compress(trace, min_iterations=3) : compresseur de traces hiérarchique.sl.evaluate(block_or_trace, k_passes=100) : évaluateur d'état abstrait et d'invariants.sl.Instruction : représentation unifiée d'instruction assembleur.sl.LoopBlock : nœud de boucle hiérarchique avec bornes d'itérations.sl.LoopSummary : résumé de transformation de forme fermée contenant les deltas, les motifs cycliques et les ensembles de constantes.sl.LoopInvariantContract : descripteur formel d'invariant de sortie structurel et générateur de règles de frontière SMT.sl.StridedInterval : représentation mathématique d'intervalle avec alignement de pas et congruence modulaire.sl.Z3Translator : lifter SMT symbolique convertissant les résumés de boucle en contraintes BitVector Z3.Double licence : MIT / propriétaire. Développé avec ❤️ pour la rétro-ingénierie haute performance et l'analyse binaire.
| Fichier de test | Description | Composants testés |
|---|
test_facade.py | API développeur de haut niveau (sl.analyze, sl.disassemble, sl.compress, sl.evaluate) | Façade strilight |
test_capstone_decoupling.py | Désassemblage d'octets de code machine bruts et enregistrement de pont traceur personnalisé | Instruction, `[...] |
test_invariant_contract.py | Contrats d'invariant mathématiques et descripteurs de frontière de contrainte de fer $N-1$ | `LoopInvari[...] |
test_interval.py | Bornage d'intervalles de base, arithmétique d'intervalles et opérations | Interval |
test_disjoint_set.py | Ensembles mémoire disjoints, arithmétique de plages non contiguës et unions | DisjointIntervalSet |
test_strided_interval_notion.py | Domaine d'intervalles à pas, pont de congruence PGCD et masques binaires de sous-registres | `Stri[...] |
test_circular_theorems.py | Théorèmes d'enroulement de l'arithmétique modulaire circulaire ($x \pmod{2^w}$) | Mathématiques StridedInterval |
test_loop_compressor.py | Plissement de traces et détection des arêtes de retour de boucle en arbres LoopBlock | TraceCompressor |
test_nested_loops.py | Compression de boucles imbriquées multi-niveaux (plissement hiérarchique $O(N \cdot M)$) | Arbres TraceCompressor |
test_vsa_evaluator.py | Passes de simulation d'analyse d'ensembles de valeurs et extraction de deltas affines | LoopEvaluator |
test_polycyclic.py | Motifs périodiques polycycliques en mémoire et dans les registres ($P > 1$) | LoopEvaluator |
| Fichier de test | Description | Composants testés |
|---|
test_tracker.py | Découpage d'instructions arrière/avant, chaînes def-use registres/mémoire | Tracker, BackwardTracker |
test_lazy_tracker.py | Évaluation paresseuse et saut de blocs de boucle non pertinents | Optimisation Tracker |
test_loop_taint.py | Propagation de taint de boucle et suivi des dépendances de contrôle à la sortie de boucle | Taint Tracker |
test_path_tree.py | Mise en cache des décisions de branchement et élimination des chemins sans issue | PathTree |
test_stop_dict.py | Définitions des frontières de taint d'API | stop_dict |
test_hooks.py | Rappels d'interception d'accès aux instructions et à la mémoire | hooks |
| Fichier de test | Description | Composants testés |
|---|
test_translator.py | Traduction complète d'instructions x86-64 en BitVectors Z3 (arithmétique, indicateurs, sauts, mémoire) | Z3Translator |
test_translator_edge_cases.py | Épuisement profond de l'AST, chaînes d'aliasing mémoire et contraintes de frontière | `Z3Translato[...] |
test_deep_doubts.py | Enroulement signé, induction de Newton cubique de degré 3 et congruences de Bézout | Preuves mathématiques |
| # | Binaire cible | Taille de la tranche | État Z3 | Clé découverte | Exécution native | Temps | Résultat |
|---|
| 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] |