Skip to content

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

Closed

Description

@unclesp1d3r

Context

Windows PE (Portable Executable) binaries contain a resource section () with rich metadata and embedded strings that are currently not being extracted by Stringy. While the PE parser already identifies resource sections and assigns them high weight (9.0), it does not parse the internal resource directory structure to extract the actual strings contained within.

The PE resource section uses a hierarchical directory structure with three levels:

  • Type - Resource type (e.g., RT_VERSION, RT_MANIFEST, RT_STRING, RT_DIALOG, RT_MENU)
  • Name/ID - Resource name or numeric identifier
  • Language - Language ID for localization

Current State

The existing PE parser (src/container/pe.rs) already:

  • ✅ Identifies the .rsrc section with SectionType::Resources
  • ✅ Assigns high weight (9.0) to resource sections
  • ✅ Extracts import/export tables
  • ✅ Has semantic tags defined (Tag::Resource, Tag::Version, Tag::Manifest)
  • ✅ Has StringSource::ResourceString variant in types

What's Missing:

  • ❌ Parsing the PE resource directory structure
  • ❌ Extracting version information fields
  • ❌ Extracting manifest XML content
  • ❌ Processing STRINGTABLE resources
  • ❌ Extracting strings from dialog and menu definitions

Proposed Solution

1. Resource Directory Parsing

Implement a resource directory parser that traverses the hierarchical structure within the .rsrc section:

// Parse resource directory tree
fn parse_resource_directory(&self, pe: &PE, data: &[u8]) -> Vec<ResourceEntry> {
    // Navigate Type → Name → Language hierarchy
    // Extract resource data for relevant types
}

2. Version Information Extraction

Parse RT_VERSION resources (VS_VERSIONINFO structure):

  • Fixed version info: File/product versions, flags, OS, file type
  • Variable version info (StringFileInfo):
    • FileDescription - File purpose/description
    • ProductName - Product name
    • CompanyName - Company/publisher
    • LegalCopyright - Copyright notice
    • OriginalFilename - Original file name
    • InternalName - Internal component name
    • FileVersion / ProductVersion - Version strings

Semantic tagging: Tag::Version, Tag::Resource
Scoring: Assign high scores (8.0-10.0) as these are high-signal strings

3. Manifest Extraction

Parse RT_MANIFEST resources (embedded XML):

  • Extract manifest as XML string
  • Optionally extract specific fields:
    • Assembly identity (name, version, architecture)
    • Requested execution level
    • Compatibility information
    • Dependencies

Semantic tagging: Tag::Manifest, Tag::Resource
Scoring: High score (8.0-9.0) for manifest strings

4. String Table Resources

Parse RT_STRING resources:

  • String tables contain 16 strings per block
  • Strings are length-prefixed UTF-16LE
  • Used for UI strings, error messages, prompts

Semantic tagging: Tag::Resource
Scoring: Medium-high score (6.0-7.0)

5. Dialog and Menu Definitions

Parse RT_DIALOG and RT_MENU resources:

  • Extract window titles, button labels, menu items
  • Parse dialog templates (DLGTEMPLATE / DLGTEMPLATEEX)
  • Parse menu templates (MENUITEMTEMPLATE)

Semantic tagging: Tag::Resource
Scoring: Medium score (5.0-6.0)

Implementation Considerations

Using goblin Crate

The project uses goblin for PE parsing. Check its capabilities:

  • Does goblin expose resource directory parsing?
  • May need to implement custom resource parsing if goblin doesn't support it
  • Resource directories are referenced via IMAGE_DIRECTORY_ENTRY_RESOURCE in the PE optional header

Error Handling

  • Resource sections may be malformed or obfuscated
  • Handle missing or invalid resource entries gracefully
  • Validate resource directory offsets and sizes to prevent out-of-bounds reads

Unicode Handling

  • Most PE resources use UTF-16LE encoding
  • Version info and string tables are UTF-16LE
  • Manifests are typically UTF-8 XML

Performance

  • Resource parsing should be efficient for large binaries
  • Consider lazy parsing or optional flags to enable/disable resource extraction
  • Balance thoroughness with performance for deeply nested resource structures

