CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-androguard

Comprehensive Python toolkit for Android application reverse engineering and security analysis.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

static-analysis.mddocs/

Static Analysis

Advanced static analysis capabilities including control flow analysis, call graph generation, method analysis, and cross-reference detection. The Analysis class provides comprehensive static analysis of Android applications.

Capabilities

Analysis Engine

The main analysis engine that provides comprehensive static analysis capabilities for Android applications.

class Analysis:
    def __init__(self, *args):
        """
        Initialize analysis engine.
        
        Parameters:
        - *args: DEX objects to analyze (can be multiple DEX files)
        """

def get_classes(self) -> list:
    """Return list of all ClassAnalysis objects."""

def get_methods(self) -> list:
    """Return list of all MethodAnalysis objects."""

def get_fields(self) -> list:
    """Return list of all FieldAnalysis objects."""

def get_strings(self) -> list:
    """Return list of all StringAnalysis objects."""

def find_classes(self, class_name: str = ".*", no_external: bool = False) -> list:
    """
    Find classes matching pattern.
    
    Parameters:
    - class_name: Regular expression pattern for class names
    - no_external: Exclude external classes if True
    
    Returns:
    List of matching ClassAnalysis objects
    """

def find_methods(self, class_name: str = ".*", method_name: str = ".*", descriptor: str = ".*", accessflags: str = ".*", no_external: bool = False) -> list:
    """
    Find methods matching criteria.
    
    Parameters:
    - class_name: Class name pattern
    - method_name: Method name pattern  
    - descriptor: Method descriptor pattern
    - accessflags: Access flags pattern
    - no_external: Exclude external methods if True
    
    Returns:
    List of matching MethodAnalysis objects
    """

def find_strings(self, string: str = ".*") -> list:
    """
    Find strings matching pattern.
    
    Parameters:
    - string: Regular expression pattern
    
    Returns:
    List of matching StringAnalysis objects
    """

def find_fields(self, class_name: str = ".*", field_name: str = ".*", field_type: str = ".*", accessflags: str = ".*") -> list:
    """
    Find fields matching criteria.
    
    Parameters:
    - class_name: Class name pattern
    - field_name: Field name pattern
    - field_type: Field type pattern
    - accessflags: Access flags pattern
    
    Returns:
    List of matching FieldAnalysis objects
    """

Call Graph Analysis

Generate and analyze call graphs showing method invocation relationships.

def get_call_graph(self, classname: str = ".*", methodname: str = ".*", descriptor: str = ".*", accessflags: str = ".*", no_isolated: bool = False, entry_points: list = None):
    """
    Generate call graph for methods matching criteria.
    
    Parameters:
    - classname: Class name filter pattern
    - methodname: Method name filter pattern
    - descriptor: Method descriptor pattern
    - accessflags: Access flags pattern
    - no_isolated: Exclude isolated nodes
    - entry_points: List of entry point methods
    
    Returns:
    NetworkX DiGraph object representing call graph
    """

def get_method(self, method) -> object:
    """
    Get MethodAnalysis for EncodedMethod.
    
    Parameters:
    - method: EncodedMethod object
    
    Returns:
    MethodAnalysis object or None
    """

def get_method_by_idx(self, idx: int) -> object:
    """Get MethodAnalysis by index."""

def get_class_analysis(self, class_def) -> object:
    """
    Get ClassAnalysis for ClassDefItem.
    
    Parameters:
    - class_def: ClassDefItem object
    
    Returns:
    ClassAnalysis object or None
    """

def get_field_analysis(self, field) -> object:
    """Get FieldAnalysis for EncodedField."""

Method Analysis

Detailed analysis of individual methods including control flow and cross-references.

