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

ordinal-lookups.mddocs/

Ordinal Lookups

Database of ordinal to symbol name mappings for common Windows DLLs. The ordlookup package provides resolution of function names from ordinal numbers when symbolic information is not available.

Capabilities

Ordinal Resolution

Look up function names from ordinal numbers for supported DLLs.

def ordLookup(libname, ord_val, make_name=False):
    """
    Look up symbol name for given ordinal in specified library.
    
    Args:
        libname (bytes): DLL name (case-insensitive)
        ord_val (int): Ordinal number to look up
        make_name (bool): If True, generate formatted name when lookup fails
        
    Returns:
        bytes: Function name if found, formatted ordinal if make_name=True,
               or None if not found and make_name=False
    """

def formatOrdString(ord_val):
    """
    Format ordinal number as standardized string.
    
    Args:
        ord_val (int): Ordinal number
        
    Returns:
        bytes: Formatted ordinal string (e.g., b"ord123")
    """

Supported Libraries

The ordlookup package includes mappings for these common Windows DLLs:

  • oleaut32.dll: OLE Automation functions
  • ws2_32.dll: Winsock 2 networking functions
  • wsock32.dll: Legacy Winsock networking functions

Usage Examples

Basic Ordinal Lookup

import ordlookup

# Look up function names by ordinal
dll_name = b"oleaut32.dll"
ordinal = 2

function_name = ordlookup.ordLookup(dll_name, ordinal)
if function_name:
    print(f"Ordinal {ordinal} in {dll_name.decode()}: {function_name.decode()}")
else:
    print(f"Ordinal {ordinal} not found in {dll_name.decode()}")

# Generate formatted name if lookup fails
formatted_name = ordlookup.ordLookup(dll_name, 9999, make_name=True)
print(f"Unknown ordinal formatted: {formatted_name.decode()}")

Integration with PE Import Analysis

import pefile
import ordlookup

def resolve_import_ordinals(pe):
    """Resolve ordinal imports using ordlookup database."""
    if not hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):
        return
    
    print("Import Analysis with Ordinal Resolution:")
    print("-" * 50)
    
    for entry in pe.DIRECTORY_ENTRY_IMPORT:
        dll_name = entry.dll
        print(f"\nDLL: {dll_name.decode('utf-8')}")
        
        for imp in entry.imports:
            if imp.import_by_ordinal:
                # Try to resolve ordinal to function name
                resolved_name = ordlookup.ordLookup(dll_name, imp.ordinal)
                
                if resolved_name:
                    print(f"  Ordinal {imp.ordinal}: {resolved_name.decode('utf-8')}")
                else:
                    print(f"  Ordinal {imp.ordinal}: <unknown>")
            else:
                # Regular named import
                if imp.name:
                    print(f"  Function: {imp.name.decode('utf-8')}")

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

Ordinal Database Exploration

import ordlookup

def explore_ordinal_database():
    """Explore available ordinal mappings."""
    print("Available Ordinal Databases:")
    print("=" * 40)
    
    for dll_name, ord_dict in ordlookup.ords.items():
        dll_str = dll_name.decode('utf-8')
        print(f"\n{dll_str}:")
        print(f"  Functions: {len(ord_dict)}")
        
        # Show ordinal range
        if ord_dict:
            min_ord = min(ord_dict.keys())
            max_ord = max(ord_dict.keys())
            print(f"  Ordinal range: {min_ord} - {max_ord}")
            
            # Show first few functions
            print("  Sample functions:")
            for ord_num in sorted(ord_dict.keys())[:5]:
                func_name = ord_dict[ord_num].decode('utf-8')
                print(f"    {ord_num}: {func_name}")
            
            if len(ord_dict) > 5:
                print(f"    ... and {len(ord_dict) - 5} more")

# Usage
explore_ordinal_database()

Custom Ordinal Resolution

import ordlookup

