Skip to content

Extract Strings from PE Resource Directory (Version Info, Manifests, String Tables, Dialogs, Menus) #57

Closed

Description

@unclesp1d3r

Context

Windows PE (Portable Executable) binaries contain a .rsrc section with a hierarchical resource directory structure that holds rich metadata and embedded strings. These resources are currently not being extracted by Stringy, resulting in missed opportunities to identify:

  • Version Information: Product names, company names, file descriptions, copyright strings
  • Manifest Files: Embedded XML manifests with assembly information and dependencies
  • String Tables: Localized strings stored in STRINGTABLE resources
  • Dialog Boxes: Control text, window titles, and UI strings
  • Menu Definitions: Menu item text and tooltips

The PE resource directory follows a three-level tree structure:

  1. Type: Resource type (RT_VERSION, RT_MANIFEST, RT_STRING, RT_DIALOG, etc.)
  2. Name: Resource identifier (numeric ID or string name)
  3. Language: Language/locale identifier (LCID)

Resources commonly use UTF-16LE encoding, requiring proper string decoding beyond ASCII/UTF-8 extraction.

Proposed Solution

Implementation Approach

Extend the PE container parser (src/container/pe.rs) to parse the resource directory structure and extract strings from high-value resource types:

1. Resource Directory Parsing

  • Locate the .rsrc section using existing section enumeration
  • Parse the three-level resource directory tree (Type → Name → Language)
  • Navigate resource data entries to locate actual resource data
  • Handle both numeric and string resource identifiers

2. Resource Type Handlers

Implement extraction for the following Win32 resource types:

RT_VERSION (Type 16) - Version Information

  • Parse VS_VERSIONINFO structure
  • Extract StringFileInfo fields:
    • FileDescription
    • ProductName
    • CompanyName
    • LegalCopyright
    • FileVersion
    • ProductVersion
    • InternalName
    • OriginalFilename
  • Tag with Version and Resource tags
  • Assign high relevance scores (8-10)

RT_MANIFEST (Type 24) - Application Manifest

  • Extract embedded XML manifest
  • Parse manifest for assembly names, dependencies, and configuration strings
  • Tag with Manifest and Resource tags
  • Assign high relevance scores (7-9)

RT_STRING (Type 6) - String Tables

  • Parse STRINGTABLE blocks (16 strings per block)
  • Extract null-terminated UTF-16LE strings
  • Tag with Resource tag
  • Assign medium-high relevance scores (6-8)

RT_DIALOG (Type 5) - Dialog Box Templates

  • Parse DLGTEMPLATE or DLGITEMTEMPLATE structures
  • Extract window titles, control text, and tooltips
  • Handle both DIALOG and DIALOGEX formats
  • Tag with Resource tag
  • Assign medium relevance scores (5-7)

RT_MENU (Type 4) - Menu Resources

  • Parse MENUITEMTEMPLATE structures
  • Extract menu item text strings
  • Tag with Resource tag
  • Assign medium relevance scores (5-7)

3. String Encoding

  • Implement UTF-16LE decoding (resources typically use UTF-16)
  • Handle null-terminated wide strings
  • Convert to UTF-8 for storage in ExtractedString
  • Integrate with existing encoding detection if mixed encodings exist

4. Integration Points

  • Add resource extraction method to PeParser implementation
  • Call during container parsing in parse() method
  • Store extracted strings with StringSource::ResourceString
  • Apply semantic tags: Resource, Version, Manifest
  • Integrate into existing section weighting/scoring system

5. Library Consideration

Option A: Use pelite crate (specialized PE parser with resource support)

  • Pros: Handles resource parsing complexity, well-tested
  • Cons: Adds dependency, may need integration work

Option B: Extend current goblin-based parser manually

  • Pros: No new dependencies, full control
  • Cons: More complex implementation, need to handle edge cases

Recommendation: Start with Option B (manual parsing) leveraging existing goblin::pe::PE structures, add pelite later if complexity warrants.

