← Back to Projects

Malware Analysis — Part 6: Static Analysis Part 2 — Strings, YARA, and IOC Extraction

The second half of static analysis — extracting strings from obfuscated binaries with FLOSS, writing YARA rules to detect malware families, using capa for capability mapping, and extracting every indicator of compromise before touching dynamic analysis.

W
WARN

This series covers the analysis of malicious software in controlled, isolated environments. All techniques described are for educational and defensive security purposes only. The author accepts no responsibility for damage to hardware, software, data, or systems resulting from following this guide.

Previous: Part 5 — Static Analysis Part 1: File Identification and PE Structure


Strings in Malware Analysis

Strings are sequences of printable ASCII or Unicode characters embedded in a binary file. They are one of the most valuable sources of intelligence in static analysis because malware authors, like all programmers, leave human-readable text in their code — C2 server addresses, file paths, registry keys, error messages, function names, configuration values.

The challenge is that modern malware almost always obfuscates its strings to defeat simple extraction. Understanding both how to extract strings and how malware authors hide them is essential for meaningful static analysis.

Why Malware Obfuscates Strings

If a malware author leaves a string like http://evil-c2.com/beacon visible in the binary, a security researcher finds it in seconds. The string can be used to:

  • Block the URL in firewalls
  • Write YARA rules that detect any malware communicating with that URL
  • Identify other samples from the same campaign
  • Investigate the infrastructure

To prevent this, malware authors use several techniques:

XOR encoding: Each character is XORed with a key byte before being stored. The binary stores the encoded version, and a small routine decodes it at runtime before using it. A string that should be cmd.exe might be stored as B3 C2 AD B6 B7 B9 (XOR'd with 0x2E).

Stack strings: The string is never stored as a complete string in the binary. Instead, the code constructs it character by character on the stack at runtime: mov [ebp-8], 0x63 (c), mov [ebp-7], 0x6D (m), and so on. Regular string extraction tools miss this entirely.

Encrypted strings: An encryption algorithm (AES, RC4, custom) is used to encrypt all strings. A decryption routine runs at startup.

Split strings: A string is split into fragments stored in different locations and concatenated at runtime.

Simple String Extraction

The built-in strings tool (on Linux/REMnux) or strings2 (on Windows) extracts all printable character sequences of 4+ characters from a binary:

# On REMnux
strings sample.exe | less

# Save to file for analysis
strings sample.exe > strings_output.txt

# Find URLs
strings sample.exe | grep -E "https?://"

# Find IP addresses
strings sample.exe | grep -E "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"

# Unicode strings (malware increasingly uses wide-char strings)
strings -e l sample.exe   # little-endian 16-bit
strings -e b sample.exe   # big-endian 16-bit

Useful things to grep for in strings output:

# Registry paths
strings sample.exe | grep -i "HKEY\|SOFTWARE\|CurrentVersion"

# File paths
strings sample.exe | grep -i "\\\\System32\|\\\\AppData\|\\\\Temp"

# Windows API names (suggests dynamic import resolution)
strings sample.exe | grep -i "LoadLibrary\|GetProcAddress\|VirtualAlloc"

# Common C2 beaconing strings
strings sample.exe | grep -i "beacon\|checkin\|heartbeat\|update"

# Error messages often reveal intent
strings sample.exe | grep -i "error\|fail\|success\|inject"

FLOSS — Extracting Obfuscated Strings

FLOSS (FLARE Obfuscated String Solver) is a tool developed by Mandiant that goes far beyond simple string extraction. FLOSS uses emulation and analysis to extract strings that would only be visible at runtime.

Free: github.com/mandiant/flare-floss

What FLOSS does that regular strings doesn't:

  1. Static strings: Regular visible strings (same as strings tool)
  2. Stack strings: Reconstructs strings built character-by-character on the stack
  3. Tight strings: Decodes strings using simple loops (XOR, ADD, ROL operations)
  4. Decoded strings: Emulates code to extract strings that are decoded by more complex routines

Using FLOSS

# On REMnux
floss sample.exe

# Save output to file
floss sample.exe > floss_output.txt 2>&1

# Filter for specific patterns
floss sample.exe | grep -E "https?://"
floss sample.exe | grep -E "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"

FLOSS output is organized by string type:

FLOSS STATIC STRINGS
====================
[strings found without emulation - same as regular strings tool]
http://legit-looking-domain.com/update
GetProcAddress
VirtualAlloc

FLOSS STACK STRINGS
==================
[strings built on the stack at runtime]
C:\Windows\System32\cmd.exe
SOFTWARE\Microsoft\Windows\CurrentVersion\Run

FLOSS TIGHT STRINGS
==================
[strings decoded by tight loops - XOR and similar]
192.168.0.1
evil-command-server.net

FLOSS DECODED STRINGS
====================
[strings decoded by more complex routines]
Mozilla/5.0 (Windows NT 10.0; Win64; x64)
/api/v2/check-in

The tight and decoded strings are what FLOSS finds that regular tools miss. These are often the most valuable — C2 URLs, API endpoints, encryption keys, configuration parameters.

Practical FLOSS Analysis Tips

FLOSS output can be very large. Focus your review on:

URLs and hostnames:

floss sample.exe | grep -Ei "https?://|\.com|\.net|\.ru|\.cn|\.top"

File system paths:

floss sample.exe | grep -i "C:\\\|%APPDATA%\|%TEMP%\|System32"

Registry keys:

floss sample.exe | grep -i "HKCU\|HKLM\|CurrentVersion\|Run"

Executable names and commands:

floss sample.exe | grep -i "\.exe\|\.dll\|\.ps1\|\.bat\|cmd\|powershell"

Mutex names (often unique to a malware family — searching the mutex name online often reveals the family immediately):

floss sample.exe | grep -i "mutex\|global\\\\"

YARA — The Language of Malware Detection

YARA is a pattern matching tool created by Victor Alvarez at VirusTotal and now maintained as an open source project. It is described as "the pattern matching Swiss knife for malware researchers." Every major security company, AV vendor, and threat intelligence team uses YARA to describe and detect malware families.

Free: virustotal.github.io/yara

Understanding YARA Rules

A YARA rule is a description of a malware sample or family. It consists of:

  • Metadata — information about the rule (author, description, date)
  • Strings — patterns to search for (text strings, byte patterns, regular expressions)
  • Condition — a logical expression that must be true for the rule to match

YARA Rule Syntax

rule RuleName {
    meta:
        description = "Human-readable description"
        author = "Your name"
        date = "2026-09-22"
        malware_family = "ExampleFamily"

    strings:
        // ASCII string (case-sensitive by default)
        $str1 = "evil-server.com"

        // Case-insensitive string
        $str2 = "Mozilla/4.0" nocase

        // Wide-character string (Unicode)
        $str3 = "cmd.exe" wide

        // Both ASCII and Unicode versions
        $str4 = "powershell" ascii wide nocase

        // Hex byte pattern (wildcards with ??)
        $hex1 = { 4D 5A ?? ?? ?? ?? 00 00 }

        // Hex pattern with alternatives
        $hex2 = { (6A 00 | 68 00 00 00 00) FF D0 }

        // Regular expression
        $re1 = /https?:\/\/[a-z0-9]{8,16}\.(com|net|ru)/

    condition:
        // All strings must be present
        all of them

        // At least 2 of the defined strings
        2 of them

        // Specific combination
        $str1 and ($hex1 or $hex2)

        // File size check combined with string
        filesize < 500KB and $str1

        // PE file with specific characteristics
        uint16(0) == 0x5A4D and $str1 // starts with MZ
}

Writing Your First YARA Rule

Let's walk through writing a YARA rule based on static analysis findings. Suppose your analysis of a sample found:

  • A suspicious URL: http://update-service.ddns.net/payload
  • A mutex name: Global\MutexObj12345
  • An unusual User-Agent: Mozilla/4.0 (compatible; MSIE 6.0)
  • Import of VirtualAllocEx and WriteProcessMemory

Your YARA rule:

rule Backdoor_ExampleFamily_v1 {
    meta:
        description = "Detects ExampleFamily backdoor based on network and injection indicators"
        author = "p@nos"
        date = "2026-09-22"
        reference = "Analysis of sample SHA256:..."
        tlp = "WHITE"

    strings:
        $c2_url     = "update-service.ddns.net" nocase
        $mutex      = "Global\\MutexObj12345" wide ascii
        $useragent  = "Mozilla/4.0 (compatible; MSIE 6.0)" nocase
        $inject1    = "VirtualAllocEx" ascii
        $inject2    = "WriteProcessMemory" ascii

    condition:
        uint16(0) == 0x5A4D and       // Must be a PE file (MZ header)
        filesize < 2MB and             // Reasonable size limit
        (
            $c2_url or
            $mutex or
            ($inject1 and $inject2 and $useragent)
        )
}

Running YARA Rules

# Scan a single file
yara rule.yar sample.exe

# Scan with verbose output (show matched strings)
yara -s rule.yar sample.exe

# Scan a directory recursively
yara -r rule.yar /path/to/samples/

# Use multiple rule files
yara rules1.yar rules2.yar sample.exe

# Scan a directory with all .yar files in a rules directory
yara -r /path/to/rules/*.yar /path/to/samples/

Using Public YARA Rule Repositories

You don't need to write all rules yourself — the community has shared thousands:

YARA-Rules Project — github.com/Yara-Rules/rules A community collection organized by malware category.

Signature-Base by Florian Roth — github.com/Neo23x0/signature-base One of the most respected community YARA rule collections. Florian Roth (Nextron Systems) is a prolific rule writer in the malware analysis community.

Elastic Security Detection Rules — github.com/elastic/detection-rules Detection rules from Elastic's security team including YARA rules.

Malpedia YARA Rules — malpedia.caad.fkie.fraunhofer.de A malware encyclopedia with YARA rules for documented malware families.

# Clone signature-base on REMnux
git clone https://github.com/Neo23x0/signature-base
cd signature-base

# Scan a sample against all rules
yara -r yara/ /path/to/samples/ 2>/dev/null

YARA Rule Quality — What Makes a Good Rule

A YARA rule is only as good as its specificity. Bad rules either miss samples (too specific) or produce false positives (too broad). Key principles:

Use multiple conditions: A rule that matches on a single common string will produce enormous false positives. Rules that require several conditions together are much more precise.

Test against benign files: Always run new rules against a collection of known-clean files before deploying them. A rule that matches notepad.exe is useless and misleading.

Anchor with PE header check: uint16(0) == 0x5A4D (MZ header check) ensures the rule only matches PE files, immediately excluding text files, images, PDFs, and other formats from matching.

Use file size bounds: Packers and rebuilds often change file size. Adding filesize < 1MB or filesize > 100KB prevents matching obvious mismatches.


capa — Capability Detection

capa (free, Mandiant) automatically identifies what a program is capable of by analyzing the binary statically and mapping findings to the MITRE ATT&CK framework.

Free: github.com/mandiant/capa

Running capa

# On REMnux or Windows
capa sample.exe

# Verbose output with matched evidence
capa -v sample.exe

# Output as JSON (useful for scripting)
capa --json sample.exe > capa_output.json

# Check against specific ATT&CK technique
capa -t T1055 sample.exe

Reading capa Output

+----------------------------+------+-----------------------+
| CAPABILITY                 | MBC  | ATT&CK                |
+----------------------------+------+-----------------------+
| inject thread              |      | T1055.001             |
| create process             |      | T1059                 |
| enumerate processes        |      | T1057                 |
| write file                 |      | T1565                 |
| modify registry            |      | T1112                 |
| persist via run keys       |      | T1547.001             |
| communicate via HTTP       |      | T1071.001             |
| decode data using XOR      |      |                       |
| contain anti-disassembly   |      |                       |
+----------------------------+------+-----------------------+

Each row tells you a specific capability the binary has. This is your analysis roadmap — you know what to look for in dynamic analysis and what to confirm in reverse engineering.

What each ATT&CK technique means:

ATT&CK IDTechniqueSignificance
T1055Process InjectionMalware hiding in other processes
T1547.001Boot or Logon Autostart via Run KeysPersistence
T1071.001C2 via HTTPNetwork-based command and control
T1082System Information DiscoveryReconnaissance/fingerprinting
T1057Process DiscoveryLooking at running processes
T1112Modify RegistryConfiguration or persistence
T1140Deobfuscate/Decode FilesUnpacking or decryption

IOC Extraction and Documentation

An Indicator of Compromise (IOC) is a piece of evidence that suggests a system has been compromised or that a file is malicious. During static analysis, you extract IOCs that can be:

  • Used to detect the malware on other systems
  • Shared with threat intelligence platforms
  • Added to firewall and DNS blocklists
  • Used to search SIEM logs for past infections

Categories of IOCs from Static Analysis

File IOCs:

MD5:    abc123...
SHA1:   def456...
SHA256: 789ghi...
File size: 245,760 bytes
File name: update.exe (note: filenames are unreliable - use hashes)

Network IOCs:

URLs:
  http://evil-server.com/beacon
  http://backup-server.net/check-in

Domains:
  evil-server.com
  backup-server.net
  dga-generated-domain.ru

IP Addresses:
  185.220.101.45  (resolve from identified domains)
  192.99.142.226

User-Agents:
  Mozilla/4.0 (compatible; MSIE 6.0)

Host IOCs:

Registry keys:
  HKCU\Software\Microsoft\Windows\CurrentVersion\Run\UpdateService

File paths:
  C:\Users\%USERNAME%\AppData\Roaming\Microsoft\svchost32.exe
  C:\Windows\Temp\payload.dll

Mutex names:
  Global\MutexObj12345
  (unique per sample - excellent detection indicator)

Service names:
  WindowsUpdateHelper

IOC Documentation Format

Adopt a consistent format for IOC documentation. Here's a simple template:

## IOCs — ExampleFamily Sample

**Analysis date:** 2026-09-22
**Sample SHA256:** abc123...

### File Indicators
| Type | Value |
|------|-------|
| MD5 | [value] |
| SHA256 | [value] |
| Size | 245,760 bytes |
| Compiler | Visual C++ 2019 |
| Packer | None |

### Network Indicators
| Type | Value | Confidence |
|------|-------|-----------|
| C2 URL | http://evil-server.com/beacon | High |
| C2 domain | evil-server.com | High |
| C2 IP | 185.220.101.45 | Medium (may rotate) |
| User-Agent | Mozilla/4.0... | High |

### Host Indicators
| Type | Value | Confidence |
|------|-------|-----------|
| Registry run key | HKCU\...\Run\UpdateService | High |
| Drop path | %APPDATA%\Microsoft\svchost32.exe | High |
| Mutex | Global\MutexObj12345 | High |
| Service | WindowsUpdateHelper | Medium |

Sharing IOCs Responsibly

Before sharing IOCs publicly:

  • Verify they are actually malicious (not from legitimate software)
  • Consider TLP (Traffic Light Protocol) classification:
    • TLP:WHITE — may be shared publicly
    • TLP:GREEN — may be shared within the community
    • TLP:AMBER — limited sharing within organizations
    • TLP:RED — not for disclosure
  • Share through appropriate channels: MalwareBazaar, MISP, your ISAC, or threat intelligence platforms

Document Analysis — Malicious Office Files and PDFs

Not all malware comes as a .exe file. A significant portion of malware delivered via phishing uses malicious documents:

Malicious Office Documents

What they are: Word documents, Excel spreadsheets, or PowerPoint presentations that contain malicious macros (VBA code) or exploit document parsing vulnerabilities.

Analysis tools on REMnux:

# oledump — analyze OLE-format Office files (.doc, .xls, .ppt)
oledump.py malicious.doc

# List streams in the document
oledump.py -s malicious.doc

# Extract a specific stream
oledump.py -s 7 --vbadecompress malicious.doc

# For newer Office XML formats (.docx, .xlsx)
# These are actually ZIP archives
unzip malicious.docx -d extracted/
cat extracted/word/document.xml

oletools suite (pre-installed on REMnux) provides additional tools:

# Check for macros
olevba malicious.doc

# Check for suspicious indicators
mraptor malicious.doc

# Analyze Excel formulas
xlmdeobfuscator -f malicious.xls

Malicious PDFs

PDFs can contain JavaScript, embedded executables, and exploit code.

# pdf-parser — examine PDF structure
pdf-parser.py malicious.pdf

# pdfid — quick triage of suspicious PDF features
pdfid.py malicious.pdf

# Suspicious features to look for:
# /JavaScript or /JS — embedded JavaScript
# /Launch — can launch external applications
# /EmbeddedFile — contains an embedded file
# /OpenAction — actions performed when PDF opens
# /RichMedia — can embed Flash or other content

Static Analysis Summary — What You Now Know

After completing Parts 5 and 6, you can perform a complete static analysis of a Windows malware sample:

  1. Identify the file type regardless of extension
  2. Compute and verify hashes and check threat intelligence
  3. Examine PE structure — headers, sections, entropy
  4. Read the import table and understand what the malware is capable of
  5. Detect packing and know how to approach unpacking
  6. Extract strings — both visible and obfuscated via FLOSS
  7. Identify capabilities systematically with capa
  8. Write YARA rules to detect the sample and related variants
  9. Extract and document IOCs ready for sharing or detection

This is more than most organizations' Level 1 and Level 2 SOC analysts can do. The next parts — dynamic analysis and reverse engineering — build on this foundation.


Verification Checklist

  • FLOSS installed and runs against a sample file
  • You understand the difference between static, stack, and decoded strings
  • YARA installed (yara --version shows output)
  • You've written at least one YARA rule manually
  • You've run a public YARA rule set against a sample
  • capa installed and you understand its output format
  • You've pulled the Yara-Rules or signature-base repository on REMnux
  • You understand what an IOC is and the different categories
  • You have an IOC documentation template ready to use

Previous: Part 5 — Static Analysis Part 1: File Identification and PE Structure Next: Part 7 — Dynamic Analysis Part 1: Behavioral Monitoring