def resolve_with_fallback(dll_name, ordinal):
    """Resolve ordinal with multiple fallback strategies."""
    # Try direct lookup
    result = ordlookup.ordLookup(dll_name, ordinal)
    if result:
        return result.decode('utf-8'), 'database'
    
    # Check case variations of DLL name
    dll_variations = [
        dll_name.lower(),
        dll_name.upper(),
        dll_name.lower().replace(b'.dll', b'') + b'.dll'
    ]
    
    for dll_var in dll_variations:
        result = ordlookup.ordLookup(dll_var, ordinal)
        if result:
            return result.decode('utf-8'), 'case_variant'
    
    # Generate formatted ordinal as fallback
    formatted = ordlookup.formatOrdString(ordinal)
    return formatted.decode('utf-8'), 'generated'

# Usage example
test_cases = [
    (b"oleaut32.dll", 2),      # Known mapping
    (b"OLEAUT32.DLL", 2),      # Case variation
    (b"kernel32.dll", 1),      # Unknown DLL
    (b"ws2_32.dll", 999)       # Unknown ordinal
]

print("Ordinal Resolution with Fallback:")
print("-" * 40)

for dll, ordinal in test_cases:
    result, method = resolve_with_fallback(dll, ordinal)
    print(f"{dll.decode():<15} ord {ordinal:<3}: {result:<20} ({method})")

PE File Analysis with Complete Ordinal Resolution

import pefile
import ordlookup

def complete_import_analysis(pe_file):
    """Complete import analysis with ordinal resolution."""
    print(f"Complete Import Analysis: {pe_file}")
    print("=" * 60)
    
    with pefile.PE(pe_file) as pe:
        if not hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):
            print("No imports found")
            return
        
        total_imports = 0
        resolved_ordinals = 0
        
        for entry in pe.DIRECTORY_ENTRY_IMPORT:
            dll_name = entry.dll
            dll_str = dll_name.decode('utf-8')
            
            print(f"\n{dll_str}:")
            print("-" * len(dll_str))
            
            dll_imports = 0
            dll_resolved = 0
            
            for imp in entry.imports:
                dll_imports += 1
                total_imports += 1
                
                if imp.import_by_ordinal:
                    # Try to resolve ordinal
                    resolved_name = ordlookup.ordLookup(dll_name, imp.ordinal)
                    
                    if resolved_name:
                        function_name = resolved_name.decode('utf-8')
                        resolved_ordinals += 1
                        dll_resolved += 1
                        status = "✓"
                    else:
                        function_name = f"<unknown ordinal {imp.ordinal}>"
                        status = "✗"
                    
                    print(f"  {status} Ordinal {imp.ordinal:3d}: {function_name}")
                else:
                    # Named import
                    if imp.name:
                        function_name = imp.name.decode('utf-8')
                        print(f"  ○ Function: {function_name}")
                    else:
                        print(f"  ? Import at 0x{imp.address:08x}")
            
            print(f"  Summary: {dll_imports} imports, {dll_resolved} ordinals resolved")
        
        # Overall statistics
        print(f"\nOverall Statistics:")
        print("-" * 20)
        print(f"Total imports: {total_imports}")
        print(f"Resolved ordinals: {resolved_ordinals}")
        
        if total_imports > 0:
            resolution_rate = (resolved_ordinals / total_imports) * 100
            print(f"Resolution rate: {resolution_rate:.1f}%")

# Usage
complete_import_analysis('executable.exe')

Extending the Ordinal Database

import ordlookup

# Example of how to extend the database (conceptual)
def add_custom_ordinals():
    """Example of extending ordinal database with custom mappings."""
    
    # This shows how you could add custom ordinal mappings
    # Note: This modifies the runtime database, not persistent storage
    
    custom_dll = b"custom.dll"
    custom_mappings = {
        1: b"CustomFunction1",
        2: b"CustomFunction2",
        100: b"SpecialExport"
    }
    
    # Add to ordlookup database
    ordlookup.ords[custom_dll] = custom_mappings
    
    print("Added custom ordinal mappings")
    
    # Test the new mappings
    for ordinal, expected_name in custom_mappings.items():
        resolved = ordlookup.ordLookup(custom_dll, ordinal)
        if resolved == expected_name:
            print(f"✓ Custom ordinal {ordinal}: {resolved.decode()}")
        else:
            print(f"✗ Failed to resolve custom ordinal {ordinal}")

# Note: This is for demonstration - actual extension would require
# modifying the ordlookup package files or creating a custom lookup system

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