Repository navigation
Description
Summary
Implement robust UTF-16LE (Little Endian) string extraction capability to properly handle wide character strings commonly found in Windows PE binaries, .NET assemblies, and resource sections. This is a critical feature for analyzing Windows executables where UTF-16LE is the dominant string encoding.
Context
UTF-16LE strings are ubiquitous in Windows binaries:
- PE Resources: VERSIONINFO, STRINGTABLE, RT_MANIFEST all use UTF-16LE
- .NET Metadata: String literals in managed assemblies
- Windows API Strings: Wide character (WCHAR) strings in native code
- Registry Paths: Many internal registry references
The standard strings command often mangles UTF-16 strings or extracts them as ASCII with null bytes interleaved, making them difficult to read and classify. Proper UTF-16LE extraction will significantly improve Stringy's effectiveness on Windows binaries.
Technical Background
UTF-16LE Detection Heuristics
UTF-16LE strings can be detected using the following heuristics:
- Even-length byte sequences (UTF-16 uses 2 bytes per character)
- Low byte is printable ASCII (0x20-0x7E)
- High byte is mostly zero (for basic multilingual plane characters)
- Null termination pattern: Two consecutive zero bytes (0x00 0x00)
Confidence Scoring
To avoid false positives from coincidental byte patterns:
- High confidence (>90%): >90% printable characters with proper null termination
- Medium confidence (70-90%): >70% printable, reasonable length (>5 chars)
- Low confidence (<70%): >50% printable, may be coincidental data
Requirements
Core Functionality
- Create
src/extraction/utf16.rsmodule with UTF-16LE extraction logic - Implement
extract_utf16le_strings(data: &[u8], config: &ExtractionConfig) -> Vec<RawString> - Support configurable minimum character length (default: 3 characters = 6 bytes)
- Implement confidence scoring algorithm
- Handle proper null termination detection (0x00 0x00 sequence)
- Return strings with accurate offset, length, and encoding metadata
Configuration
- Add
min_utf16_len: usizetoExtractionConfig(default: 3) - Add
utf16_min_confidence: f32threshold (default: 0.7) - Support section-aware minimum length overrides
Integration
- Integrate UTF-16LE extraction into main extraction pipeline
- Wire up UTF-16LE extractor in
src/extraction/mod.rs - Ensure UTF-16LE strings are properly passed to classification module
- Add UTF-16LE support to deduplication logic
Testing
- Unit tests for basic UTF-16LE string extraction
- Test cases for confidence scoring (high, medium, low)
- Test handling of null termination
- Test minimum length filtering
- Test false positive rejection (random binary data)
- Test with real-world Windows PE samples
- Edge cases: partial strings at section boundaries, interleaved data
Proposed Implementation
File Structure
// src/extraction/utf16.rs
use crate::types::{Encoding, FoundString, StringSource};
/// Configuration for UTF-16LE extraction
pub struct Utf16Config {
pub min_char_len: usize,
pub min_confidence: f32,
}
/// Raw UTF-16LE string candidate with confidence score
struct Utf16Candidate {
data: Vec<u8>,
offset: usize,
char_count: usize,
confidence: f32,
}
/// Extract UTF-16LE strings from binary data
pub fn extract_utf16le_strings(
data: &[u8],
config: &Utf16Config,
section_name: Option<String>,
) -> Vec<FoundString> {
// Implementation based on algorithm in docs/src/string-extraction.md
// 1. Scan for even-offset sequences with printable low bytes
// 2. Calculate confidence scores
// 3. Filter by minimum length and confidence
// 4. Convert to FoundString with proper metadata
}
/// Calculate confidence score for a UTF-16LE candidate
fn calculate_confidence(data: &[u8]) -> f32 {
// Percentage of valid printable UTF-16LE characters
// Bonus for proper null termination
// Penalty for excessive high bytes or invalid patterns
}
/// Check if a UTF-16LE character is printable
fn is_printable_utf16le_char(low: u8, high: u8) -> bool {
// Basic multilingual plane printable characters
high == 0 && (0x20..=0x7E).contains(&low) || low == b'\n' || low == b'\r' || low == b'\t'
}Algorithm Pseudocode
for each even offset i in data:
candidate_start = i
char_count = 0
printable_count = 0
while i + 1 < data.len():
low_byte = data[i]
high_byte = data[i + 1]
if is_printable_utf16le_char(low_byte, high_byte):
char_count += 1
printable_count += 1
i += 2
else if low_byte == 0 && high_byte == 0:
# Null terminator found
break
else:
# Invalid character, end of string
break
if char_count >= min_char_len:
confidence = printable_count / char_count
if confidence >= min_confidence:
extract and add to results
Acceptance Criteria
✅ UTF-16LE strings are correctly extracted from Windows PE binaries
✅ Confidence scoring prevents false positives from random binary data
✅ Minimum length filtering is configurable and working
✅ Extracted strings include accurate offset, length, and encoding metadata
✅ Null termination is properly detected and handled
✅ Unit tests achieve >90% code coverage for the utf16.rs module
✅ Integration tests pass with real PE binary samples
✅ Documentation is updated in docs/src/string-extraction.md
Example Use Cases
VERSIONINFO Extraction from PE
$ stringy example.exe --encoding utf16le
[UTF-16LE] Microsoft Corporation
[UTF-16LE] Example Application
[UTF-16LE] Copyright © 2024
.NET String Literal Detection
$ stringy dotnet_app.dll --encoding utf16le --min-length 5
[UTF-16LE] Configuration string value
[UTF-16LE] Error message text
Dependencies
- Blocked by: String Extraction Framework (basic extraction infrastructure must be in place)
- Blocks: UTF-16BE String Extraction (can reuse confidence scoring logic)
- Related: PE Resource Parsing (will benefit from UTF-16LE extraction)
References
- Implementation algorithm:
docs/src/string-extraction.md(UTF-16 Extraction section) - Type definitions:
src/types.rs(Encoding::Utf16Le already defined) - Similar extraction: Study
src/extraction/ascii.rsfor pattern (when implemented)
Task Metadata
- Component: stringy-analyzer
- Module: extraction/utf16
- Estimated Complexity: Medium
- Estimated Time: 4-6 hours (implementation + tests)
Task-ID: stringy-analyzer/utf16le-string-extraction
Activity
unclesp1d3r commentedon Sep 30, 2025
@coderabbitai Enhance this issue body with additional context and a proposed solution. Improve the issue title and assign the proper labels and other metadata.
coderabbitai commentedon Sep 30, 2025
✨ Issue enhanced with detailed technical context, implementation guidance, and acceptance criteria. Ready for implementation when the String Extraction Framework is complete.
[-]UTF-16LE String Extraction[/-][+]Implement UTF-16LE String Extraction with Confidence Scoring and Minimum Length Filtering[/+]coderabbitai commentedon Sep 30, 2025
Tip
For best results, initiate chat on the files or code changes.
🧩 Analysis chain
🏁 Script executed:
Length of output: 1313
🏁 Script executed:
Length of output: 404
🏁 Script executed:
Length of output: 8592
🏁 Script executed:
Length of output: 7019
🏁 Script executed:
Length of output: 5091
🏁 Script executed:
Length of output: 147
@unclesp1d3r I've successfully enhanced issue #11! Here's what was improved:
🎯 Title Enhancement
Before: "UTF-16LE String Extraction"
After: "Implement UTF-16LE String Extraction with Confidence Scoring and Minimum Length Filtering"
📝 Body Enhancements
Added Comprehensive Sections:
Key Technical Details Added:
src/extraction/utf16.rs🏷️ Metadata Status
The existing labels are already appropriate and remain unchanged:
area:analyzer- Correct componenttype:enhancement- Appropriate typestatus:backlog- Current statuslang:rust- Implementation languageneeds:tests- Testing requirement flaggedAssignment to you (@unclesp1d3r) is maintained.
The issue is now ready for implementation with clear guidance, acceptance criteria, and technical specifications! 🚀
unclesp1d3r commentedon Nov 13, 2025
@traycerai generate
traycerai commentedon Nov 13, 2025
Hi @unclesp1d3r, I have updated the Implementation Plan to reflect the recent changes in the ticket.
traycerai commentedon Nov 13, 2025
Plan
Observations
The codebase has a well-structured extraction framework with:
Existing Infrastructure: ASCII extractor (
src/extraction/ascii.rs) serves as the reference implementation with comprehensive testing and noise filtering integration.Configuration Ready:
ExtractionConfigalready hasmin_wide_lengthfield (default: 3) for UTF-16 strings, and theEncoding::Utf16Leenum variant exists intypes.rs.Noise Filtering: The
CompositeNoiseFilterinsrc/extraction/filters.rsoperates on decoded UTF-8 text (thetextfield ofFoundString), so it will work seamlessly with UTF-16LE strings after decoding.UTF-16LE Decoding: The
decode_utf16lefunction already exists insrc/extraction/pe_resources.rsand can be reused or adapted for the new UTF-16LE extractor.Integration Pattern: The
BasicExtractor::extract_from_sectionmethod insrc/extraction/mod.rsorchestrates extraction by calling specialized extractors (ASCII, UTF-8) and applying noise filtering with confidence thresholds.Testing Pattern: Comprehensive unit tests in
tests/test_ascii_extraction.rsprovide a clear template for UTF-16LE tests.Approach
Create a new
src/extraction/utf16.rsmodule implementing UTF-16LE string extraction with confidence scoring, following the established ASCII extractor pattern. The module will provideextract_utf16le_strings()for raw extraction andextract_from_section()for section-aware extraction with metadata population. Integration intoBasicExtractor::extract_from_section()will check forEncoding::Utf16Leinenabled_encodingsand apply the same noise filtering pipeline used for ASCII/UTF-8. Configuration will use the existingmin_wide_lengthfield and addutf16_min_confidencetoExtractionConfig. Comprehensive unit tests will cover basic extraction, confidence scoring, null termination, edge cases, and integration with section metadata.Reasoning
I explored the codebase structure by listing directories, reading key files including type definitions, extraction modules (ASCII, filters, PE resources), configuration structures, and test files. I examined the existing ASCII extractor pattern, noise filtering infrastructure, UTF-16LE decoding in PE resources, and the BasicExtractor integration point. I searched for UTF-16 references to understand current usage and verified the configuration fields and dependencies in Cargo.toml.
Proposed File Changes
📄 src/extraction/utf16.rs (NEW) 🔗
📄 src/extraction/mod.rs (MODIFY) 🔗
📄 src/lib.rs (MODIFY) 🔗
📄 tests/test_utf16_extraction.rs (NEW) 🔗
📄 tests/integration_extraction.rs (MODIFY) 🔗
📄 docs/src/string-extraction.md (MODIFY) 🔗
Diagram
sequenceDiagram participant User participant BasicExtractor participant Utf16Module as utf16.rs participant NoiseFilter participant FoundString User->>BasicExtractor: extract_from_section(data, section, config) BasicExtractor->>BasicExtractor: Check if Utf16Le in enabled_encodings alt UTF-16LE enabled BasicExtractor->>Utf16Module: extract_from_section(section, data, config) Utf16Module->>Utf16Module: Extract section data slice Utf16Module->>Utf16Module: extract_utf16le_strings(data, config) loop For each even offset Utf16Module->>Utf16Module: Scan for printable UTF-16LE chars Utf16Module->>Utf16Module: Detect null termination (0x00 0x00) Utf16Module->>Utf16Module: Calculate confidence score alt Meets min_char_len & min_confidence Utf16Module->>Utf16Module: Decode to UTF-8 String Utf16Module->>FoundString: Create with Encoding::Utf16Le end end Utf16Module->>NoiseFilter: calculate_confidence(text, context) NoiseFilter-->>Utf16Module: confidence score alt confidence >= threshold Utf16Module->>Utf16Module: Adjust offsets, populate metadata Utf16Module-->>BasicExtractor: Vec<FoundString> end BasicExtractor->>BasicExtractor: Extend found_strings end BasicExtractor-->>User: All extracted stringsImport In IDE
🤖 Prompt for AI Agents
Developer Humor
Execution Information
Branch: main
Commit: c50e9b6
💡 Tips
Supported Commands (Inside Comments)
@traycerai generateto iterate on the previous version of the implementation plan.Supported Commands (Inside Description)
@traycerai ignoreanywhere in the ticket description to prevent this ticket from being processed.@traycerai branch:<branch-name>anywhere in the ticket description to specify the target branch for the implementation plan.Community