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

sections.mddocs/

Section Operations

Methods for working with PE sections, including accessing section data and metadata. Sections contain the actual code, data, and resources of the PE file, organized into logical segments with specific characteristics and permissions.

Capabilities

Section Access

Locate and access sections by address or offset.

def get_section_by_rva(self, rva):
    """
    Get section containing the specified RVA.
    
    Args:
        rva (int): Relative virtual address
        
    Returns:
        SectionStructure: Section containing the RVA, or None if not found
    """

def get_section_by_offset(self, offset):
    """
    Get section containing the specified file offset.
    
    Args:
        offset (int): File offset
        
    Returns:
        SectionStructure: Section containing the offset, or None if not found
    """

Section Data Management

Apply modifications made to section data back to the PE structure.

def merge_modified_section_data(self):
    """
    Update PE internal data with modified section data.
    
    This method applies any changes made to section data back to the
    main PE data structure, ensuring consistency between section objects
    and the underlying file data. Must be called after modifying section
    data through section.set_data() or direct manipulation.
    """

SectionStructure Methods

Individual section objects provide detailed access to section data and properties.

class SectionStructure:
    def get_data(self, start=None, length=None, ignore_padding=False):
        """
        Get section data.
        
        Args:
            start (int, optional): Start offset within section
            length (int, optional): Number of bytes to read
            ignore_padding (bool): Whether to ignore alignment padding
            
        Returns:
            bytes: Section data
        """
    
    def get_entropy(self):
        """
        Calculate Shannon entropy of section data.
        
        Returns:
            float: Entropy value (0.0 to 8.0), higher values indicate more randomness
        """
    
    def get_hash_md5(self):
        """
        Calculate MD5 hash of section data.
        
        Returns:
            str: MD5 hash as hexadecimal string
        """
    
    def get_hash_sha1(self):
        """
        Calculate SHA-1 hash of section data.
        
        Returns:
            str: SHA-1 hash as hexadecimal string
        """
    
    def get_hash_sha256(self):
        """
        Calculate SHA-256 hash of section data.
        
        Returns:
            str: SHA-256 hash as hexadecimal string
        """
    
    def get_hash_sha512(self):
        """
        Calculate SHA-512 hash of section data.
        
        Returns:
            str: SHA-512 hash as hexadecimal string
        """
    
    def contains_rva(self, rva):
        """
        Check if section contains the specified RVA.
        
        Args:
            rva (int): Relative virtual address
            
        Returns:
            bool: True if RVA is within section bounds
        """
    
    def contains_offset(self, offset):
        """
        Check if section contains the specified file offset.
        
        Args:
            offset (int): File offset
            
        Returns:
            bool: True if offset is within section bounds
        """

Section Parsing

Parse section headers from the PE file.

def parse_sections(self, offset):
    """
    Parse section headers starting at specified offset.
    
    Args:
        offset (int): File offset where section headers begin
        
    Populates:
        self.sections: List of SectionStructure objects
    """

Section Structure Attributes

Each section in the pe.sections list is a SectionStructure object with the following key attributes:

class SectionStructure:
    """Represents a PE file section."""
    Name: bytes                    # Section name (8 bytes, null-padded)
    VirtualSize: int              # Size of section when loaded in memory
    VirtualAddress: int           # RVA where section is loaded
    SizeOfRawData: int           # Size of section in file
    PointerToRawData: int        # File offset to section data
    PointerToRelocations: int    # File offset to relocations
    PointerToLinenumbers: int    # File offset to line numbers
    NumberOfRelocations: int     # Number of relocations
    NumberOfLinenumbers: int     # Number of line number entries
    Characteristics: int          # Section characteristics/flags
    
    def get_data(self, start=None, length=None):
        """Get section data."""
    
    def set_data(self, data):
        """Set section data."""
    
    def get_entropy(self):
        """Calculate section entropy."""
        
    def get_hash_sha1(self):
        """Get SHA1 hash of section data."""
        
    def get_hash_sha256(self):
        """Get SHA256 hash of section data."""
        
    def get_hash_md5(self):
        """Get MD5 hash of section data."""

Usage Examples

Basic Section Analysis

import pefile

with pefile.PE('executable.exe') as pe:
    print("Section Analysis:")
    print("-" * 60)
    print(f"{'Name':<10} {'VirtAddr':<10} {'VirtSize':<10} {'RawSize':<10} {'Entropy':<8}")
    print("-" * 60)
    
    for section in pe.sections:
        name = section.Name.decode('utf-8').strip('\x00')
        virt_addr = f"0x{section.VirtualAddress:08x}"
        virt_size = f"0x{section.VirtualSize:08x}"
        raw_size = f"0x{section.SizeOfRawData:08x}"
        entropy = f"{section.get_entropy():.2f}"
        
        print(f"{name:<10} {virt_addr:<10} {virt_size:<10} {raw_size:<10} {entropy:<8}")

Section Characteristics Analysis

import pefile

with pefile.PE('executable.exe') as pe:
    print("Section Characteristics:")
    print("-" * 40)
    
    for section in pe.sections:
        name = section.Name.decode('utf-8').strip('\x00')
        characteristics = section.Characteristics
        
        print(f"\nSection: {name}")
        print(f"Characteristics: 0x{characteristics:08x}")
        
        # Decode characteristics flags
        flags = []
        if characteristics & 0x00000020:  # IMAGE_SCN_CNT_CODE
            flags.append("CODE")
        if characteristics & 0x00000040:  # IMAGE_SCN_CNT_INITIALIZED_DATA  
            flags.append("INITIALIZED_DATA")
        if characteristics & 0x00000080:  # IMAGE_SCN_CNT_UNINITIALIZED_DATA
            flags.append("UNINITIALIZED_DATA")
        if characteristics & 0x20000000:  # IMAGE_SCN_MEM_EXECUTE
            flags.append("EXECUTABLE")
        if characteristics & 0x40000000:  # IMAGE_SCN_MEM_READ
            flags.append("READABLE")
        if characteristics & 0x80000000:  # IMAGE_SCN_MEM_WRITE
            flags.append("WRITABLE")
            
        if flags:
            print(f"Flags: {', '.join(flags)}")

Section Data Extraction

import pefile
import os

with pefile.PE('executable.exe') as pe:
    # Create directory for section dumps
    output_dir = 'section_dumps'
    os.makedirs(output_dir, exist_ok=True)
    
    for i, section in enumerate(pe.sections):
        name = section.Name.decode('utf-8').strip('\x00')
        
        # Get section data
        section_data = section.get_data()
        
        # Save section to file
        filename = f"{output_dir}/{i:02d}_{name}.bin"
        with open(filename, 'wb') as f:
            f.write(section_data)
        
        print(f"Extracted {name}: {len(section_data)} bytes -> {filename}")
        
        # Calculate hashes
        sha256 = section.get_hash_sha256()
        md5 = section.get_hash_md5()
        entropy = section.get_entropy()
        
        print(f"  SHA256: {sha256}")
        print(f"  MD5: {md5}")
        print(f"  Entropy: {entropy:.3f}")

Section Modification

import pefile

# Load PE file
pe = pefile.PE('executable.exe')

# Find text section
text_section = None
for section in pe.sections:
    name = section.Name.decode('utf-8').strip('\x00')
    if name == '.text':
        text_section = section
        break

if text_section:
    print(f"Found .text section at RVA 0x{text_section.VirtualAddress:08x}")
    
    # Get current section data
    original_data = text_section.get_data()
    print(f"Original size: {len(original_data)} bytes")
    
    # Modify section data (example: NOP out first few bytes)
    modified_data = bytearray(original_data)
    modified_data[0:10] = b'\x90' * 10  # NOP instructions
    
    # Set modified data back to section
    text_section.set_data(bytes(modified_data))
    
    # Apply changes to PE structure
    pe.merge_modified_section_data()
    
    # Write modified PE
    pe.write('modified_executable.exe')
    print("Modified executable saved")

pe.close()

Finding Sections by Address

import pefile

with pefile.PE('executable.exe') as pe:
    # Find section containing entry point
    entry_point = pe.OPTIONAL_HEADER.AddressOfEntryPoint
    entry_section = pe.get_section_by_rva(entry_point)
    
    if entry_section:
        name = entry_section.Name.decode('utf-8').strip('\x00')
        print(f"Entry point 0x{entry_point:08x} is in section: {name}")
        
        # Calculate offset within section
        section_offset = entry_point - entry_section.VirtualAddress
        print(f"Offset within section: 0x{section_offset:08x}")
    
    # Find section containing specific file offset
    file_offset = 0x1000
    offset_section = pe.get_section_by_offset(file_offset)
    
    if offset_section:
        name = offset_section.Name.decode('utf-8').strip('\x00')
        print(f"File offset 0x{file_offset:08x} is in section: {name}")

Section Entropy Analysis

import pefile

def analyze_entropy(pe):
    """Analyze section entropy to detect packing."""
    print("Entropy Analysis:")
    print("-" * 30)
    
    high_entropy_sections = []
    
    for section in pe.sections:
        name = section.Name.decode('utf-8').strip('\x00')
        entropy = section.get_entropy()
        
        print(f"{name:<10}: {entropy:.3f}")
        
        # Flag high entropy sections (possibly packed/encrypted)
        if entropy > 7.0:  # High entropy threshold
            high_entropy_sections.append((name, entropy))
    
    if high_entropy_sections:
        print("\nHigh entropy sections (possibly packed):")
        for name, entropy in high_entropy_sections:
            print(f"  {name}: {entropy:.3f}")
    
    return high_entropy_sections

# Usage
with pefile.PE('executable.exe') as pe:
    high_entropy = analyze_entropy(pe)

Section Alignment Utilities

import pefile

with pefile.PE('executable.exe') as pe:
    file_alignment = pe.OPTIONAL_HEADER.FileAlignment
    section_alignment = pe.OPTIONAL_HEADER.SectionAlignment
    
    print(f"File Alignment: 0x{file_alignment:x}")
    print(f"Section Alignment: 0x{section_alignment:x}")
    print()
    
    for section in pe.sections:
        name = section.Name.decode('utf-8').strip('\x00')
        
        # Check alignment
        raw_addr_aligned = (section.PointerToRawData % file_alignment) == 0
        virt_addr_aligned = (section.VirtualAddress % section_alignment) == 0
        
        print(f"Section {name}:")
        print(f"  Raw Address: 0x{section.PointerToRawData:08x} (aligned: {raw_addr_aligned})")
        print(f"  Virtual Address: 0x{section.VirtualAddress:08x} (aligned: {virt_addr_aligned})")

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