Acceptance Criteria

  • Parse PE resource directory three-level tree structure (Type → Name → Language)
  • Extract version info fields (FileDescription, ProductName, CompanyName, etc.)
  • Extract manifest XML strings from embedded manifests
  • Handle STRINGTABLE resources with UTF-16LE decoding
  • Extract dialog box template strings (window titles, control text)
  • Extract menu definition strings
  • Apply appropriate semantic tags (Resource, Version, Manifest)
  • Include resource strings in scoring/ranking system with appropriate weights
  • Add unit tests for resource directory parsing
  • Add integration tests using real PE binaries with resources
  • Handle edge cases: missing resources, malformed structures, mixed encodings
  • Document resource extraction in docs/src/binary-formats.md

Implementation Notes

  • Resource extraction should be optional/non-blocking (gracefully handle parse failures)
  • Maintain performance: avoid deep recursion, limit resource tree depth
  • Consider adding CLI flag --resources to enable/disable resource extraction
  • Test with real-world Windows binaries (e.g., notepad.exe, calc.exe)

Related Issues

Note: This issue consolidates and supersedes #5 and #56 with a more comprehensive approach.

References

Activity

  1. added this to the v0.2 milestone on Nov 10, 2025
  2. self-assigned this
    on Nov 10, 2025
  3. traycerai commented on Nov 10, 2025

    @traycerai

    Warning

    Rate limit exceeded. Please try after 265 seconds.

  4. unclesp1d3r commented on Nov 10, 2025

    @unclesp1d3r
    MemberAuthor

    @coderabbitai Enhance this issue body with additional context and a proposed solution. Improve the issue title and assign the proper labels and other metadata.

  5. changed the title [-]Advanced PE Resources Extraction[/-] [+]Extract Strings from PE Resource Directory (Version Info, Manifests, String Tables, Dialogs, Menus)[/+] on Nov 10, 2025
  6. coderabbitai commented on Nov 10, 2025

    @coderabbitai
    Contributor

    Tip

    For best results, initiate chat on the files or code changes.

    🧩 Analysis chain

    🏁 Script executed:

    #!/bin/bash
    
    # Fetch current issue details
    echo "=== Current Issue #57 Details ==="
    gh issue view 57 --json title,body,labels,assignees,milestone,state
    
    echo -e "\n=== Checking PE parser implementation ==="
    # Check if the PE parser file exists and show its structure
    if [ -f "src/container/pe.rs" ]; then
        echo "File exists: src/container/pe.rs"
        head -100 src/container/pe.rs
    else
        echo "File not found: src/container/pe.rs"
        # Search for PE-related files
        fd -e rs pe
    fi
    
    echo -e "\n=== Checking for resource-related code ==="
    rg -n --type rust "resource" -C 2 | head -50
    
    echo -e "\n=== Checking semantic tags ==="
    rg -n --type rust "semantic.*tag|tag.*semantic" -C 2 | head -30
    
    echo -e "\n=== Checking scoring system ==="
    rg -n --type rust "score|scoring|rank" -C 2 | head -30
    

    Length of output: 7330


    🏁 Script executed:

    #!/bin/bash
    
    # Get available labels in the repository
    echo "=== Available Labels ==="
    gh label list --limit 50
    
    echo -e "\n=== Check for related issues/PRs ==="
    gh issue list --search "PE resource" --json number,title,state,labels --limit 10
    
    echo -e "\n=== Check Epic #40 for context ==="
    gh issue view 40 --json title,body,labels
    
    echo -e "\n=== Check project structure ==="
    fd -t d -d 1 .
    
    echo -e "\n=== Check for existing tests related to PE ==="
    fd test | xargs rg -l "pe|PE" 2>/dev/null | head -10
    
    echo -e "\n=== Look at types.rs for Tag enum ==="
    rg -n "enum Tag|pub enum Tag" -A 30 src/types.rs
    

    Length of output: 14093


    🏁 Script executed:

    #!/bin/bash
    
    # Create enhanced issue body
    cat > /tmp/enhanced_issue.md << 'EOF'
    ## Context
    
    Windows PE (Portable Executable) binaries contain a `.rsrc` section with a hierarchical resource directory structure that holds rich metadata and embedded strings. These resources are currently not being extracted by Stringy, resulting in missed opportunities to identify:
    
    - **Version Information**: Product names, company names, file descriptions, copyright strings
    - **Manifest Files**: Embedded XML manifests with assembly information and dependencies
    - **String Tables**: Localized strings stored in `STRINGTABLE` resources
    - **Dialog Boxes**: Control text, window titles, and UI strings
    - **Menu Definitions**: Menu item text and tooltips
    
    The PE resource directory follows a three-level tree structure:
    1. **Type**: Resource type (RT_VERSION, RT_MANIFEST, RT_STRING, RT_DIALOG, etc.)
    2. **Name**: Resource identifier (numeric ID or string name)
    3. **Language**: Language/locale identifier (LCID)
    
    Resources commonly use UTF-16LE encoding, requiring proper string decoding beyond ASCII/UTF-8 extraction.
    
    ## Proposed Solution
    
    ### Implementation Approach
    
    Extend the PE container parser (`src/container/pe.rs`) to parse the resource directory structure and extract strings from high-value resource types:
    
    #### 1. Resource Directory Parsing
    
    - Locate the `.rsrc` section using existing section enumeration
    - Parse the three-level resource directory tree (Type → Name → Language)
    - Navigate resource data entries to locate actual resource data
    - Handle both numeric and string resource identifiers
    
    #### 2. Resource Type Handlers
    
    Implement extraction for the following Win32 resource types:
    
    **RT_VERSION (Type 16)** - Version Information
    - Parse `VS_VERSIONINFO` structure
    - Extract `StringFileInfo` fields:
      - `FileDescription`
      - `ProductName`
      - `CompanyName`
      - `LegalCopyright`
      - `FileVersion`
      - `ProductVersion`
      - `InternalName`
      - `OriginalFilename`
    - Tag with `Version` and `Resource` tags
    - Assign high relevance scores (8-10)
    
    **RT_MANIFEST (Type 24)** - Application Manifest
    - Extract embedded XML manifest
    - Parse manifest for assembly names, dependencies, and configuration strings
    - Tag with `Manifest` and `Resource` tags
    - Assign high relevance scores (7-9)
    
    **RT_STRING (Type 6)** - String Tables
    - Parse `STRINGTABLE` blocks (16 strings per block)
    - Extract null-terminated UTF-16LE strings
    - Tag with `Resource` tag
    - Assign medium-high relevance scores (6-8)
    
    **RT_DIALOG (Type 5)** - Dialog Box Templates
    - Parse `DLGTEMPLATE` or `DLGITEMTEMPLATE` structures
    - Extract window titles, control text, and tooltips
    - Handle both `DIALOG` and `DIALOGEX` formats
    - Tag with `Resource` tag
    - Assign medium relevance scores (5-7)
    
    **RT_MENU (Type 4)** - Menu Resources
    - Parse `MENUITEMTEMPLATE` structures
    - Extract menu item text strings
    - Tag with `Resource` tag
    - Assign medium relevance scores (5-7)
    
    #### 3. String Encoding
    
    - Implement UTF-16LE decoding (resources typically use UTF-16)
    - Handle null-terminated wide strings
    - Convert to UTF-8 for storage in `ExtractedString`
    - Integrate with existing encoding detection if mixed encodings exist
    
    #### 4. Integration Points
    
    - Add resource extraction method to `PeParser` implementation
    - Call during container parsing in `parse()` method
    - Store extracted strings with `StringSource::ResourceString`
    - Apply semantic tags: `Resource`, `Version`, `Manifest`
    - Integrate into existing section weighting/scoring system
    
    #### 5. Library Consideration
    
    **Option A**: Use `pelite` crate (specialized PE parser with resource support)
    - Pros: Handles resource parsing complexity, well-tested
    - Cons: Adds dependency, may need integration work
    
    **Option B**: Extend current `goblin`-based parser manually
    - Pros: No new dependencies, full control
    - Cons: More complex implementation, need to handle edge cases
    
    **Recommendation**: Start with Option B (manual parsing) leveraging existing `goblin::pe::PE` structures, add `pelite` later if complexity warrants.
    
    ## Acceptance Criteria
    
    - [ ] Parse PE resource directory three-level tree structure (Type → Name → Language)
    - [ ] Extract version info fields (`FileDescription`, `ProductName`, `CompanyName`, etc.)
    - [ ] Extract manifest XML strings from embedded manifests
    - [ ] Handle `STRINGTABLE` resources with UTF-16LE decoding
    - [ ] Extract dialog box template strings (window titles, control text)
    - [ ] Extract menu definition strings
    - [ ] Apply appropriate semantic tags (`Resource`, `Version`, `Manifest`)
    - [ ] Include resource strings in scoring/ranking system with appropriate weights
    - [ ] Add unit tests for resource directory parsing
    - [ ] Add integration tests using real PE binaries with resources
    - [ ] Handle edge cases: missing resources, malformed structures, mixed encodings
    - [ ] Document resource extraction in `docs/src/binary-formats.md`
    
    ## Implementation Notes
    
    - Resource extraction should be optional/non-blocking (gracefully handle parse failures)
    - Maintain performance: avoid deep recursion, limit resource tree depth
    - Consider adding CLI flag `--resources` to enable/disable resource extraction
    - Test with real-world Windows binaries (e.g., `notepad.exe`, `calc.exe`)
    
    ## Related Issues
    
    - #4 - Add pelite dependency for PE resource extraction
    - #5 - Implement PE Resource String Extraction (VERSIONINFO, STRINGTABLE, Manifests)
    - #56 - Extract Strings from PE Resource Directory
    
    **Note**: This issue consolidates and supersedes #5 and #56 with a more comprehensive approach.
    
    ## References
    
    - Parent Epic: [Epic: v0.2 - PE Resources, Symbol Demangling & Import/Export Enhancement](https://github.com/EvilBit-Labs/StringyMcStringFace/issues/40)
    - [Microsoft PE Format Specification](https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#the-rsrc-section)
    - [Resource Types Documentation](https://learn.microsoft.com/en-us/windows/win32/menurc/resource-types)
    EOF
    
    # Update the issue with enhanced content
    gh issue edit 57 \
      --title "Extract Strings from PE Resource Directory (Version Info, Manifests, String Tables, Dialogs, Menus)" \
      --body-file /tmp/enhanced_issue.md \
      --add-label "area:analyzer" \
      --add-label "lang:rust" \
      --add-label "needs:tests" \
      --add-label "priority:medium"
    
    echo -e "\n=== Issue updated successfully ==="
    gh issue view 57 --json title,labels,body | jq -r '.title'
    

    Length of output: 197


    @unclesp1d3r I've successfully enhanced issue #57 with comprehensive technical details and proper metadata. Here's what was improved:

    Changes Made

    🏷️ Title Update

    New: "Extract Strings from PE Resource Directory (Version Info, Manifests, String Tables, Dialogs, Menus)"

    • More descriptive and specific about what resources are being extracted

    📋 Enhanced Body Content

    1. Expanded Context

    • Added technical details about PE resource directory structure (three-level tree: Type → Name → Language)
    • Explained specific resource types and their value (RT_VERSION, RT_MANIFEST, RT_STRING, RT_DIALOG, RT_MENU)
    • Highlighted UTF-16LE encoding requirements

    2. Detailed Implementation Approach

    • Resource directory parsing strategy
    • Specific handlers for each Win32 resource type with relevance scores
    • UTF-16LE string decoding requirements
    • Integration points with existing PeParser
    • Library comparison (pelite vs manual parsing with recommendation)

    3. Expanded Acceptance Criteria

    • Added specific resource types to handle
    • Included testing requirements (unit tests + integration tests)
    • Added edge case handling requirements
    • Documentation requirements

    4. Implementation Notes

    • Performance considerations
    • Optional CLI flag suggestion (--resources)
    • Real-world testing recommendations

    5. Cross-References

    🏷️ Labels Added

    • area:analyzer - Binary analyzer functionality
    • lang:rust - Rust implementation
    • needs:tests - Test coverage required
    • priority:medium - Appropriate priority level

    The issue now provides a comprehensive blueprint for implementation with technical specifications, architectural decisions, and clear success criteria. It's ready for development! 🚀

  7. unclesp1d3r commented on Jul 4, 2026

    @unclesp1d3r
    MemberAuthor

    Implemented: PE resource extraction in src/extraction/pe_resources/ (version_info, string_tables, manifests, dialogs/menus via pelite). Closing as completed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions