0
# Bytecode Utilities
1
2
Comprehensive bytecode analysis and formatting utilities for advanced Android reverse engineering. These functions provide visualization, export, and formatting capabilities for Android bytecode analysis.
3
4
## Capabilities
5
6
### Method Visualization
7
8
Generate visual representations of method control flow and structure.
9
10
```python { .api }
11
def method2dot(mx: MethodAnalysis, colors: dict = None) -> str:
12
"""
13
Generate DOT graph representation of method control flow.
14
15
Parameters:
16
- mx: MethodAnalysis object to visualize
17
- colors: Optional color mapping dictionary for nodes
18
19
Returns:
20
str: DOT format graph representation
21
"""
22
23
def method2format(filename: str, format: str, mx: MethodAnalysis, colors: dict = None) -> None:
24
"""
25
Export method visualization to various formats.
26
27
Parameters:
28
- filename: Output file name
29
- format: Output format ('png', 'svg', 'pdf', 'dot')
30
- mx: MethodAnalysis object to export
31
- colors: Optional color mapping for visualization
32
"""
33
34
def method2png(filename: str, mx: MethodAnalysis, colors: dict = None) -> None:
35
"""
36
Export method control flow as PNG image.
37
38
Parameters:
39
- filename: Output PNG file name
40
- mx: MethodAnalysis object to export
41
- colors: Optional color mapping for nodes
42
"""
43
```
44
45
### JSON Export
46
47
Convert bytecode analysis results to structured JSON format.
48
49
```python { .api }
50
def method2json(mx: MethodAnalysis, colors: dict = None) -> str:
51
"""
52
Convert method analysis to JSON representation.
53
54
Parameters:
55
- mx: MethodAnalysis object to convert
56
- colors: Optional color information to include
57
58
Returns:
59
str: JSON representation of method analysis
60
"""
61
62
def class2json(cx: ClassAnalysis) -> str:
63
"""
64
Convert class analysis to JSON representation.
65
66
Parameters:
67
- cx: ClassAnalysis object to convert
68
69
Returns:
70
str: JSON representation of class analysis
71
"""
72
73
def analysis2json(dx: Analysis) -> str:
74
"""
75
Convert complete analysis to JSON representation.
76
77
Parameters:
78
- dx: Analysis object to convert
79
80
Returns:
81
str: JSON representation of complete analysis
82
"""
83
```
84
85
### Class Name Formatting
86
87
Format Android class names for different target languages and conventions.
88
89
```python { .api }
90
def FormatClassToJava(class_name: str) -> str:
91
"""
92
Format Android class name to Java-style notation.
93
94
Parameters:
95
- class_name: Android internal class name (e.g., 'Lcom/example/App;')
96
97
Returns:
98
str: Java-style class name (e.g., 'com.example.App')
99
"""
100
101
def FormatClassToPython(class_name: str) -> str:
102
"""
103
Format Android class name to Python-style notation.
104
105
Parameters:
106
- class_name: Android internal class name
107
108
Returns:
109
str: Python-style class name with underscores
110
"""
111
112
def FormatClassToSmali(class_name: str) -> str:
113
"""
114
Format class name to Smali notation.
115
116
Parameters:
117
- class_name: Input class name
118
119
Returns:
120
str: Smali-format class name
121
"""
122
```
123
124
### Package and Class Analysis
125
126
Utilities for analyzing package structures and class relationships.
127
128
```python { .api }
129
def get_package_class_name(class_name: str) -> tuple[str, str]:
130
"""
131
Extract package and class name from full class name.
132
133
Parameters:
134
- class_name: Full Android class name
135
136
Returns:
137
tuple: (package_name, simple_class_name)
138
"""
139
140
def split_package_class(full_name: str) -> dict:
141
"""
142
Split full class name into components.
143
144
Parameters:
145
- full_name: Full class name to analyze
146
147
Returns:
148
dict: Dictionary with 'package', 'class', and 'inner_classes' keys
149
"""
150
151
def get_class_hierarchy(cx: ClassAnalysis) -> list[str]:
152
"""
153
Get inheritance hierarchy for a class.
154
155
Parameters:
156
- cx: ClassAnalysis object
157
158
Returns:
159
list: List of parent class names in hierarchy order
160
"""
161
```
162
163
### Bytecode Statistics
164
165
Generate statistical information about bytecode structure and complexity.
166
167
```python { .api }
168
def get_method_complexity(mx: MethodAnalysis) -> dict:
169
"""
170
Calculate complexity metrics for a method.
171
172
Parameters:
173
- mx: MethodAnalysis object
174
175
Returns:
176
dict: Complexity metrics including cyclomatic complexity, instruction count, etc.
177
"""
178
179
def get_class_statistics(cx: ClassAnalysis) -> dict:
180
"""
181
Generate statistics for a class.
182
183
Parameters:
184
- cx: ClassAnalysis object
185
186
Returns:
187
dict: Class statistics including method count, field count, complexity metrics
188
"""
189
190
def get_package_metrics(dx: Analysis, package_name: str) -> dict:
191
"""
192
Calculate metrics for an entire package.
193
194
Parameters:
195
- dx: Analysis object
196
- package_name: Target package name
197
198
Returns:
199
dict: Package-level metrics and statistics
200
"""
201
```
202
203
### Control Flow Utilities
204
205
Advanced control flow analysis and manipulation utilities.
206
207
```python { .api }
208
def get_basic_blocks(mx: MethodAnalysis) -> list:
209
"""
210
Extract basic blocks from method analysis.
211
212
Parameters:
213
- mx: MethodAnalysis object
214
215
Returns:
216
list: List of basic block objects
217
"""
218
219
def analyze_control_flow(mx: MethodAnalysis) -> dict:
220
"""
221
Perform detailed control flow analysis.
222
223
Parameters:
224
- mx: MethodAnalysis object
225
226
Returns:
227
dict: Control flow analysis results
228
"""
229
230
def detect_patterns(mx: MethodAnalysis) -> list[str]:
231
"""
232
Detect common code patterns in method.
233
234
Parameters:
235
- mx: MethodAnalysis object
236
237
Returns:
238
list: List of detected pattern names
239
"""
240
```
241
242
## Usage Examples
243
244
### Method Visualization
245
246
```python
247
from androguard.core.bytecode import method2dot, method2png, method2format
248
from androguard.misc import AnalyzeAPK
249
250
# Analyze APK
251
a, d, dx = AnalyzeAPK("app.apk")
252
253
# Find a specific method
254
target_method = None
255
for cls in dx.get_classes():
256
for method in cls.get_methods():
257
if method.name == "onCreate":
258
target_method = method
259
break
260
if target_method:
261
break
262
263
if target_method:
264
# Generate DOT graph
265
dot_graph = method2dot(target_method)
266
print("DOT Graph:")
267
print(dot_graph)
268
269
# Export as PNG
270
method2png("onCreate_flow.png", target_method)
271
272
# Export in multiple formats
273
method2format("onCreate_flow", "svg", target_method)
274
method2format("onCreate_flow", "pdf", target_method)
275
```
276
277
### JSON Export and Analysis
278
279
```python
280
from androguard.core.bytecode import method2json, class2json, analysis2json
281
import json
282
283
# Convert method to JSON
284
if target_method:
285
method_json = method2json(target_method)
286
method_data = json.loads(method_json)
287
288
print("Method Analysis JSON:")
289
print(json.dumps(method_data, indent=2))
290
291
# Convert entire class to JSON
292
target_class = target_method.get_class_analysis() if target_method else None
293
if target_class:
294
class_json = class2json(target_class)
295
class_data = json.loads(class_json)
296
297
print(f"Class '{target_class.name}' has {len(class_data['methods'])} methods")
298
299
# Export complete analysis
300
full_analysis = analysis2json(dx)
301
print(f"Full analysis size: {len(full_analysis)} characters")
302
```
303
304
### Class Name Formatting
305
306
```python
307
from androguard.core.bytecode import FormatClassToJava, FormatClassToPython, get_package_class_name
308
309
# Format class names
310
internal_name = "Lcom/example/myapp/MainActivity;"
311
java_name = FormatClassToJava(internal_name)
312
python_name = FormatClassToPython(internal_name)
313
314
print(f"Internal: {internal_name}")
315
print(f"Java: {java_name}") # com.example.myapp.MainActivity
316
print(f"Python: {python_name}") # com_example_myapp_MainActivity
317
318
# Extract package and class
319
package, class_name = get_package_class_name(internal_name)
320
print(f"Package: {package}") # com.example.myapp
321
print(f"Class: {class_name}") # MainActivity
322
```
323
324
### Bytecode Statistics
325
326
```python
327
from androguard.core.bytecode import get_method_complexity, get_class_statistics, get_package_metrics
328
329
# Method complexity analysis
330
if target_method:
331
complexity = get_method_complexity(target_method)
332
print("Method Complexity:")
333
print(f" Cyclomatic complexity: {complexity['cyclomatic']}")
334
print(f" Instruction count: {complexity['instructions']}")
335
print(f" Basic blocks: {complexity['basic_blocks']}")
336
print(f" Branch points: {complexity['branches']}")
337
338
# Class statistics
339
if target_class:
340
stats = get_class_statistics(target_class)
341
print("Class Statistics:")
342
print(f" Methods: {stats['method_count']}")
343
print(f" Fields: {stats['field_count']}")
344
print(f" Inner classes: {stats['inner_classes']}")
345
print(f" Average method complexity: {stats['avg_complexity']}")
346
347
# Package-level metrics
348
package_metrics = get_package_metrics(dx, "com.example.myapp")
349
print("Package Metrics:")
350
print(f" Total classes: {package_metrics['class_count']}")
351
print(f" Total methods: {package_metrics['method_count']}")
352
print(f" Package complexity: {package_metrics['total_complexity']}")
353
```
354
355
### Control Flow Analysis
356
357
```python
358
from androguard.core.bytecode import get_basic_blocks, analyze_control_flow, detect_patterns
359
360
if target_method:
361
# Get basic blocks
362
blocks = get_basic_blocks(target_method)
363
print(f"Method has {len(blocks)} basic blocks")
364
365
# Detailed control flow analysis
366
flow_analysis = analyze_control_flow(target_method)
367
print("Control Flow Analysis:")
368
print(f" Entry points: {flow_analysis['entry_points']}")
369
print(f" Exit points: {flow_analysis['exit_points']}")
370
print(f" Loops detected: {flow_analysis['loop_count']}")
371
print(f" Conditional branches: {flow_analysis['conditional_branches']}")
372
373
# Pattern detection
374
patterns = detect_patterns(target_method)
375
if patterns:
376
print("Detected Patterns:")
377
for pattern in patterns:
378
print(f" - {pattern}")
379
```
380
381
### Batch Analysis
382
383
```python
384
from androguard.core.bytecode import method2format, get_method_complexity
385
import os
386
387
# Create output directory
388
os.makedirs("analysis_output", exist_ok=True)
389
390
# Analyze all methods in a class
391
complexity_report = []
392
for method in target_class.get_methods() if target_class else []:
393
# Export visualization
394
safe_name = method.name.replace('<', '').replace('>', '').replace('/', '_')
395
output_file = f"analysis_output/{safe_name}"
396
397
try:
398
method2format(output_file, "png", method)
399
400
# Collect complexity data
401
complexity = get_method_complexity(method)
402
complexity_report.append({
403
'method': method.name,
404
'complexity': complexity['cyclomatic'],
405
'instructions': complexity['instructions']
406
})
407
except Exception as e:
408
print(f"Error analyzing {method.name}: {e}")
409
410
# Sort by complexity
411
complexity_report.sort(key=lambda x: x['complexity'], reverse=True)
412
413
print("Top 5 most complex methods:")
414
for item in complexity_report[:5]:
415
print(f" {item['method']}: complexity={item['complexity']}, instructions={item['instructions']}")
416
```
417
418
## Integration with Other Modules
419
420
### Combined with Static Analysis
421
422
```python
423
from androguard.core.bytecode import method2json, get_method_complexity
424
from androguard.core.analysis.analysis import MethodAnalysis
425
import json
426
427
# Find methods with high complexity that call cryptographic APIs
428
crypto_apis = ["javax.crypto", "java.security", "android.security"]
429
complex_crypto_methods = []
430
431
for cls in dx.get_classes():
432
for method in cls.get_methods():
433
# Check complexity
434
complexity = get_method_complexity(method)
435
if complexity['cyclomatic'] > 10: # High complexity threshold
436
437
# Check for crypto API usage
438
method_json = method2json(method)
439
method_data = json.loads(method_json)
440
441
calls_crypto = any(
442
any(crypto_api in call.get('target', '') for crypto_api in crypto_apis)
443
for call in method_data.get('external_calls', [])
444
)
445
446
if calls_crypto:
447
complex_crypto_methods.append({
448
'class': cls.name,
449
'method': method.name,
450
'complexity': complexity['cyclomatic']
451
})
452
453
print("Complex methods using cryptographic APIs:")
454
for method_info in sorted(complex_crypto_methods, key=lambda x: x['complexity'], reverse=True):
455
print(f" {method_info['class']}.{method_info['method']} (complexity: {method_info['complexity']})")
456
```