CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pefile

Python PE parsing module for analyzing Portable Executable (PE) files with comprehensive header, section, and directory entry support

Pending
Overview
Eval results
Files

resources.mddocs/

Resource Analysis

Access to embedded resources including strings, icons, version information, and other resource types. PE files can contain various resources embedded within the file structure for use by the application.

Capabilities

Resource Directory Parsing

Parse and navigate the resource directory tree structure.

def parse_resources_directory(self, rva, size=0, base_rva=None, level=0, dirs=None):
    """
    Parse resources directory at specified RVA.
    
    Args:
        rva (int): RVA of resource directory
        size (int): Size of resource directory
        base_rva (int, optional): Base RVA for resource calculations  
        level (int): Current directory level (0=type, 1=name, 2=language)
        dirs (list, optional): List to collect directory entries
        
    Populates:
        self.DIRECTORY_ENTRY_RESOURCE: ResourceDirData object with resource tree
    """

String Resource Extraction

Extract string resources embedded in the PE file.

def get_resources_strings(self):
    """
    Get all strings from string table resources.
    
    Returns:
        list: List of tuples (language_id, string_id, string_value)
        
    Note:
        Extracts strings from RT_STRING resource type, commonly used
        for application messages, error text, and UI strings.
    """

Version Information Parsing

Parse version information resources containing file metadata.

def parse_version_information(self, version_struct):
    """
    Parse version information structure.
    
    Args:
        version_struct: Version information resource structure
        
    Returns:
        dict: Parsed version information including:
            - FileVersion, ProductVersion
            - CompanyName, FileDescription
            - InternalName, OriginalFilename
            - ProductName, LegalCopyright
            - And other version fields
    """

Usage Examples

Basic Resource Analysis

import pefile

with pefile.PE('executable.exe') as pe:
    # Check if resources are present
    if hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'):
        print("Resource Analysis:")
        print("-" * 40)
        
        # Walk resource tree
        for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries:
            # Resource type (RT_ICON, RT_STRING, etc.)
            if resource_type.name is not None:
                type_name = resource_type.name
            else:
                type_name = pefile.RESOURCE_TYPE.get(resource_type.struct.Id, 
                                                   f"Unknown({resource_type.struct.Id})")
            
            print(f"\nResource Type: {type_name}")
            
            # Resource names/IDs within this type
            if hasattr(resource_type, 'directory'):
                for resource_id in resource_type.directory.entries:
                    if resource_id.name is not None:
                        id_name = resource_id.name
                    else:
                        id_name = f"ID_{resource_id.struct.Id}"
                    
                    print(f"  Resource: {id_name}")
                    
                    # Language versions
                    if hasattr(resource_id, 'directory'):
                        for resource_lang in resource_id.directory.entries:
                            lang_id = resource_lang.struct.Id
                            lang_name = pefile.LANG.get(lang_id >> 10, f"Lang_{lang_id >> 10}")
                            sublang_id = lang_id & 0x3ff
                            
                            print(f"    Language: {lang_name} (0x{lang_id:04x})")
                            
                            # Get resource data
                            data_rva = resource_lang.data.struct.OffsetToData
                            data_size = resource_lang.data.struct.Size
                            print(f"    Data: RVA=0x{data_rva:08x}, Size={data_size}")
    else:
        print("No resources found")

String Resource Extraction

import pefile

with pefile.PE('executable.exe') as pe:
    # Extract string resources
    strings = pe.get_resources_strings()
    
    if strings:
        print("String Resources:")
        print("-" * 40)
        
        for lang_id, string_id, string_value in strings:
            # Decode language info
            lang_name = pefile.LANG.get(lang_id >> 10, f"Unknown_{lang_id >> 10}")
            sublang_id = lang_id & 0x3ff
            
            print(f"Language: {lang_name} (0x{lang_id:04x})")
            print(f"String ID: {string_id}")
            print(f"Value: {repr(string_value)}")
            print()
    else:
        print("No string resources found")

Version Information Analysis

import pefile

def extract_version_info(pe):
    """Extract and display version information."""
    if not hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'):
        return None
    
    # Look for version information resource
    for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries:
        if resource_type.struct.Id == pefile.RESOURCE_TYPE['RT_VERSION']:
            for resource_id in resource_type.directory.entries:
                for resource_lang in resource_id.directory.entries:
                    # Get version data
                    data_rva = resource_lang.data.struct.OffsetToData
                    data_size = resource_lang.data.struct.Size
                    data = pe.get_data(data_rva, data_size)
                    
                    # Parse version information
                    version_info = pe.parse_version_information(data)
                    return version_info
    
    return None

# Usage
with pefile.PE('executable.exe') as pe:
    version_info = extract_version_info(pe)
    
    if version_info:
        print("Version Information:")
        print("-" * 30)
        
        # Display common version fields
        common_fields = [
            'FileVersion', 'ProductVersion', 'CompanyName',
            'FileDescription', 'InternalName', 'OriginalFilename',
            'ProductName', 'LegalCopyright'
        ]
        
        for field in common_fields:
            if field in version_info:
                value = version_info[field]
                if isinstance(value, bytes):
                    value = value.decode('utf-8', errors='ignore')
                print(f"{field}: {value}")
    else:
        print("No version information found")

Icon Resource Extraction