class MethodAnalysis:
    def get_method(self):
        """Return associated EncodedMethod object."""
    
    def get_name(self) -> str:
        """Return method name."""
    
    def get_descriptor(self) -> str:
        """Return method descriptor."""
    
    def get_class_name(self) -> str:
        """Return containing class name."""
    
    def get_access_flags_string(self) -> str:
        """Return access flags as readable string."""
    
    def is_external(self) -> bool:
        """Return True if method is external/system method."""
    
    def is_android_api(self) -> bool:
        """Return True if method is Android API."""
    
    def get_length(self) -> int:
        """Return method code length."""

def get_basic_blocks(self) -> object:
    """
    Get basic blocks for method.
    
    Returns:
    BasicBlocks object containing control flow blocks
    """

def get_xref_from(self) -> list:
    """
    Get cross-references from this method.
    
    Returns:
    List of (ClassAnalysis, MethodAnalysis, offset) tuples
    """

def get_xref_to(self) -> list:
    """
    Get cross-references to this method.
    
    Returns:
    List of (ClassAnalysis, MethodAnalysis, offset) tuples
    """

def get_xref_new_instance(self) -> list:
    """Get cross-references for new-instance instructions."""

def get_xref_const_class(self) -> list:
    """Get cross-references for const-class instructions."""

Class Analysis

Comprehensive analysis of classes and their relationships.

class ClassAnalysis:
    def get_class(self):
        """Return associated ClassDefItem object."""
    
    def get_name(self) -> str:
        """Return class name."""
    
    def get_superclass_name(self) -> str:
        """Return superclass name."""
    
    def get_interfaces(self) -> list[str]:
        """Return list of implemented interface names."""
    
    def get_access_flags_string(self) -> str:
        """Return access flags as readable string."""
    
    def is_external(self) -> bool:
        """Return True if class is external/system class."""
    
    def is_android_api(self) -> bool:
        """Return True if class is Android API."""

def get_methods(self) -> list:
    """
    Get all methods in class.
    
    Returns:
    List of MethodAnalysis objects
    """

def get_fields(self) -> list:
    """
    Get all fields in class.
    
    Returns:
    List of FieldAnalysis objects
    """

def get_xref_from(self) -> list:
    """Get cross-references from this class."""

def get_xref_to(self) -> list:
    """Get cross-references to this class."""

def get_xref_new_instance(self) -> list:
    """Get new-instance references to this class."""

def get_xref_const_class(self) -> list:
    """Get const-class references to this class."""

Field Analysis

Analysis of field usage and cross-references.

class FieldAnalysis:
    def get_field(self):
        """Return associated EncodedField object."""
    
    def get_name(self) -> str:
        """Return field name."""
    
    def get_descriptor(self) -> str:
        """Return field type descriptor."""
    
    def get_class_name(self) -> str:
        """Return containing class name."""
    
    def get_access_flags_string(self) -> str:
        """Return access flags as readable string."""
    
    def is_external(self) -> bool:
        """Return True if field is external."""

def get_xref_read(self) -> list:
    """
    Get cross-references for field reads.
    
    Returns:
    List of (ClassAnalysis, MethodAnalysis, offset) tuples
    """

def get_xref_write(self) -> list:
    """
    Get cross-references for field writes.
    
    Returns:
    List of (ClassAnalysis, MethodAnalysis, offset) tuples
    """

String Analysis

Analysis of string usage throughout the application.

class StringAnalysis:
    def get_orig_value(self) -> str:
        """Return original string value."""
    
    def get_value(self) -> str:
        """Return string value (may be modified)."""
    
    def set_value(self, value: str) -> None:
        """Set new string value."""

def get_xref_from(self) -> list:
    """
    Get cross-references from this string.
    
    Returns:
    List of (ClassAnalysis, MethodAnalysis, offset) tuples where string is used
    """

Control Flow Analysis

Detailed control flow analysis with basic blocks and exception handling.

class BasicBlocks:
    def get(self) -> list:
        """Return list of all basic blocks."""
    
    def get_basic_block(self, idx: int):
        """Get basic block by index."""
    
    def gets(self) -> list:
        """Return list of basic blocks with extra information."""

class DEXBasicBlock:
    def get_name(self) -> str:
        """Return basic block name."""
    
    def get_start(self) -> int:
        """Return start offset of block."""
    
    def get_end(self) -> int:
        """Return end offset of block."""
    
    def get_last_length(self) -> int:
        """Return length of last instruction."""
    
    def get_nb_instructions(self) -> int:
        """Return number of instructions in block."""

def get_instructions(self) -> list:
    """Return list of instructions in basic block."""

def get_exception_analysis(self):
    """Return exception analysis for this block."""

def get_childs(self) -> list:
    """
    Get child basic blocks.
    
    Returns:
    List of (next_block, condition) tuples
    """

def get_fathers(self) -> list:
    """
    Get parent basic blocks.
    
    Returns:
    List of (prev_block, condition) tuples
    """

Exception Analysis

Analysis of exception handling and flow.

class ExceptionAnalysis:
    def get_exception(self):
        """Return exception object."""
    
    def get_catches(self) -> list:
        """Return list of catch handlers."""
    
    def show_source(self) -> str:
        """Return formatted source representation."""

class Exceptions:
    def get_exception(self, addr_start: int, addr_end: int) -> list:
        """
        Get exceptions for address range.
        
        Parameters:
        - addr_start: Start address
        - addr_end: End address
        
        Returns:
        List of exception handlers
        """

Usage Examples

Basic Static Analysis

from androguard.core.dex import DEX
from androguard.core.analysis.analysis import Analysis

# Load and analyze DEX
dex = DEX(open("classes.dex", "rb").read())
dx = Analysis(dex)

# Get analysis statistics
print(f"Classes: {len(dx.get_classes())}")
print(f"Methods: {len(dx.get_methods())}")
print(f"Fields: {len(dx.get_fields())}")
print(f"Strings: {len(dx.get_strings())}")

# Find specific classes
activity_classes = dx.find_classes(r".*Activity$")
print(f"Activity classes: {len(activity_classes)}")

for cls in activity_classes:
    print(f"  {cls.get_name()}")

Method Cross-Reference Analysis

# Find onCreate methods
oncreate_methods = dx.find_methods(method_name="onCreate")
print(f"Found {len(oncreate_methods)} onCreate methods")

for method in oncreate_methods:
    print(f"\nMethod: {method.get_class_name()}.{method.get_name()}")
    
    # Get methods called by this method
    xrefs_from = method.get_xref_from()
    if xrefs_from:
        print("  Calls to:")
        for ref_class, ref_method, offset in xrefs_from:
            print(f"    {ref_class.get_name()}.{ref_method.get_name()} at offset {offset}")
    
    # Get methods that call this method
    xrefs_to = method.get_xref_to()
    if xrefs_to:
        print("  Called by:")
        for ref_class, ref_method, offset in xrefs_to:
            print(f"    {ref_class.get_name()}.{ref_method.get_name()} at offset {offset}")

String Usage Analysis

# Find strings containing sensitive keywords
sensitive_strings = dx.find_strings(r".*(password|secret|key|token).*")
print(f"Found {len(sensitive_strings)} sensitive strings")

for string_analysis in sensitive_strings:
    string_value = string_analysis.get_value()
    print(f"\nString: '{string_value}'")
    
    # Find where this string is used
    xrefs = string_analysis.get_xref_from()
    if xrefs:
        print("  Used in:")
        for ref_class, ref_method, offset in xrefs:
            print(f"    {ref_class.get_name()}.{ref_method.get_name()} at offset {offset}")

Call Graph Generation

import networkx as nx
import matplotlib.pyplot as plt

# Generate call graph for specific class
call_graph = dx.get_call_graph(classname=r".*MainActivity.*")

print(f"Call graph nodes: {call_graph.number_of_nodes()}")
print(f"Call graph edges: {call_graph.number_of_edges()}")

# Find most called methods
in_degree = dict(call_graph.in_degree())
most_called = sorted(in_degree.items(), key=lambda x: x[1], reverse=True)[:10]

print("Most called methods:")
for method, count in most_called:
    print(f"  {method}: {count} calls")

# Find methods that call the most other methods
out_degree = dict(call_graph.out_degree())
most_calling = sorted(out_degree.items(), key=lambda x: x[1], reverse=True)[:10]

print("Methods with most outgoing calls:")
for method, count in most_calling:
    print(f"  {method}: {count} calls")

Control Flow Analysis

# Analyze control flow for specific method
target_method = dx.find_methods(class_name=r".*MainActivity.*", method_name="onCreate")[0]
if target_method:
    basic_blocks = target_method.get_basic_blocks()
    
    print(f"Method: {target_method.get_name()}")
    print(f"Basic blocks: {len(basic_blocks.get())}")
    
    for i, bb in enumerate(basic_blocks.get()):
        print(f"\nBasic Block {i}:")
        print(f"  Start: {bb.get_start():04x}")
        print(f"  End: {bb.get_end():04x}")
        print(f"  Instructions: {bb.get_nb_instructions()}")
        
        # Get child blocks (control flow)
        children = bb.get_childs()
        if children:
            print("  Children:")
            for child, condition in children:
                print(f"    Block at {child.get_start():04x} (condition: {condition})")
        
        # Check for exception handling
        exception_analysis = bb.get_exception_analysis()
        if exception_analysis:
            print("  Exception handling present")

Field Access Analysis

# Find field access patterns
password_fields = dx.find_fields(field_name=r".*[Pp]assword.*")
print(f"Found {len(password_fields)} password-related fields")

for field in password_fields:
    print(f"\nField: {field.get_class_name()}.{field.get_name()}")
    print(f"  Type: {field.get_descriptor()}")
    
    # Get field read operations
    reads = field.get_xref_read()
    if reads:
        print("  Read by:")
        for ref_class, ref_method, offset in reads:
            print(f"    {ref_class.get_name()}.{ref_method.get_name()} at {offset}")
    
    # Get field write operations
    writes = field.get_xref_write()
    if writes:
        print("  Written by:")
        for ref_class, ref_method, offset in writes:
            print(f"    {ref_class.get_name()}.{ref_method.get_name()} at {offset}")

Advanced Search Patterns

# Find crypto-related methods
crypto_methods = dx.find_methods(
    class_name=r".*(Crypto|Cipher|Hash|Encrypt|Decrypt).*",
    method_name=r".*(encrypt|decrypt|hash|sign|verify).*"
)

print(f"Found {len(crypto_methods)} crypto-related methods")
for method in crypto_methods:
    print(f"  {method.get_class_name()}.{method.get_name()}")

# Find network-related classes
network_classes = dx.find_classes(r".*(Http|Network|Socket|URL).*")
print(f"Found {len(network_classes)} network-related classes")

# Find potentially obfuscated methods (short names)
obfuscated_methods = dx.find_methods(method_name=r"^[a-c]$")
print(f"Potentially obfuscated methods: {len(obfuscated_methods)}")

# Find native methods
native_methods = dx.find_methods(accessflags=r".*native.*")
print(f"Native methods: {len(native_methods)}")

Utility Functions

def is_ascii_obfuscation(vm) -> bool:
    """
    Detect ASCII-based obfuscation in DEX file.
    
    Parameters:
    - vm: DEX object to analyze
    
    Returns:
    True if ASCII obfuscation patterns detected
    """

Install with Tessl CLI

npx tessl i tessl/pypi-androguard

docs

apk-processing.md

bytecode-utilities.md

cli-tools.md

decompilation.md

dex-analysis.md

dynamic-analysis.md

index.md

session-management.md

static-analysis.md

utility-functions.md

xml-resources.md

tile.json