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.
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-bitUseful 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:
- Static strings: Regular visible strings (same as
stringstool) - Stack strings: Reconstructs strings built character-by-character on the stack
- Tight strings: Decodes strings using simple loops (XOR, ADD, ROL operations)
- 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
VirtualAllocExandWriteProcessMemory
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/nullYARA 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.exeReading 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 ID | Technique | Significance |
|---|---|---|
| T1055 | Process Injection | Malware hiding in other processes |
| T1547.001 | Boot or Logon Autostart via Run Keys | Persistence |
| T1071.001 | C2 via HTTP | Network-based command and control |
| T1082 | System Information Discovery | Reconnaissance/fingerprinting |
| T1057 | Process Discovery | Looking at running processes |
| T1112 | Modify Registry | Configuration or persistence |
| T1140 | Deobfuscate/Decode Files | Unpacking 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.xmloletools 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.xlsMalicious 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 contentStatic Analysis Summary — What You Now Know
After completing Parts 5 and 6, you can perform a complete static analysis of a Windows malware sample:
- Identify the file type regardless of extension
- Compute and verify hashes and check threat intelligence
- Examine PE structure — headers, sections, entropy
- Read the import table and understand what the malware is capable of
- Detect packing and know how to approach unpacking
- Extract strings — both visible and obfuscated via FLOSS
- Identify capabilities systematically with capa
- Write YARA rules to detect the sample and related variants
- 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 --versionshows 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