Repository navigation
Description
Overview
This task implements a YARA rule formatter for StringyMcStringFace that outputs extracted strings in valid YARA rule syntax. YARA is a widely-used pattern matching tool in malware research and incident response, making YARA-compatible output a critical feature for security analysts who want to create detection rules from extracted strings.
Context
The binary analyzer currently extracts strings from ELF, PE, and Mach-O binaries with rich metadata including:
- Encoding types (ASCII, UTF-8, UTF-16LE, UTF-16BE)
- Semantic tags (URLs, domains, IPs, file paths, etc.)
- Offsets, RVAs, and section information
- Relevance scores
To maximize utility for security practitioners, we need to format this data as valid YARA rules that can be immediately used for threat hunting and detection.
Technical Requirements
1. String Escaping
Implement proper C-style escaping for YARA text strings:
- Escape double quotes:
\" - Escape backslashes:
\\ - Escape newlines:
\n - Escape carriage returns:
\r - Escape tabs:
\t - Non-printable bytes:
\xNN(hex notation)
2. Encoding Mapping
Map FoundString encoding types to YARA string modifiers:
Encoding::Ascii/Encoding::Utf8→ascii(default)Encoding::Utf16Le/Encoding::Utf16Be→widemodifier- Consider adding
ascii widefor broader matching when appropriate
3. String Truncation
Apply truncation rules for excessively long strings:
- Maximum string length: 256 bytes (configurable)
- Truncate with indicator comment (e.g.,
// truncated from N bytes) - Consider hex string format for binary data or very long strings
4. Semantic Tag Integration
Leverage semantic tags to enhance rule conditions:
- Group strings by tag type in rule conditions
- Add metadata comments indicating tag classifications
- Generate compound conditions (e.g.,
any of ($url*))
5. Rule Structure
Generate complete, valid YARA rules:
rule binary_name_strings {
meta:
description = "Extracted strings from binary_name"
format = "ELF/PE/MachO"
generated_by = "StringyMcStringFace"
strings:
$s1 = "extracted_string" ascii
$s2 = "wide_string" wide
$url1 = "https://example.com" nocase
condition:
any of them
}Proposed Implementation
File: src/output/yara.rs
pub struct YaraFormatter {
max_string_length: usize,
include_metadata: bool,
rule_name: String,
}
impl YaraFormatter {
pub fn format_rule(&self, strings: &[FoundString], binary_info: &ContainerInfo) -> String;
fn escape_string(&self, s: &str) -> String;
fn get_string_modifiers(&self, string: &FoundString) -> Vec<&str>;
fn truncate_if_needed(&self, s: &str) -> (String, bool);
fn generate_condition(&self, strings: &[FoundString]) -> String;
}Module Registration: src/output/mod.rs
pub mod yara;
pub enum OutputFormat {
Json,
Yara,
// ... other formats
}
pub trait Formatter {
fn format(&self, strings: &[FoundString], info: &ContainerInfo) -> String;
}Example Output
Given extracted strings from a binary, the formatter should produce:
rule suspicious_binary_strings {
meta:
description = "Strings extracted from suspicious.exe"
format = "PE"
generated_by = "StringyMcStringFace v0.1"
extracted_count = 47
strings:
// URLs and network indicators
$url1 = "http://malicious.example.com/payload" nocase
$ip1 = "192.168.1.100" ascii
// File paths
$path1 = "C:\\Windows\\System32\\evil.dll" nocase
// Wide strings (UTF-16)
$wide1 = "WideString" wide
// Import/Export names
$imp1 = "CreateRemoteThread" ascii
$imp2 = "VirtualAllocEx" ascii
condition:
any of ($url*) or
2 of ($imp*) or
any of ($path*)
}Test Scenarios
Unit tests should cover:
-
String Escaping
- Quotes, backslashes, newlines in strings
- Non-ASCII characters (hex escape)
- Already-escaped content (no double-escaping)
-
Encoding Handling
- ASCII strings →
asciimodifier - UTF-16LE/BE →
widemodifier - Mixed encoding in single rule
- ASCII strings →
-
Truncation
- Strings under limit → no truncation
- Strings over limit → truncated with comment
- Extreme cases (empty strings, very long strings)
-
Rule Generation
- Valid YARA syntax (parseable by YARA)
- Proper section formatting (meta, strings, condition)
- Special characters in rule names
-
Semantic Tags
- URLs grouped and commented
- Network indicators (IPs, domains)
- Import/Export grouping
Dependencies
- Blocked by: Output Formatting Framework (Implement Output Formatter Framework with Trait-Based Architecture #25)
- Need base
OutputFormatenum andFormattertrait - May proceed with initial implementation if framework is defined
- Need base
Acceptance Criteria
-
src/output/yara.rsimplementsYaraFormatter - All special characters properly escaped per YARA specification
- Encoding types correctly mapped to YARA modifiers
- Long strings truncated at configurable threshold
- Generated rules pass YARA syntax validation
- Comprehensive unit tests with >90% coverage
- Integration test with sample binaries (ELF, PE, Mach-O)
- Documentation with usage examples
References
Related Issues
- Output Formatting Framework (dependency)
- Requirement 6.3 implementation
Task ID: stringy-analyzer/yara-friendly-output
Activity
unclesp1d3r commentedon Nov 10, 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.
[-]YARA-Friendly Output[/-][+]Implement YARA Rule Output Formatter with String Escaping and Modifiers[/+]traycerai commentedon Nov 10, 2025
Plan
Observations
The codebase has a well-defined structure with all necessary types in
src/types.rs. Thesrc/output/mod.rsmodule is currently empty and ready for the output framework. The project usesserdefor serialization,thiserrorfor errors, andinstafor snapshot testing. The extraction modules already returnVec<FoundString>with complete metadata including encoding, tags, source, offset, RVA, and section information. The documentation clearly describes the expected YARA output format with proper escaping, modifiers, and rule structure.Approach
Implement a two-layer solution: (1) Define the output formatting framework with
OutputFormatenum andFormattertrait insrc/output/mod.rs, and (2) ImplementYaraFormatterinsrc/output/yara.rswith proper string escaping, encoding-to-modifier mapping, truncation logic, semantic tag grouping, and complete YARA rule generation. The formatter will be configurable via aYaraConfigstruct and will generate valid YARA rules that can be immediately used for threat hunting.Reasoning
I explored the codebase structure, examined existing types and extraction modules, reviewed documentation for YARA output requirements, researched YARA string escaping specifications, and analyzed the testing patterns used in the project. I confirmed that all necessary data structures exist and the output module is ready for implementation.
Proposed File Changes
📄 src/output/mod.rs (MODIFY) 🔗
📄 src/output/yara.rs (NEW) 🔗
📄 tests/yara_formatter_integration.rs (NEW) 🔗
📄 src/lib.rs (MODIFY) 🔗
📄 README.md (MODIFY) 🔗
Diagram
sequenceDiagram participant User participant YaraFormatter participant Escaper participant ModifierMapper participant RuleGenerator User->>YaraFormatter: format(strings, container_info) YaraFormatter->>YaraFormatter: Filter by min_score YaraFormatter->>YaraFormatter: Group strings by tags loop For each string YaraFormatter->>Escaper: escape_string(text) Escaper-->>YaraFormatter: escaped_text YaraFormatter->>ModifierMapper: get_string_modifiers(encoding, tags) ModifierMapper-->>YaraFormatter: ["ascii"/"wide", "nocase"] YaraFormatter->>YaraFormatter: truncate_if_needed(text, max_len) end YaraFormatter->>RuleGenerator: generate_rule_header(rule_name) YaraFormatter->>RuleGenerator: generate_meta_section(container_info) YaraFormatter->>RuleGenerator: generate_strings_section(grouped_strings) YaraFormatter->>RuleGenerator: generate_condition(grouped_strings) RuleGenerator-->>YaraFormatter: Complete YARA rule YaraFormatter-->>User: Result<String>Import In IDE
🤖 Prompt for AI Agents
Developer Humor
Execution Information
Branch: main
Commit: baf4526
💡 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
coderabbitai commentedon Nov 10, 2025
Tip
For best results, initiate chat on the files or code changes.
🧩 Analysis chain
🏁 Script executed:
Length of output: 1766
🏁 Script executed:
Length of output: 5904
🌐 Web query:
💡 Result:
Short summary — how to escape strings in YARA:
Text (double‑quoted) strings: use C‑style escapes. Escape double quote and backslash with a backslash (" and \). Other supported escapes: \n, \r, \t and hex byte \xNN (where NN are two hex digits). Use these when you need literal control characters or to include quotes/backslashes. (yara.readthedocs.io)
Hex (curly‑brace) strings: enclosed in { ... } and represent raw bytes; do not use C escapes inside — specify bytes in hex (e.g. { 41 42 43 }), with wildcards (?) , ranges/jumps ([n] or [n-m]) and alternatives ((AA|BB)). (deepwiki.com)
Regular expressions in YARA follow PCRE‑like rules: use backslash to escape regex metacharacters when needed. (yara.readthedocs.io)
Notes:
Sources:
[1] YARA documentation — Writing YARA rules (text strings, escapes). (yara.readthedocs.io)
[2] YARA grammar / hex string syntax summary. (deepwiki.com)
[3] YARA regex/escape behavior (PCRE‑like). (yara.readthedocs.io)
Citations:
🌐 Web query:
💡 Result:
Quick summary of YARA text/regex string modifiers and how they behave:
ascii — match the plain ASCII form (default for non-wide). Use with wide to include both forms (e.g., "foo" wide ascii). [1][2]
wide — match the UTF‑16/2‑byte form produced by interleaving 0x00 bytes (e.g., "A" matches 41 00). Does not handle full UTF‑16 multibyte characters beyond simple interleaving. Can be combined with ascii and nocase. [1][2]
fullword — require the matched string be delimited by non‑alphanumeric characters (so "domain" fullword won’t match inside "mydomain"). Cannot be used with base64/base64wide. [1][2]
nocase — case‑insensitive matching for text and regex. Cannot be combined with xor, base64, or base64wide. Works with wide/ascii/fullword. [1][2]
Examples
Notes / restrictions
Sources: YARA official docs (writing rules / string modifiers) and YARA‑X text patterns docs. [1][2]
🏁 Script executed:
Length of output: 6365
@unclesp1d3r I've successfully enhanced issue #28! Here's what was updated:
Changes Made
📝 Updated Title
"Implement YARA Rule Output Formatter with String Escaping and Modifiers"
📋 Enhanced Issue Body
Added comprehensive sections including:
Overview & Context - Explains YARA's importance in malware analysis and how it fits into StringyMcStringFace's architecture
Technical Requirements - Five detailed sections covering:
\",\\,\n,\r,\t,\xNN)Proposed Implementation - Concrete API design for
YaraFormatterwith key methods:format_rule()- Main entry pointescape_string()- Handle special charactersget_string_modifiers()- Map encodings to YARA modifierstruncate_if_needed()- Handle long stringsgenerate_condition()- Build rule conditionsExample Output - Shows realistic YARA rule with:
Test Scenarios - Five comprehensive test categories with specific cases
Acceptance Criteria - Clear checklist with 8 measurable items
References - Links to official YARA documentation
🏷️ Metadata Status
The issue already had excellent metadata:
area:analyzer,type:enhancement,status:backlog,lang:rust,needs:testsNo changes were needed to labels or assignments.
The issue is now ready for implementation with clear technical specifications, example code structure, and comprehensive test requirements! 🎯
🐰✨
(Ready to help security analysts turn extracted strings into detection rules!)
traycerai commentedon Nov 12, 2025
I have updated the Implementation Plan to reflect the recent changes in the ticket.
unclesp1d3r commentedon Jul 4, 2026
Implemented: YARA rule formatter with escaping/modifiers in src/output/yara/ (--yara). Closing as completed.