0
# Session Management
1
2
Persistent analysis sessions for complex workflows, enabling save/restore of analysis state and incremental processing. Sessions provide a way to manage multiple files and maintain analysis results across different execution contexts.
3
4
## Capabilities
5
6
### Session Class
7
8
The main session management class that handles persistent analysis state and multi-file workflows.
9
10
```python { .api }
11
class Session:
12
def __init__(self, export_ipython: bool = False):
13
"""
14
Initialize analysis session.
15
16
Parameters:
17
- export_ipython: Enable IPython/Jupyter notebook integration
18
"""
19
20
def save(self, filename: str) -> None:
21
"""
22
Save session state to file.
23
24
Parameters:
25
- filename: Path to save session file (.ag extension recommended)
26
"""
27
28
def load(self, filename: str) -> None:
29
"""
30
Load session state from file.
31
32
Parameters:
33
- filename: Path to session file to load
34
"""
35
36
def reset(self) -> None:
37
"""Reset session to initial state, clearing all loaded files and analyses."""
38
39
def add(self, filename: str, raw_data: bytes = None) -> str:
40
"""
41
Add file to session for analysis.
42
43
Parameters:
44
- filename: Path to file or identifier if raw_data provided
45
- raw_data: Raw file bytes (optional, will read from filename if not provided)
46
47
Returns:
48
Session identifier for the added file
49
"""
50
51
def addAPK(self, filename: str, raw_data: bytes = None) -> tuple:
52
"""
53
Add APK file to session with full analysis.
54
55
Parameters:
56
- filename: Path to APK file
57
- raw_data: Raw APK bytes (optional)
58
59
Returns:
60
Tuple of (APK_object, DEX_objects_list, Analysis_object)
61
"""
62
63
def addDEX(self, filename: str, raw_data: bytes = None) -> tuple:
64
"""
65
Add DEX file to session with analysis.
66
67
Parameters:
68
- filename: Path to DEX file
69
- raw_data: Raw DEX bytes (optional)
70
71
Returns:
72
Tuple of (DEX_object, Analysis_object)
73
"""
74
```
75
76
### Session Information and Access
77
78
Retrieve information about files and analyses in the current session.
79
80
```python { .api }
81
def get_objects_apk(self, filename: str = None) -> list:
82
"""
83
Get APK objects in session.
84
85
Parameters:
86
- filename: Filter by specific filename (optional)
87
88
Returns:
89
List of APK objects
90
"""
91
92
def get_objects_dex(self) -> list:
93
"""
94
Get all DEX objects in session.
95
96
Returns:
97
List of DEX objects from all loaded files
98
"""
99
100
def get_analysis(self, dex_object) -> object:
101
"""
102
Get Analysis object for DEX.
103
104
Parameters:
105
- dex_object: DEX object to get analysis for
106
107
Returns:
108
Analysis object or None if not found
109
"""
110
111
def get_format_type(self, filename: str) -> str:
112
"""
113
Get file format type.
114
115
Parameters:
116
- filename: File identifier
117
118
Returns:
119
Format string ('APK', 'DEX', 'ODEX', etc.)
120
"""
121
122
def get_filename_by_raw(self, raw_data: bytes) -> str:
123
"""
124
Get filename for raw data.
125
126
Parameters:
127
- raw_data: Raw file bytes
128
129
Returns:
130
Associated filename or None
131
"""
132
133
def get_raw_by_filename(self, filename: str) -> bytes:
134
"""
135
Get raw data for filename.
136
137
Parameters:
138
- filename: File identifier
139
140
Returns:
141
Raw file bytes or None
142
"""
143
```
144
145
### Session Operations
146
147
Advanced session operations for batch processing and management.
148
149
```python { .api }
150
def get_sessions(self) -> list:
151
"""
152
Get list of all active sessions.
153
154
Returns:
155
List of session identifiers
156
"""
157
158
def get_session_by_filename(self, filename: str) -> str:
159
"""
160
Get session identifier for filename.
161
162
Parameters:
163
- filename: File identifier
164
165
Returns:
166
Session identifier or None
167
"""
168
169
def remove_session(self, session_id: str) -> bool:
170
"""
171
Remove session from active sessions.
172
173
Parameters:
174
- session_id: Session identifier to remove
175
176
Returns:
177
True if session was removed
178
"""
179
180
def get_nb_sessions(self) -> int:
181
"""
182
Get number of active sessions.
183
184
Returns:
185
Number of active session objects
186
"""
187
```
188
189
### Export and Integration
190
191
Export session data and integrate with external tools.
192
193
```python { .api }
194
def export_to_ipython(self) -> None:
195
"""Export session objects to IPython/Jupyter namespace for interactive analysis."""
196
197
def create_xref_png(self, filename: str, **kwargs) -> None:
198
"""
199
Create cross-reference PNG diagram.
200
201
Parameters:
202
- filename: Output PNG file path
203
- **kwargs: Additional graphing options
204
"""
205
206
def create_call_graph_png(self, filename: str, **kwargs) -> None:
207
"""
208
Create call graph PNG diagram.
209
210
Parameters:
211
- filename: Output PNG file path
212
- **kwargs: Additional graphing options
213
"""
214
215
def show_info(self) -> None:
216
"""Display detailed session information including loaded files and analyses."""
217
218
def get_stats(self) -> dict:
219
"""
220
Get session statistics.
221
222
Returns:
223
Dictionary with session statistics and metrics
224
"""
225
```
226
227
## Multi-File Session Management
228
229
Handle complex analysis workflows with multiple APK and DEX files.
230
231
```python { .api }
232
def add_directory(self, directory: str, recursive: bool = True) -> list:
233
"""
234
Add all supported files from directory.
235
236
Parameters:
237
- directory: Directory path to scan
238
- recursive: Include subdirectories
239
240
Returns:
241
List of added file identifiers
242
"""
243
244
def batch_analysis(self, file_list: list, parallel: bool = False) -> dict:
245
"""
246
Perform batch analysis on multiple files.
247
248
Parameters:
249
- file_list: List of file paths to analyze
250
- parallel: Enable parallel processing
251
252
Returns:
253
Dictionary mapping filenames to analysis results
254
"""
255
256
def compare_sessions(self, other_session) -> dict:
257
"""
258
Compare this session with another session.
259
260
Parameters:
261
- other_session: Another Session object to compare
262
263
Returns:
264
Dictionary with comparison results
265
"""
266
267
def merge_sessions(self, other_session) -> None:
268
"""
269
Merge another session into this one.
270
271
Parameters:
272
- other_session: Session object to merge
273
"""
274
```
275
276
### Session Serialization
277
278
Advanced serialization options for session persistence.
279
280
```python { .api }
281
def save_compressed(self, filename: str, compression_level: int = 6) -> None:
282
"""
283
Save session with compression.
284
285
Parameters:
286
- filename: Output file path
287
- compression_level: Compression level (1-9)
288
"""
289
290
def load_from_url(self, url: str) -> None:
291
"""
292
Load session from remote URL.
293
294
Parameters:
295
- url: HTTP/HTTPS URL to session file
296
"""
297
298
def export_json(self, filename: str, include_bytecode: bool = False) -> None:
299
"""
300
Export session data as JSON.
301
302
Parameters:
303
- filename: Output JSON file path
304
- include_bytecode: Include raw bytecode in export
305
"""
306
307
def import_json(self, filename: str) -> None:
308
"""
309
Import session data from JSON.
310
311
Parameters:
312
- filename: JSON file path to import
313
"""
314
```
315
316
## Usage Examples
317
318
### Basic Session Usage
319
320
```python
321
from androguard.session import Session
322
323
# Create new session
324
session = Session()
325
326
# Add APK file to session
327
apk, dex_list, dx = session.addAPK("app.apk")
328
329
print(f"Added APK: {apk.get_package()}")
330
print(f"DEX files: {len(dex_list)}")
331
print(f"Classes analyzed: {len(dx.get_classes())}")
332
333
# Save session for later use
334
session.save("my_analysis.ag")
335
print("Session saved")
336
337
# Later, load the session
338
new_session = Session()
339
new_session.load("my_analysis.ag")
340
print("Session loaded")
341
342
# Access previously analyzed data
343
apk_objects = new_session.get_objects_apk()
344
print(f"Restored APKs: {len(apk_objects)}")
345
```
346
347
### Multi-File Analysis Session
348
349
```python
350
# Create session for multiple files
351
session = Session()
352
353
# Add multiple APK files
354
apk_files = ["app1.apk", "app2.apk", "app3.apk"]
355
analysis_results = {}
356
357
for apk_file in apk_files:
358
print(f"Analyzing {apk_file}...")
359
try:
360
apk, dex_list, dx = session.addAPK(apk_file)
361
analysis_results[apk_file] = {
362
'package': apk.get_package(),
363
'classes': len(dx.get_classes()),
364
'methods': len(dx.get_methods()),
365
'strings': len(dx.get_strings())
366
}
367
print(f" ✓ Package: {apk.get_package()}")
368
print(f" ✓ Classes: {len(dx.get_classes())}")
369
except Exception as e:
370
print(f" ✗ Failed: {e}")
371
analysis_results[apk_file] = None
372
373
# Display summary
374
print(f"\nAnalysis Summary:")
375
for apk_file, result in analysis_results.items():
376
if result:
377
print(f"{apk_file}: {result['package']} ({result['classes']} classes)")
378
else:
379
print(f"{apk_file}: Analysis failed")
380
381
# Save comprehensive session
382
session.save("multi_app_analysis.ag")
383
```
384
385
### Batch Directory Processing
386
387
```python
388
import os
389
390
# Create session for directory processing
391
session = Session()
392
393
# Add all APKs from directory
394
apk_directory = "/path/to/apk/collection"
395
added_files = session.add_directory(apk_directory, recursive=True)
396
397
print(f"Found and added {len(added_files)} files")
398
399
# Get statistics for all loaded APKs
400
total_classes = 0
401
total_methods = 0
402
package_names = []
403
404
for filename in added_files:
405
if session.get_format_type(filename) == "APK":
406
apk_objects = session.get_objects_apk(filename)
407
if apk_objects:
408
apk = apk_objects[0]
409
package_names.append(apk.get_package())
410
411
# Get analysis for this APK
412
dex_objects = session.get_objects_dex()
413
for dex in dex_objects:
414
dx = session.get_analysis(dex)
415
if dx:
416
total_classes += len(dx.get_classes())
417
total_methods += len(dx.get_methods())
418
419
print(f"Total statistics:")
420
print(f" Packages: {len(package_names)}")
421
print(f" Classes: {total_classes}")
422
print(f" Methods: {total_methods}")
423
print(f" Average classes per app: {total_classes/len(package_names):.1f}")
424
425
# Save batch analysis session
426
session.save("batch_analysis.ag")
427
```
428
429
### Session Comparison and Analysis
430
431
```python
432
# Load two different sessions for comparison
433
session1 = Session()
434
session1.load("version1_analysis.ag")
435
436
session2 = Session()
437
session2.load("version2_analysis.ag")
438
439
# Compare sessions
440
comparison = session1.compare_sessions(session2)
441
print("Session comparison results:")
442
for key, value in comparison.items():
443
print(f" {key}: {value}")
444
445
# Get detailed statistics
446
stats1 = session1.get_stats()
447
stats2 = session2.get_stats()
448
449
print(f"\nSession 1 stats: {stats1}")
450
print(f"Session 2 stats: {stats2}")
451
452
# Merge sessions if needed
453
combined_session = Session()
454
combined_session.merge_sessions(session1)
455
combined_session.merge_sessions(session2)
456
457
print(f"Combined session has {combined_session.get_nb_sessions()} total sessions")
458
```
459
460
### Interactive Session with IPython
461
462
```python
463
# Create session with IPython integration
464
session = Session(export_ipython=True)
465
466
# Add files
467
session.addAPK("target_app.apk")
468
session.addDEX("additional.dex")
469
470
# Export to IPython namespace for interactive analysis
471
session.export_to_ipython()
472
473
# Now in IPython/Jupyter, you can access:
474
# - APK objects directly
475
# - DEX objects directly
476
# - Analysis objects directly
477
# - All androguard functionality
478
479
# Display session info
480
session.show_info()
481
482
# Create visualizations
483
session.create_call_graph_png("call_graph.png", show_edge_labels=True)
484
session.create_xref_png("cross_refs.png", node_color='lightblue')
485
```
486
487
### Advanced Session Serialization
488
489
```python
490
# Session with advanced serialization
491
session = Session()
492
493
# Add multiple files
494
session.addAPK("app.apk")
495
session.add("custom_dex.dex")
496
497
# Save with different formats
498
session.save("standard_session.ag") # Standard format
499
session.save_compressed("compressed_session.ag.gz", compression_level=9) # Compressed
500
session.export_json("session_data.json", include_bytecode=False) # JSON export
501
502
# Load from different sources
503
new_session = Session()
504
new_session.load("standard_session.ag")
505
506
json_session = Session()
507
json_session.import_json("session_data.json")
508
509
# Compare file sizes and load times
510
import time
511
512
start_time = time.time()
513
test_session1 = Session()
514
test_session1.load("standard_session.ag")
515
standard_time = time.time() - start_time
516
517
start_time = time.time()
518
test_session2 = Session()
519
test_session2.load("compressed_session.ag.gz")
520
compressed_time = time.time() - start_time
521
522
print(f"Standard load time: {standard_time:.2f}s")
523
print(f"Compressed load time: {compressed_time:.2f}s")
524
```
525
526
### Session State Management
527
528
```python
529
# Advanced session state management
530
session = Session()
531
532
# Add files and track state
533
original_state = session.get_stats()
534
print(f"Initial state: {original_state}")
535
536
# Add first APK
537
session.addAPK("app1.apk")
538
state_after_app1 = session.get_stats()
539
print(f"After app1: {state_after_app1}")
540
541
# Add second APK
542
session.addAPK("app2.apk")
543
state_after_app2 = session.get_stats()
544
print(f"After app2: {state_after_app2}")
545
546
# Create checkpoint
547
session.save("checkpoint.ag")
548
549
# Continue analysis...
550
session.addDEX("extra.dex")
551
552
# If something goes wrong, restore from checkpoint
553
if some_error_condition:
554
session.reset()
555
session.load("checkpoint.ag")
556
print("Restored from checkpoint")
557
558
# Clean up sessions
559
active_sessions = session.get_sessions()
560
print(f"Active sessions: {len(active_sessions)}")
561
562
for session_id in active_sessions:
563
if should_remove_session(session_id):
564
session.remove_session(session_id)
565
566
print(f"Remaining sessions: {session.get_nb_sessions()}")
567
```
568
569
## Utility Functions
570
571
```python { .api }
572
def save_session(objects: dict, filename: str) -> None:
573
"""
574
Save analysis objects to session file.
575
576
Parameters:
577
- objects: Dictionary of analysis objects to save
578
- filename: Output session file path
579
"""
580
581
def load_session(filename: str) -> dict:
582
"""
583
Load analysis objects from session file.
584
585
Parameters:
586
- filename: Session file path to load
587
588
Returns:
589
Dictionary of loaded analysis objects
590
"""
591
592
def get_default_session() -> Session:
593
"""
594
Get or create default global session.
595
596
Returns:
597
Global Session object
598
"""
599
600
def clear_default_session() -> None:
601
"""Clear the default global session."""
602
```