Comprehensive Python toolkit for Android application reverse engineering and security analysis.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
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.
The main session management class that handles persistent analysis state and multi-file workflows.
class Session:
def __init__(self, export_ipython: bool = False):
"""
Initialize analysis session.
Parameters:
- export_ipython: Enable IPython/Jupyter notebook integration
"""
def save(self, filename: str) -> None:
"""
Save session state to file.
Parameters:
- filename: Path to save session file (.ag extension recommended)
"""
def load(self, filename: str) -> None:
"""
Load session state from file.
Parameters:
- filename: Path to session file to load
"""
def reset(self) -> None:
"""Reset session to initial state, clearing all loaded files and analyses."""
def add(self, filename: str, raw_data: bytes = None) -> str:
"""
Add file to session for analysis.
Parameters:
- filename: Path to file or identifier if raw_data provided
- raw_data: Raw file bytes (optional, will read from filename if not provided)
Returns:
Session identifier for the added file
"""
def addAPK(self, filename: str, raw_data: bytes = None) -> tuple:
"""
Add APK file to session with full analysis.
Parameters:
- filename: Path to APK file
- raw_data: Raw APK bytes (optional)
Returns:
Tuple of (APK_object, DEX_objects_list, Analysis_object)
"""
def addDEX(self, filename: str, raw_data: bytes = None) -> tuple:
"""
Add DEX file to session with analysis.
Parameters:
- filename: Path to DEX file
- raw_data: Raw DEX bytes (optional)
Returns:
Tuple of (DEX_object, Analysis_object)
"""Retrieve information about files and analyses in the current session.
def get_objects_apk(self, filename: str = None) -> list:
"""
Get APK objects in session.
Parameters:
- filename: Filter by specific filename (optional)
Returns:
List of APK objects
"""
def get_objects_dex(self) -> list:
"""
Get all DEX objects in session.
Returns:
List of DEX objects from all loaded files
"""
def get_analysis(self, dex_object) -> object:
"""
Get Analysis object for DEX.
Parameters:
- dex_object: DEX object to get analysis for
Returns:
Analysis object or None if not found
"""
def get_format_type(self, filename: str) -> str:
"""
Get file format type.
Parameters:
- filename: File identifier
Returns:
Format string ('APK', 'DEX', 'ODEX', etc.)
"""
def get_filename_by_raw(self, raw_data: bytes) -> str:
"""
Get filename for raw data.
Parameters:
- raw_data: Raw file bytes
Returns:
Associated filename or None
"""
def get_raw_by_filename(self, filename: str) -> bytes:
"""
Get raw data for filename.
Parameters:
- filename: File identifier
Returns:
Raw file bytes or None
"""Advanced session operations for batch processing and management.
def get_sessions(self) -> list:
"""
Get list of all active sessions.
Returns:
List of session identifiers
"""
def get_session_by_filename(self, filename: str) -> str:
"""
Get session identifier for filename.
Parameters:
- filename: File identifier
Returns:
Session identifier or None
"""
def remove_session(self, session_id: str) -> bool:
"""
Remove session from active sessions.
Parameters:
- session_id: Session identifier to remove
Returns:
True if session was removed
"""
def get_nb_sessions(self) -> int:
"""
Get number of active sessions.
Returns:
Number of active session objects
"""Export session data and integrate with external tools.
def export_to_ipython(self) -> None:
"""Export session objects to IPython/Jupyter namespace for interactive analysis."""
def create_xref_png(self, filename: str, **kwargs) -> None:
"""
Create cross-reference PNG diagram.
Parameters:
- filename: Output PNG file path
- **kwargs: Additional graphing options
"""
def create_call_graph_png(self, filename: str, **kwargs) -> None:
"""
Create call graph PNG diagram.
Parameters:
- filename: Output PNG file path
- **kwargs: Additional graphing options
"""
def show_info(self) -> None:
"""Display detailed session information including loaded files and analyses."""
def get_stats(self) -> dict:
"""
Get session statistics.
Returns:
Dictionary with session statistics and metrics
"""Handle complex analysis workflows with multiple APK and DEX files.
def add_directory(self, directory: str, recursive: bool = True) -> list:
"""
Add all supported files from directory.
Parameters:
- directory: Directory path to scan
- recursive: Include subdirectories
Returns:
List of added file identifiers
"""
def batch_analysis(self, file_list: list, parallel: bool = False) -> dict:
"""
Perform batch analysis on multiple files.
Parameters:
- file_list: List of file paths to analyze
- parallel: Enable parallel processing
Returns:
Dictionary mapping filenames to analysis results
"""
def compare_sessions(self, other_session) -> dict:
"""
Compare this session with another session.
Parameters:
- other_session: Another Session object to compare
Returns:
Dictionary with comparison results
"""
def merge_sessions(self, other_session) -> None:
"""
Merge another session into this one.
Parameters:
- other_session: Session object to merge
"""Advanced serialization options for session persistence.
def save_compressed(self, filename: str, compression_level: int = 6) -> None:
"""
Save session with compression.
Parameters:
- filename: Output file path
- compression_level: Compression level (1-9)
"""
def load_from_url(self, url: str) -> None:
"""
Load session from remote URL.
Parameters:
- url: HTTP/HTTPS URL to session file
"""
def export_json(self, filename: str, include_bytecode: bool = False) -> None:
"""
Export session data as JSON.
Parameters:
- filename: Output JSON file path
- include_bytecode: Include raw bytecode in export
"""
def import_json(self, filename: str) -> None:
"""
Import session data from JSON.
Parameters:
- filename: JSON file path to import
"""from androguard.session import Session
# Create new session
session = Session()
# Add APK file to session
apk, dex_list, dx = session.addAPK("app.apk")
print(f"Added APK: {apk.get_package()}")
print(f"DEX files: {len(dex_list)}")
print(f"Classes analyzed: {len(dx.get_classes())}")
# Save session for later use
session.save("my_analysis.ag")
print("Session saved")
# Later, load the session
new_session = Session()
new_session.load("my_analysis.ag")
print("Session loaded")
# Access previously analyzed data
apk_objects = new_session.get_objects_apk()
print(f"Restored APKs: {len(apk_objects)}")# Create session for multiple files
session = Session()
# Add multiple APK files
apk_files = ["app1.apk", "app2.apk", "app3.apk"]
analysis_results = {}
for apk_file in apk_files:
print(f"Analyzing {apk_file}...")
try:
apk, dex_list, dx = session.addAPK(apk_file)
analysis_results[apk_file] = {
'package': apk.get_package(),
'classes': len(dx.get_classes()),
'methods': len(dx.get_methods()),
'strings': len(dx.get_strings())
}
print(f" ✓ Package: {apk.get_package()}")
print(f" ✓ Classes: {len(dx.get_classes())}")
except Exception as e:
print(f" ✗ Failed: {e}")
analysis_results[apk_file] = None
# Display summary
print(f"\nAnalysis Summary:")
for apk_file, result in analysis_results.items():
if result:
print(f"{apk_file}: {result['package']} ({result['classes']} classes)")
else:
print(f"{apk_file}: Analysis failed")
# Save comprehensive session
session.save("multi_app_analysis.ag")import os
# Create session for directory processing
session = Session()
# Add all APKs from directory
apk_directory = "/path/to/apk/collection"
added_files = session.add_directory(apk_directory, recursive=True)
print(f"Found and added {len(added_files)} files")
# Get statistics for all loaded APKs
total_classes = 0
total_methods = 0
package_names = []
for filename in added_files:
if session.get_format_type(filename) == "APK":
apk_objects = session.get_objects_apk(filename)
if apk_objects:
apk = apk_objects[0]
package_names.append(apk.get_package())
# Get analysis for this APK
dex_objects = session.get_objects_dex()
for dex in dex_objects:
dx = session.get_analysis(dex)
if dx:
total_classes += len(dx.get_classes())
total_methods += len(dx.get_methods())
print(f"Total statistics:")
print(f" Packages: {len(package_names)}")
print(f" Classes: {total_classes}")
print(f" Methods: {total_methods}")
print(f" Average classes per app: {total_classes/len(package_names):.1f}")
# Save batch analysis session
session.save("batch_analysis.ag")# Load two different sessions for comparison
session1 = Session()
session1.load("version1_analysis.ag")
session2 = Session()
session2.load("version2_analysis.ag")
# Compare sessions
comparison = session1.compare_sessions(session2)
print("Session comparison results:")
for key, value in comparison.items():
print(f" {key}: {value}")
# Get detailed statistics
stats1 = session1.get_stats()
stats2 = session2.get_stats()
print(f"\nSession 1 stats: {stats1}")
print(f"Session 2 stats: {stats2}")
# Merge sessions if needed
combined_session = Session()
combined_session.merge_sessions(session1)
combined_session.merge_sessions(session2)
print(f"Combined session has {combined_session.get_nb_sessions()} total sessions")# Create session with IPython integration
session = Session(export_ipython=True)
# Add files
session.addAPK("target_app.apk")
session.addDEX("additional.dex")
# Export to IPython namespace for interactive analysis
session.export_to_ipython()
# Now in IPython/Jupyter, you can access:
# - APK objects directly
# - DEX objects directly
# - Analysis objects directly
# - All androguard functionality
# Display session info
session.show_info()
# Create visualizations
session.create_call_graph_png("call_graph.png", show_edge_labels=True)
session.create_xref_png("cross_refs.png", node_color='lightblue')# Session with advanced serialization
session = Session()
# Add multiple files
session.addAPK("app.apk")
session.add("custom_dex.dex")
# Save with different formats
session.save("standard_session.ag") # Standard format
session.save_compressed("compressed_session.ag.gz", compression_level=9) # Compressed
session.export_json("session_data.json", include_bytecode=False) # JSON export
# Load from different sources
new_session = Session()
new_session.load("standard_session.ag")
json_session = Session()
json_session.import_json("session_data.json")
# Compare file sizes and load times
import time
start_time = time.time()
test_session1 = Session()
test_session1.load("standard_session.ag")
standard_time = time.time() - start_time
start_time = time.time()
test_session2 = Session()
test_session2.load("compressed_session.ag.gz")
compressed_time = time.time() - start_time
print(f"Standard load time: {standard_time:.2f}s")
print(f"Compressed load time: {compressed_time:.2f}s")# Advanced session state management
session = Session()
# Add files and track state
original_state = session.get_stats()
print(f"Initial state: {original_state}")
# Add first APK
session.addAPK("app1.apk")
state_after_app1 = session.get_stats()
print(f"After app1: {state_after_app1}")
# Add second APK
session.addAPK("app2.apk")
state_after_app2 = session.get_stats()
print(f"After app2: {state_after_app2}")
# Create checkpoint
session.save("checkpoint.ag")
# Continue analysis...
session.addDEX("extra.dex")
# If something goes wrong, restore from checkpoint
if some_error_condition:
session.reset()
session.load("checkpoint.ag")
print("Restored from checkpoint")
# Clean up sessions
active_sessions = session.get_sessions()
print(f"Active sessions: {len(active_sessions)}")
for session_id in active_sessions:
if should_remove_session(session_id):
session.remove_session(session_id)
print(f"Remaining sessions: {session.get_nb_sessions()}")def save_session(objects: dict, filename: str) -> None:
"""
Save analysis objects to session file.
Parameters:
- objects: Dictionary of analysis objects to save
- filename: Output session file path
"""
def load_session(filename: str) -> dict:
"""
Load analysis objects from session file.
Parameters:
- filename: Session file path to load
Returns:
Dictionary of loaded analysis objects
"""
def get_default_session() -> Session:
"""
Get or create default global session.
Returns:
Global Session object
"""
def clear_default_session() -> None:
"""Clear the default global session."""Install with Tessl CLI
npx tessl i tessl/pypi-androguard