-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathmutation_workflow.py
More file actions
212 lines (161 loc) · 6.22 KB
/
Copy pathmutation_workflow.py
File metadata and controls
212 lines (161 loc) · 6.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#!/usr/bin/env python3
"""
Mutation workflow example for r2morph.
This example demonstrates working with different mutation passes:
1. Using individual mutation passes
2. Combining passes in a pipeline
3. Controlling pass configuration
4. Checking mutation results
Usage:
python mutation_workflow.py input.bin
"""
import sys
from pathlib import Path
from r2morph import __version__
from r2morph.core.config import (
EngineConfig,
InstructionSubstitutionConfig,
NopInsertionConfig,
RegisterSubstitutionConfig,
)
from r2morph.core.engine import MorphEngine
def demo_individual_passes(input_path: Path):
"""Example: Using individual mutation passes."""
print("\n" + "=" * 60)
print("Demo 1: Individual Mutation Passes")
print("=" * 60)
config = EngineConfig.create_default()
with MorphEngine(config=config) as engine:
engine.load_binary(input_path).analyze()
# Demo NOP insertion only
print("\n[NOP Insertion Pass]")
engine.add_mutation("nop")
result = engine.run(validation_mode="off")
print(f" Mutations: {result.mutations_applied}")
# Get mutation details from report
report = engine.build_report(result)
for pass_name, pass_result in report.get("passes", {}).items():
print(f" Pass: {pass_name}")
print(f" Mutations: {pass_result.get('mutation_count', 0)}")
def demo_custom_config(input_path: Path):
"""Example: Custom pass configuration."""
print("\n" + "=" * 60)
print("Demo 2: Custom Pass Configuration")
print("=" * 60)
# Create custom configurations for each pass
nop_config = NopInsertionConfig(
max_nop_sequences=5,
probability=0.3,
)
substitute_config = InstructionSubstitutionConfig(
preserve_semantics=True,
max_instruction_size=15,
)
register_config = RegisterSubstitutionConfig(
preserve_calling_convention=True,
)
config = EngineConfig(
nop=nop_config,
substitution=substitute_config,
register=register_config,
)
with MorphEngine(config=config) as engine:
engine.load_binary(input_path).analyze()
engine.add_mutation("nop")
engine.add_mutation("substitute")
result = engine.run(validation_mode="structural")
print("\nCustom configuration applied:")
print(f" NOP config: max={nop_config.max_nop_sequences}, prob={nop_config.probability}")
print(f" Result: {result.mutations_applied} mutations")
def demo_aggressive_mode(input_path: Path):
"""Example: Aggressive mutation mode."""
print("\n" + "=" * 60)
print("Demo 3: Aggressive Mutation Mode")
print("=" * 60)
# Aggressive mode enables more mutations per pass
config = EngineConfig.create_aggressive()
with MorphEngine(config=config) as engine:
engine.load_binary(input_path).analyze()
# All stable passes
engine.add_mutation("nop")
engine.add_mutation("substitute")
engine.add_mutation("register")
result = engine.run(validation_mode="structural")
print("\nAggressive mode:")
print(f" Mutations: {result.mutations_applied}")
print(f" Validation: {result.validation_status}")
def demo_experimental_passes(input_path: Path):
"""Example: Experimental mutation passes."""
print("\n" + "=" * 60)
print("Demo 4: Experimental Passes")
print("=" * 60)
print("\nExperimental passes (best-effort support):")
print(" - block: Basic block reordering")
print(" - expand: Instruction expansion")
print(" - cff: Control flow flattening")
print(" - opaque: Opaque predicates")
print(" - dead-code: Dead code injection")
print()
config = EngineConfig.create_default()
with MorphEngine(config=config) as engine:
engine.load_binary(input_path).analyze()
# Note: Experimental passes may not work on all binaries
engine.add_mutation("block") # Experimental
try:
result = engine.run(
validation_mode="structural",
rollback_policy="skip-invalid-pass",
)
print(f"Experimental pass result: {result.validation_status}")
except Exception as e:
print(f"Experimental pass failed (expected): {e}")
def demo_mutation_records(input_path: Path):
"""Example: Accessing mutation records."""
print("\n" + "=" * 60)
print("Demo 5: Mutation Records")
print("=" * 60)
config = EngineConfig.create_default()
with MorphEngine(config=config) as engine:
engine.load_binary(input_path).analyze()
engine.add_mutation("nop")
result = engine.run(validation_mode="off")
# Access mutation records
report = engine.build_report(result)
print("\nMutation Records:")
for pass_name, pass_data in report.get("passes", {}).items():
records = pass_data.get("records", [])
print(f"\n Pass: {pass_name}")
print(f" Record count: {len(records)}")
# Show first few records
for i, record in enumerate(records[:3]):
addr = record.get("address", "N/A")
desc = record.get("description", "N/A")
print(f" [{i}] 0x{addr:x}: {desc}")
if len(records) > 3:
print(f" ... and {len(records) - 3} more")
def main():
if len(sys.argv) < 2:
print(f"Usage: {sys.argv[0]} <input.bin>")
print()
print("Demonstrates various mutation workflows:")
print(" 1. Individual passes")
print(" 2. Custom configuration")
print(" 3. Aggressive mode")
print(" 4. Experimental passes")
print(" 5. Mutation records")
sys.exit(1)
input_path = Path(sys.argv[1])
if not input_path.exists():
print(f"Error: Input file not found: {input_path}")
sys.exit(1)
print(f"r2morph {__version__} - Mutation Workflow Example")
print("=" * 60)
demo_individual_passes(input_path)
demo_custom_config(input_path)
demo_aggressive_mode(input_path)
demo_experimental_passes(input_path)
demo_mutation_records(input_path)
print("\n" + "=" * 60)
print("Demos completed!")
if __name__ == "__main__":
main()