Acceptance Criteria

  • Parse PE resource directory structure (Type → Name → Language hierarchy)
  • Extract version info fields (FileDescription, ProductName, CompanyName, FileVersion, etc.)
  • Extract manifest XML strings from RT_MANIFEST resources
  • Handle RT_STRING (STRINGTABLE) resources with length-prefixed UTF-16LE strings
  • Extract strings from RT_DIALOG and RT_MENU resources
  • Add appropriate semantic tagging (Tag::Resource, Tag::Version, Tag::Manifest)
  • Include resource strings in scoring/ranking system with appropriate weights
  • Add unit tests for resource parsing logic
  • Add integration tests with real PE binaries containing resources
  • Handle malformed or missing resource sections gracefully
  • Document resource extraction in user-facing documentation

Technical References

  • PE Format Specification: Microsoft PE and COFF Specification
  • Resource Directory: IMAGE_RESOURCE_DIRECTORY structure
  • Version Resources: VS_VERSIONINFO structure
  • String Tables: RT_STRING resource format
  • goblin Documentation: Check for resource directory support

Related Files

  • src/container/pe.rs - PE parser implementation
  • src/types.rs - Type definitions (Tag, StringSource, SectionType)
  • tests/integration_pe.rs - Integration tests for PE parsing

References

Parent Epic: Epic: v0.2 - PE Resources, Symbol Demangling & Import/Export Enhancement

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 519 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)[/+] 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 the current issue details
    echo "=== Current Issue #56 Details ==="
    gh issue view 56 --json title,body,labels,assignees,milestone,state
    
    echo -e "\n=== Epic #40 Details ==="
    gh issue view 40 --json title,body,labels
    
    echo -e "\n=== Available Repository Labels ==="
    gh label list --limit 100
    
    echo -e "\n=== Repository Structure ==="
    fd -t f -e rs | head -20
    
    echo -e "\n=== Check for PE parser ==="
    fd -t f "pe.rs"
    

    Length of output: 9038


    🏁 Script executed:

    #!/bin/bash
    
    # Examine the current PE parser implementation
    echo "=== PE Parser Implementation ==="
    cat src/container/pe.rs
    
    echo -e "\n=== PE Integration Tests ==="
    cat tests/integration_pe.rs
    
    echo -e "\n=== Check for existing resource handling ==="
    rg -n "resource" src/container/pe.rs tests/integration_pe.rs
    
    echo -e "\n=== Check types.rs for semantic tags ==="
    cat src/types.rs | head -100
    

    Length of output: 16764


    🏁 Script executed:

    #!/bin/bash
    
    # Update the issue with enhanced body, title, and labels
    gh issue edit 56 \
      --title "Extract Strings from PE Resource Directory (Version Info, Manifests, String Tables, Dialogs)" \
      --body "## Context
    
    Windows PE (Portable Executable) binaries contain a resource section (`.rsrc`) with rich metadata and embedded strings that are currently not being extracted by Stringy. While the PE parser already identifies resource sections and assigns them high weight (9.0), it does not parse the internal resource directory structure to extract the actual strings contained within.
    
    The PE resource section uses a hierarchical directory structure with three levels:
    - **Type** - Resource type (e.g., RT_VERSION, RT_MANIFEST, RT_STRING, RT_DIALOG, RT_MENU)
    - **Name/ID** - Resource name or numeric identifier
    - **Language** - Language ID for localization
    
    ## Current State
    
    The existing PE parser (\`src/container/pe.rs\`) already:
    - ✅ Identifies the \`.rsrc\` section with \`SectionType::Resources\`
    - ✅ Assigns high weight (9.0) to resource sections
    - ✅ Extracts import/export tables
    - ✅ Has semantic tags defined (\`Tag::Resource\`, \`Tag::Version\`, \`Tag::Manifest\`)
    - ✅ Has \`StringSource::ResourceString\` variant in types
    
    **What's Missing:**
    - ❌ Parsing the PE resource directory structure
    - ❌ Extracting version information fields
    - ❌ Extracting manifest XML content
    - ❌ Processing STRINGTABLE resources
    - ❌ Extracting strings from dialog and menu definitions
    
    ## Proposed Solution
    
    ### 1. Resource Directory Parsing
    
    Implement a resource directory parser that traverses the hierarchical structure within the \`.rsrc\` section:
    
    \`\`\`rust
    // Parse resource directory tree
    fn parse_resource_directory(&self, pe: &PE, data: &[u8]) -> Vec<ResourceEntry> {
        // Navigate Type → Name → Language hierarchy
        // Extract resource data for relevant types
    }
    \`\`\`
    
    ### 2. Version Information Extraction
    
    Parse \`RT_VERSION\` resources (VS_VERSIONINFO structure):
    - **Fixed version info**: File/product versions, flags, OS, file type
    - **Variable version info (StringFileInfo)**:
      - \`FileDescription\` - File purpose/description
      - \`ProductName\` - Product name
      - \`CompanyName\` - Company/publisher
      - \`LegalCopyright\` - Copyright notice
      - \`OriginalFilename\` - Original file name
      - \`InternalName\` - Internal component name
      - \`FileVersion\` / \`ProductVersion\` - Version strings
    
    **Semantic tagging**: \`Tag::Version\`, \`Tag::Resource\`  
    **Scoring**: Assign high scores (8.0-10.0) as these are high-signal strings
    
    ### 3. Manifest Extraction
    
    Parse \`RT_MANIFEST\` resources (embedded XML):
    - Extract manifest as XML string
    - Optionally extract specific fields:
      - Assembly identity (name, version, architecture)
      - Requested execution level
      - Compatibility information
      - Dependencies
    
    **Semantic tagging**: \`Tag::Manifest\`, \`Tag::Resource\`  
    **Scoring**: High score (8.0-9.0) for manifest strings
    
    ### 4. String Table Resources
    
    Parse \`RT_STRING\` resources:
    - String tables contain 16 strings per block
    - Strings are length-prefixed UTF-16LE
    - Used for UI strings, error messages, prompts
    
    **Semantic tagging**: \`Tag::Resource\`  
    **Scoring**: Medium-high score (6.0-7.0)
    
    ### 5. Dialog and Menu Definitions
    
    Parse \`RT_DIALOG\` and \`RT_MENU\` resources:
    - Extract window titles, button labels, menu items
    - Parse dialog templates (DLGTEMPLATE / DLGTEMPLATEEX)
    - Parse menu templates (MENUITEMTEMPLATE)
    
    **Semantic tagging**: \`Tag::Resource\`  
    **Scoring**: Medium score (5.0-6.0)
    
    ## Implementation Considerations
    
    ### Using goblin Crate
    
    The project uses \`goblin\` for PE parsing. Check its capabilities:
    - Does goblin expose resource directory parsing?
    - May need to implement custom resource parsing if goblin doesn't support it
    - Resource directories are referenced via \`IMAGE_DIRECTORY_ENTRY_RESOURCE\` in the PE optional header
    
    ### Error Handling
    
    - Resource sections may be malformed or obfuscated
    - Handle missing or invalid resource entries gracefully
    - Validate resource directory offsets and sizes to prevent out-of-bounds reads
    
    ### Unicode Handling
    
    - Most PE resources use UTF-16LE encoding
    - Version info and string tables are UTF-16LE
    - Manifests are typically UTF-8 XML
    
    ### Performance
    
    - Resource parsing should be efficient for large binaries
    - Consider lazy parsing or optional flags to enable/disable resource extraction
    - Balance thoroughness with performance for deeply nested resource structures
    
    ## Acceptance Criteria
    
    - [ ] Parse PE resource directory structure (Type → Name → Language hierarchy)
    - [ ] Extract version info fields (\`FileDescription\`, \`ProductName\`, \`CompanyName\`, \`FileVersion\`, etc.)
    - [ ] Extract manifest XML strings from \`RT_MANIFEST\` resources
    - [ ] Handle \`RT_STRING\` (STRINGTABLE) resources with length-prefixed UTF-16LE strings
    - [ ] Extract strings from \`RT_DIALOG\` and \`RT_MENU\` resources
    - [ ] Add appropriate semantic tagging (\`Tag::Resource\`, \`Tag::Version\`, \`Tag::Manifest\`)
    - [ ] Include resource strings in scoring/ranking system with appropriate weights
    - [ ] Add unit tests for resource parsing logic
    - [ ] Add integration tests with real PE binaries containing resources
    - [ ] Handle malformed or missing resource sections gracefully
    - [ ] Document resource extraction in user-facing documentation
    
    ## Technical References
    
    - **PE Format Specification**: [Microsoft PE and COFF Specification](https://docs.microsoft.com/en-us/windows/win32/debug/pe-format)
    - **Resource Directory**: IMAGE_RESOURCE_DIRECTORY structure
    - **Version Resources**: VS_VERSIONINFO structure
    - **String Tables**: RT_STRING resource format
    - **goblin Documentation**: Check for resource directory support
    
    ## Related Files
    
    - \`src/container/pe.rs\` - PE parser implementation
    - \`src/types.rs\` - Type definitions (Tag, StringSource, SectionType)
    - \`tests/integration_pe.rs\` - Integration tests for PE parsing
    
    ## References
    
    Parent Epic: [Epic: v0.2 - PE Resources, Symbol Demangling & Import/Export Enhancement](https://github.com/EvilBit-Labs/StringyMcStringFace/issues/40)"
    
    echo "Issue body updated successfully!"
    
    # Add labels
    gh issue edit 56 --add-label "area:analyzer,lang:rust,needs:tests,priority:medium"
    
    echo "Labels added successfully!"
    

    Length of output: 227


    🏁 Script executed:

    #!/bin/bash
    
    # Verify the updated issue
    echo "=== Updated Issue #56 ==="
    gh issue view 56 --json title,labels,assignees,milestone | jq -r '
      "Title: \(.title)",
      "",
      "Labels:",
      (.labels[] | "  - \(.name)"),
      "",
      "Assigned to: \(.assignees[].login)",
      "Milestone: \(.milestone.title)"
    '
    
    echo -e "\n=== Issue URL ==="
    echo "https://github.com/EvilBit-Labs/StringyMcStringFace/issues/56"
    

    Length of output: 341


    @unclesp1d3r I've successfully enhanced issue #56 with comprehensive technical details and proper metadata! Here's what was updated:

    📝 Changes Made

    Title Enhancement

    Before: "Advanced PE Resources Extraction"
    After: "Extract Strings from PE Resource Directory (Version Info, Manifests, String Tables, Dialogs)"

    The new title is more specific and clearly describes the scope of work.

    Issue Body Enhancements

    1. Added "Current State" Section - Documents what's already implemented in the PE parser (resource section identification, semantic tags, etc.) vs. what's missing (actual parsing)

    2. Expanded Proposed Solution with detailed subsections:

      • Resource Directory Parsing (Type → Name → Language hierarchy)
      • Version Information Extraction (VS_VERSIONINFO structure details)
      • Manifest Extraction (embedded XML handling)
      • String Table Resources (length-prefixed UTF-16LE strings)
      • Dialog and Menu Definitions
    3. Added Implementation Considerations:

      • goblin crate capabilities and limitations
      • Error handling for malformed resources
      • Unicode handling (UTF-16LE vs UTF-8)
      • Performance considerations
    4. Enhanced Acceptance Criteria - More specific and testable items including unit tests, integration tests, and documentation

    5. Added Technical References - Links to Microsoft PE specification, resource structures, and related documentation

    6. Added Related Files Section - Points to relevant source files for implementation

    Labels Added

    • area:analyzer - Binary analyzer functionality
    • lang:rust - Rust implementation
    • needs:tests - Requires test coverage
    • priority:medium - Medium priority task

    Preserved Metadata

    • ✅ Assigned to: unclesp1d3r
    • ✅ Milestone: v0.2
    • ✅ Original enhancement label

    🔗 View the updated issue: #56

    The issue is now much more actionable with clear technical guidance for implementing PE resource extraction!

    (\\_/)
    (^.^)  *thinking about PE resources*
    (")_(")
    
  7. unclesp1d3r commented on Jul 4, 2026

    @unclesp1d3r
    MemberAuthor

    Implemented: PE resource extraction in src/extraction/pe_resources/ (version_info, string_tables, manifests, detection + tests). Duplicate of #57. 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