import pefile

def extract_icons(pe, output_dir='icons'):
    """Extract icon resources from PE file."""
    import os
    
    if not hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'):
        return []
    
    os.makedirs(output_dir, exist_ok=True)
    extracted_icons = []
    
    # Find icon resources
    for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries:
        if resource_type.struct.Id == pefile.RESOURCE_TYPE['RT_ICON']:
            print("Found icon resources:")
            
            for resource_id in resource_type.directory.entries:
                icon_id = resource_id.struct.Id
                
                for resource_lang in resource_id.directory.entries:
                    lang_id = resource_lang.struct.Id
                    
                    # Get icon data
                    data_rva = resource_lang.data.struct.OffsetToData
                    data_size = resource_lang.data.struct.Size
                    icon_data = pe.get_data(data_rva, data_size)
                    
                    # Save icon file
                    filename = f"{output_dir}/icon_{icon_id}_{lang_id:04x}.ico"
                    with open(filename, 'wb') as f:
                        f.write(icon_data)
                    
                    extracted_icons.append(filename)
                    print(f"  Extracted icon {icon_id}: {filename} ({data_size} bytes)")
        
        elif resource_type.struct.Id == pefile.RESOURCE_TYPE['RT_GROUP_ICON']:
            print("Found icon group resources (metadata)")
    
    return extracted_icons

# Usage
with pefile.PE('executable.exe') as pe:
    icons = extract_icons(pe)
    print(f"Extracted {len(icons)} icons")

Manifest Resource Analysis

import pefile
import xml.etree.ElementTree as ET

def extract_manifest(pe):
    """Extract and parse application manifest."""
    if not hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'):
        return None
    
    # Look for manifest resource (RT_MANIFEST = 24)
    for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries:
        if resource_type.struct.Id == 24:  # RT_MANIFEST
            for resource_id in resource_type.directory.entries:
                for resource_lang in resource_id.directory.entries:
                    # Get manifest data
                    data_rva = resource_lang.data.struct.OffsetToData
                    data_size = resource_lang.data.struct.Size
                    manifest_data = pe.get_data(data_rva, data_size)
                    
                    try:
                        # Parse XML manifest
                        manifest_text = manifest_data.decode('utf-8')
                        return manifest_text
                    except UnicodeDecodeError:
                        # Try other encodings
                        try:
                            manifest_text = manifest_data.decode('utf-16')
                            return manifest_text
                        except:
                            return manifest_data  # Return raw data
    
    return None

# Usage
with pefile.PE('executable.exe') as pe:
    manifest = extract_manifest(pe)
    
    if manifest:
        print("Application Manifest:")
        print("-" * 30)
        
        if isinstance(manifest, str):
            # Try to parse XML for better display
            try:
                root = ET.fromstring(manifest)
                
                # Extract key information
                print("Manifest parsed successfully")
                
                # Look for UAC level
                for elem in root.iter():
                    if 'level' in elem.attrib:
                        print(f"UAC Level: {elem.attrib['level']}")
                    if 'uiAccess' in elem.attrib:
                        print(f"UI Access: {elem.attrib['uiAccess']}")
                
                print("\nFull manifest:")
                print(manifest)
                
            except ET.ParseError:
                print("Manifest (not valid XML):")
                print(manifest)
        else:
            print("Manifest (binary data):")
            print(manifest[:200], "..." if len(manifest) > 200 else "")
    else:
        print("No manifest found")

Resource Statistics

import pefile

def resource_statistics(pe):
    """Generate statistics about resources in PE file."""
    if not hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'):
        print("No resources found")
        return
    
    stats = {}
    total_size = 0
    
    # Count resources by type
    for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries:
        if resource_type.name is not None:
            type_name = str(resource_type.name)
        else:
            type_name = pefile.RESOURCE_TYPE.get(resource_type.struct.Id, 
                                               f"Type_{resource_type.struct.Id}")
        
        type_count = 0
        type_size = 0
        
        if hasattr(resource_type, 'directory'):
            for resource_id in resource_type.directory.entries:
                if hasattr(resource_id, 'directory'):
                    for resource_lang in resource_id.directory.entries:
                        type_count += 1
                        size = resource_lang.data.struct.Size
                        type_size += size
                        total_size += size
        
        stats[type_name] = {'count': type_count, 'size': type_size}
    
    # Display statistics
    print("Resource Statistics:")
    print("-" * 50)
    print(f"{'Type':<20} {'Count':<8} {'Size':<12} {'Percentage':<10}")
    print("-" * 50)
    
    for type_name, info in sorted(stats.items()):
        count = info['count']
        size = info['size']
        percentage = (size / total_size * 100) if total_size > 0 else 0
        
        print(f"{type_name:<20} {count:<8} {size:<12} {percentage:.1f}%")
    
    print("-" * 50)
    print(f"{'Total':<20} {sum(s['count'] for s in stats.values()):<8} {total_size:<12} 100.0%")

# Usage
with pefile.PE('executable.exe') as pe:
    resource_statistics(pe)

Install with Tessl CLI

npx tessl i tessl/pypi-pefile

docs

data-access.md

debug.md

hashing.md

import-export.md

index.md

memory.md

ordinal-lookups.md

packer-detection.md

pe-parsing.md

resources.md

sections.md

tile.json