strings [OPTION]... [FILE]...
strings -n MIN_LENGTH [FILE]
strings -a [FILE]
strings -t {d|o|x} [FILE]
The strings command extracts printable character sequences (strings) from binary files. By default, it finds sequences of at least 4 printable ASCII characters terminated by a non-printable character. This seemingly simple utility is invaluable for examining compiled programs, libraries, firmware images, memory dumps, and any binary data that might contain embedded text.
Strings is a fundamental tool in security analysis, reverse engineering, malware investigation, forensics, and data recovery. It can reveal hardcoded passwords, API keys, URLs, error messages, debug strings, copyright notices, and other textual artifacts embedded in binary files. While strings doesn't execute or disassemble code, it provides quick insight into what a binary might do or contain. Modern forensics, incident response, and security research would be significantly more difficult without this essential utility. The command works on executables, libraries, core dumps, disk images, memory captures, and any file containing binary data mixed with text.
# Extract strings from a binary
strings /bin/ls
# Extract strings from a library
strings /lib/x86_64-linux-gnu/libc.so.6
# Show strings with minimum length of 8
strings -n 8 /bin/bash
# Extract strings from multiple files
strings /usr/bin/* | head -50
# Count strings in a binary
strings /bin/ls | wc -l
# Find specific patterns
strings /bin/ls | grep -i color
# Look for URLs
strings application.bin | grep -E 'https?://'
# Find potential API keys (example pattern)
strings app.exe | grep -E '[A-Za-z0-9]{32,}'
# Extract and sort unique strings
strings program.bin | sort -u
# Look for version information
strings /usr/bin/gcc | grep -i version
# Find error messages
strings application | grep -i error
# Search for file paths
strings binary | grep '^/'
# Look for email addresses
strings app | grep -E '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'
# Practical: quick binary analysis
echo "=== Binary Analysis: /bin/ls ==="
echo "Total strings: $(strings /bin/ls | wc -l)"
echo "Long strings (>20 chars): $(strings -n 20 /bin/ls | wc -l)"
echo ""
echo "Interesting strings:"
strings /bin/ls | grep -E '(error|warning|invalid|failed|permission)' | head -5
# From /bin/ls:
/lib64/ld-linux-x86-64.so.2
libc.so.6
stdout
error
invalid option
cannot access
Permission denied
--color
--time-style
GNU coreutils
# Binary analysis output:
=== Binary Analysis: /bin/ls ===
Total strings: 847
Long strings (>20 chars): 142
Interesting strings:
cannot access %s: %s
error reading directory
invalid argument
Permission denied
invalid option
Default minimum length is 4 characters. Increase with -n to reduce noise. Common patterns: URLs (http://), paths (/usr/, C:\), error messages, version strings. strings reveals what text is embedded in binaries without executing them - safe for malware analysis.
# Show decimal offsets
strings -t d /bin/ls | head -10
# Show hexadecimal offsets (most common)
strings -t x /bin/ls | head -10
# Show octal offsets
strings -t o /bin/ls | head -10
# Combine with longer minimum length
strings -n 10 -t x /bin/bash | head -20
# Find specific string and show offset
strings -t x /bin/ls | grep "color"
# Show offsets for potential secrets
strings -t x application.bin | grep -i password
# Locate version string
strings -t x /usr/bin/gcc | grep -i "gcc version"
# Export with offsets for analysis
strings -t x suspicious.exe > strings_with_offsets.txt
# Find string at specific offset (reverse lookup)
# If we know offset 0x1234, verify what's there
strings -t x binary | grep "^1234"
# Compare string locations between files
diff <(strings -t x file1.bin) <(strings -t x file2.bin)
# Practical: forensic analysis
cat > analyze_binary.sh << 'EOF'
#!/bin/bash
BINARY="$1"
echo "String Location Analysis: $BINARY"
echo "=================================="
echo ""
echo "High-offset strings (likely in data section):"
strings -t x "$BINARY" | awk '$1 > "10000"' | head -10
echo ""
echo "Low-offset strings (likely in header/code):"
strings -t x "$BINARY" | awk '$1 < "1000"' | head -10
echo ""
echo "Suspicious patterns with locations:"
strings -t x "$BINARY" | grep -iE '(password|secret|key|token|api)' | head -10
EOF
chmod +x analyze_binary.sh
./analyze_binary.sh /bin/ls
# Decimal offsets (-t d):
792 /lib64/ld-linux-x86-64.so.2
1024 GNU
1536 libc.so.6
2048 stdout
# Hexadecimal offsets (-t x):
318 /lib64/ld-linux-x86-64.so.2
400 GNU
600 libc.so.6
800 stdout
a20 --color
b40 --time-style
# Finding specific string:
a20 --color
a28 --color=auto
# Analysis output:
String Location Analysis: /bin/ls
==================================
High-offset strings (likely in data section):
14a20 cannot access %s
14b30 error reading %s
15040 invalid option
Low-offset strings (likely in header/code):
318 /lib64/ld-linux-x86-64.so.2
400 GNU
600 libc.so.6
The -t flag shows offsets: d=decimal, x=hexadecimal, o=octal. Hexadecimal is most common for binary analysis. Offsets help locate strings in hex editors or disassemblers. Low offsets often contain headers/metadata, high offsets contain data. Use offsets to correlate strings with specific file sections.
# Default: scan only data sections
strings /bin/ls | wc -l
# Scan entire file with -a
strings -a /bin/ls | wc -l
# Compare the difference
echo "Data sections only: $(strings /bin/ls | wc -l)"
echo "Entire file: $(strings -a /bin/ls | wc -l)"
# Scan entire binary file
strings -a suspicious.bin > all_strings.txt
# Find strings only in code sections (entire file minus data sections)
comm -13 \
<(strings /bin/bash | sort) \
<(strings -a /bin/bash | sort) \
> code_section_strings.txt
# Scan disk image or memory dump (always use -a)
strings -a disk.img | grep -i password
# Scan partition
strings -a /dev/sda1 | grep -E 'filename|document' | head -20
# Data recovery from corrupted file
strings -a corrupted_file.doc | grep -A 5 -B 5 "important data"
# Memory dump analysis
strings -a memory_dump.raw | grep -i "malware"
# Scan entire core dump
strings -a core.12345 > core_strings.txt
# Compare scanning methods
cat > compare_scan.sh << 'EOF'
#!/bin/bash
FILE="$1"
echo "Scan Comparison: $FILE"
echo "===================="
DATA_COUNT=$(strings "$FILE" | wc -l)
FULL_COUNT=$(strings -a "$FILE" | wc -l)
DIFF=$((FULL_COUNT - DATA_COUNT))
echo "Data sections only: $DATA_COUNT strings"
echo "Entire file: $FULL_COUNT strings"
echo "Additional in code sections: $DIFF strings"
echo ""
echo "Sample strings only in code sections:"
comm -13 \
<(strings "$FILE" | sort | head -100) \
<(strings -a "$FILE" | sort | head -100) \
| head -5
EOF
chmod +x compare_scan.sh
./compare_scan.sh /bin/ls
# Clean up
rm -f compare_scan.sh code_section_strings.txt
# Default vs -a comparison:
Data sections only: 847
Entire file: 1523
# Detailed comparison:
Scan Comparison: /bin/ls
====================
Data sections only: 847 strings
Entire file: 1523 strings
Additional in code sections: 676 strings
Sample strings only in code sections:
__cxa_finalize
__errno_location
__fprintf_chk
__libc_start_main
__stack_chk_fail
# From disk image:
important_document.pdf
mypassword123
confidential_report.docx
backup_2025.tar.gz
# Memory dump:
malware.exe
C:\Windows\Temp\
http://malicious-site.com/
Process injection detected
Default strings scans only initialized data sections (.data, .rodata) of object files. The -a flag scans the entire file including code (.text), headers, and all sections. Always use -a for: disk images, memory dumps, unknown file types, data recovery, and forensic analysis. ELF/PE aware vs raw scanning.
# Default: 7-bit ASCII
strings program.exe
# Include 8-bit characters (extended ASCII)
strings -e S program.exe
# UTF-16 little-endian (Windows binaries)
strings -e l program.exe
# UTF-16 big-endian
strings -e b program.exe
# Extract all encoding types
strings -e s program.exe # 7-bit
strings -e S program.exe # 8-bit
strings -e l program.exe # UTF-16 LE
strings -e b program.exe # UTF-16 BE
# Combine all encodings
{
strings -e s program.exe
strings -e S program.exe
strings -e l program.exe
strings -e b program.exe
} | sort -u > all_strings.txt
# Windows executable analysis (UTF-16 common)
strings -e l windows_app.exe | grep -i error
# Look for Unicode strings
strings -e l app.dll | head -20
# Mixed encoding analysis
cat > extract_all_encodings.sh << 'EOF'
#!/bin/bash
FILE="$1"
echo "Encoding Analysis: $FILE"
echo "========================"
echo ""
echo "ASCII (7-bit) strings:"
strings -e s "$FILE" | wc -l
echo "Extended ASCII (8-bit) strings:"
strings -e S "$FILE" | wc -l
echo "UTF-16 LE strings:"
strings -e l "$FILE" | wc -l
echo "UTF-16 BE strings:"
strings -e b "$FILE" | wc -l
echo ""
echo "Sample UTF-16 LE strings:"
strings -e l "$FILE" | head -10
EOF
chmod +x extract_all_encodings.sh
# Analyze Windows PE file
./extract_all_encodings.sh windows_program.exe
# Find Unicode URLs
strings -e l app.dll | grep -E 'https?://'
# Extract localized strings (often UTF-16)
strings -e l localized_app.exe | \
grep -E '[\x80-\xFF]' | \
head -20
# Compare ASCII vs UTF-16 content
echo "ASCII unique strings:"
strings -e s binary | sort -u | wc -l
echo "UTF-16 LE unique strings:"
strings -e l binary | sort -u | wc -l
# Clean up
rm -f extract_all_encodings.sh all_strings.txt
# Encoding options:
-e s : 7-bit ASCII (default for most Unix tools)
-e S : 8-bit extended ASCII
-e l : UTF-16 little-endian (Windows)
-e b : UTF-16 big-endian
# Windows executable analysis:
Encoding Analysis: windows_program.exe
========================
ASCII (7-bit) strings: 234
Extended ASCII (8-bit) strings: 267
UTF-16 LE strings: 1847
UTF-16 BE strings: 12
Sample UTF-16 LE strings:
Microsoft Corporation
Windows Error Reporting
Error accessing file
Invalid parameter
File not found
Access denied
System.dll
kernel32.dll
# UTF-16 LE URLs from DLL:
http://www.microsoft.com/
https://update.windows.com/
https://login.live.com/
Windows binaries typically use UTF-16 LE (-e l). Unix/Linux binaries use ASCII (-e s/S). Use -e l for .exe, .dll files. Combine multiple encodings to catch all strings. UTF-16 doubles the minimum length needed (8 bytes = 4 characters). Always check UTF-16 when analyzing Windows malware or applications.
# Quick triage of suspicious binary
cat > security_triage.sh << 'EOF'
#!/bin/bash
BINARY="$1"
echo "========================================="
echo "Security Triage: $(basename "$BINARY")"
echo "========================================="
echo ""
echo "=== Network Indicators ==="
echo "IP addresses:"
strings -a "$BINARY" | \
grep -oE '\b([0-9]{1,3}\.){3}[0-9]{1,3}\b' | \
sort -u | head -10
echo ""
echo "URLs:"
strings -a "$BINARY" | \
grep -oE 'https?://[a-zA-Z0-9./?=_%:-]*' | \
head -10
echo ""
echo "Domain names:"
strings -a "$BINARY" | \
grep -oE '[a-zA-Z0-9.-]+\.(com|net|org|edu|gov)' | \
sort -u | head -10
echo ""
echo "=== File Operations ==="
strings -a "$BINARY" | \
grep -iE '(CreateFile|OpenFile|WriteFile|DeleteFile|CopyFile)' | \
head -5
echo ""
echo "=== Registry Operations (Windows) ==="
strings -a "$BINARY" | \
grep -iE '(RegOpenKey|RegSetValue|RegDeleteKey|HKEY_)' | \
head -5
echo ""
echo "=== Process Operations ==="
strings -a "$BINARY" | \
grep -iE '(CreateProcess|OpenProcess|TerminateProcess|inject)' | \
head -5
echo ""
echo "=== Suspicious Keywords ==="
strings -a "$BINARY" | \
grep -iE '(password|admin|root|exploit|payload|shell|cmd\.exe)' | \
head -10
echo ""
echo "=== Crypto/Encoding ==="
strings -a "$BINARY" | \
grep -iE '(base64|encrypt|decrypt|crypto|cipher|AES|RSA)' | \
head -5
echo ""
echo "=== User Agents ==="
strings -a "$BINARY" | \
grep -i "User-Agent:" | head -3
EOF
chmod +x security_triage.sh
# Run triage on binary
./security_triage.sh suspicious.exe
# Look for hardcoded credentials
strings -a app.exe | grep -iE '(password|passwd|pwd).{0,20}[:=]'
# Find potential C2 (Command & Control) servers
strings -a malware.bin | \
grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}:[0-9]+' | \
sort -u
# Extract Windows API calls
strings -a suspicious.dll | \
grep -E '^[A-Z][a-z]+[A-Z][a-zA-Z]*$' | \
sort -u | \
head -20
# Find file paths (potential targets)
echo "=== Potential Target Files ==="
strings -a ransomware.exe | grep -E '\.(doc|pdf|jpg|xlsx|ppt)' | head -10
# Look for persistence mechanisms
strings -a malware.exe | \
grep -iE '(startup|run|service|schedule|task)' | \
head -10
# Extract environment variables accessed
strings -a binary | \
grep -E '%[A-Z_]+%|$[A-Z_]+' | \
sort -u
# Find debug/error messages
strings -a app.exe | \
grep -iE '^(error|warning|debug|info):' | \
head -10
# Create full report
cat > malware_analysis.sh << 'EOF'
#!/bin/bash
SAMPLE="$1"
REPORT="${SAMPLE}.strings_report.txt"
{
echo "Strings Analysis Report"
echo "Sample: $SAMPLE"
echo "Date: $(date)"
echo "MD5: $(md5sum "$SAMPLE" | awk '{print $1}')"
echo "======================================"
echo ""
echo "ALL STRINGS:"
strings -a "$SAMPLE"
echo ""
echo "UTF-16 STRINGS:"
strings -a -e l "$SAMPLE"
} > "$REPORT"
echo "Report saved: $REPORT"
EOF
chmod +x malware_analysis.sh
# Clean up
rm -f security_triage.sh malware_analysis.sh
=========================================
Security Triage: suspicious.exe
=========================================
=== Network Indicators ===
IP addresses:
192.168.1.100
10.0.0.5
172.16.0.1
URLs:
http://malicious-site.com/payload
https://command-control.net/api
http://download.badsite.org/update
Domain names:
malicious-site.com
command-control.net
update-server.org
=== File Operations ===
CreateFileA
WriteFile
DeleteFileW
CopyFileA
=== Registry Operations (Windows) ===
RegOpenKeyEx
RegSetValueEx
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
=== Process Operations ===
CreateProcess
OpenProcess
Process injection complete
shellcode
=== Suspicious Keywords ===
admin
password123
cmd.exe
shell
exploit
payload
backdoor
=== Crypto/Encoding ===
base64_encode
AES_encrypt
decrypt_data
Never execute unknown binaries! Use strings for static analysis only. Strings can reveal malicious intent but sophisticated malware may obfuscate strings. This is initial triage - not comprehensive analysis. Always use in isolated environment. Combine with other tools (file, objdump, IDA) for full analysis.
# Recover text from corrupted document
strings -a corrupted_document.docx | grep -v "^.$" > recovered_text.txt
# Extract data from disk image
strings -a -n 8 disk.img | grep -i "confidential" > recovered_data.txt
# Scan partition for deleted files
sudo strings -a /dev/sda1 | \
grep -E '\.(txt|doc|pdf)' | \
head -20
# Memory dump analysis
strings -a memory.dmp | \
grep -E 'password|username|email' | \
sort -u > credentials_found.txt
# Recover email addresses from damaged drive
sudo strings -a /dev/sdb | \
grep -oE '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' | \
sort -u > recovered_emails.txt
# Extract URLs from browser cache
strings -a cache_file | \
grep -oE 'https?://[^ ]+' | \
head -50
# Recover phone numbers
strings -a data.bin | \
grep -oE '\(?[0-9]{3}\)?[-.\s]?[0-9]{3}[-.\s]?[0-9]{4}' | \
sort -u
# Find credit card numbers (for forensics only!)
strings -a suspicious.img | \
grep -oE '\b[0-9]{4}[- ]?[0-9]{4}[- ]?[0-9]{4}[- ]?[0-9]{4}\b' | \
head -10
# Carve files from raw partition
cat > carve_strings.sh << 'EOF'
#!/bin/bash
DEVICE="$1"
OUTPUT_DIR="strings_carved"
mkdir -p "$OUTPUT_DIR"
echo "Carving strings from $DEVICE"
# Extract potential filenames
sudo strings -a "$DEVICE" | \
grep -E '\.(txt|doc|pdf|jpg|png|exe)$' | \
sort -u > "$OUTPUT_DIR/filenames.txt"
# Extract email content
sudo strings -a "$DEVICE" | \
grep -i "From:" -A 20 | \
head -100 > "$OUTPUT_DIR/email_fragments.txt"
# Extract source code fragments
sudo strings -a "$DEVICE" | \
grep -E '(function|class|import|include)' | \
head -100 > "$OUTPUT_DIR/code_fragments.txt"
echo "Results in $OUTPUT_DIR/"
EOF
chmod +x carve_strings.sh
# Recover data from USB drive
# sudo ./carve_strings.sh /dev/sdc1
# Extract metadata from image files in disk
strings -a photo.jpg | \
grep -iE '(Camera|Model|DateTime|GPS|Software)' | \
head -20
# Find remaining fragments of deleted file
strings -a -t x disk.img | \
grep "important document" | \
awk '{print $1}' # Shows hex offsets
# Timeline analysis from logs on damaged drive
sudo strings -a /dev/sda | \
grep -E '[0-9]{4}-[0-9]{2}-[0-9]{2}' | \
sort -u | \
head -50
# Recover configuration data
strings -a damaged_config.bin | \
grep -E '(server|host|port|database|username)' > recovered_config.txt
# Clean up
rm -f carve_strings.sh recovered_*.txt
# Recovered text from corrupted Word doc:
Project Timeline
Q1 Goals and Objectives
Budget Allocation
Team Assignments
Critical Deliverables
# From disk image:
confidential_report_2025.pdf
C:\Users\John\Documents\Confidential\
Project_Secret_Files\
password_list.txt
# Email addresses recovered:
john.doe@company.com
admin@internal.net
support@vendor.org
contact@client.com
# URLs from cache:
https://banking.com/login
https://email.company.com/inbox
https://drive.company.com/files
https://internal-wiki.net/projects
# Metadata from image:
Camera Make: Canon
Camera Model: EOS 5D Mark IV
DateTime: 2025:12:14 10:30:45
GPS Latitude: 42.3601
GPS Longitude: -71.0589
Software: Adobe Photoshop CS6
Scanning raw devices requires root/admin privileges. Always work on images, not live systems when possible. strings recovers fragments, not complete files. Results may contain sensitive data - handle appropriately. For professional forensics, use dedicated tools (Autopsy, EnCase) alongside strings. Never modify original evidence!
# Analyze router firmware
strings -a -n 6 firmware.bin | head -100
# Find hardcoded credentials
strings -a firmware.bin | \
grep -iE '(admin|root|password|default)' | \
grep -E '.{4,}[:=]' | \
head -20
# Extract version information
strings -a firmware.bin | \
grep -iE 'version|v[0-9]+\.[0-9]+|build' | \
head -10
# Find filesystem paths
strings -a firmware.bin | \
grep '^/' | \
sort -u | \
head -30
# Look for web interface strings
strings -a firmware.bin | \
grep -E '(\.html|\.js|\.css|\.php)' | \
head -20
# Extract potential backdoor indicators
cat > analyze_firmware.sh << 'EOF'
#!/bin/bash
FIRMWARE="$1"
echo "Firmware Analysis: $(basename "$FIRMWARE")"
echo "=========================================="
echo ""
echo "=== Device Information ==="
strings -a "$FIRMWARE" | \
grep -iE '(vendor|manufacturer|model|device)' | \
head -10
echo ""
echo "=== Network Services ==="
strings -a "$FIRMWARE" | \
grep -iE '(telnet|ssh|http|ftp|tftp)' | \
sort -u | \
head -10
echo ""
echo "=== Default Credentials ==="
strings -a "$FIRMWARE" | \
grep -iE '(user.*pass|admin.*pass|default)' | \
head -10
echo ""
echo "=== Listening Ports ==="
strings -a "$FIRMWARE" | \
grep -oE ':[0-9]{2,5}' | \
sort -u | \
head -15
echo ""
echo "=== Command Injection Risks ==="
strings -a "$FIRMWARE" | \
grep -E '(system\(|exec\(|popen\(|sh -c)' | \
head -10
echo ""
echo "=== Encryption/Keys ==="
strings -a "$FIRMWARE" | \
grep -iE '(key|cert|rsa|aes|encrypt)' | \
head -10
echo ""
echo "=== Update Mechanism ==="
strings -a "$FIRMWARE" | \
grep -iE '(update|upgrade|download|http.*/fw)' | \
head -10
EOF
chmod +x analyze_firmware.sh
./analyze_firmware.sh router_firmware.bin
# Extract bootloader strings
strings -a firmware.bin | \
grep -iE '(u-boot|bootloader|grub|loader)' | \
head -15
# Find kernel version
strings -a firmware.bin | \
grep -E 'Linux version [0-9]'
# Look for BusyBox commands
strings -a firmware.bin | \
grep -E '^(ls|cat|echo|mount|ifconfig|ping)$' | \
sort -u
# Extract debug messages
strings -a firmware.bin | \
grep -iE '^(DEBUG|INFO|ERROR|WARN):' | \
head -20
# Find manufacturer URLs
strings -a firmware.bin | \
grep -oE 'https?://[a-zA-Z0-9.-]+' | \
sort -u
# IoT device analysis
cat > iot_analysis.sh << 'EOF'
#!/bin/bash
DEVICE_BIN="$1"
echo "IoT Device Binary Analysis"
echo "=========================="
# Extract Wi-Fi related strings
echo ""
echo "=== Wi-Fi Configuration ==="
strings -a "$DEVICE_BIN" | \
grep -iE '(ssid|wpa|wifi|wireless|802\.11)' | \
head -10
# Cloud connectivity
echo ""
echo "=== Cloud Services ==="
strings -a "$DEVICE_BIN" | \
grep -iE '(aws|azure|mqtt|cloud|iot)' | \
head -10
# API endpoints
echo ""
echo "=== API Endpoints ==="
strings -a "$DEVICE_BIN" | \
grep -E '/api/|/v[0-9]+/' | \
head -15
EOF
chmod +x iot_analysis.sh
# Extract configuration file paths
strings -a firmware.bin | \
grep -E '\.(conf|cfg|ini|config)$' | \
sort -u
# Clean up
rm -f analyze_firmware.sh iot_analysis.sh
Firmware Analysis: router_firmware.bin
==========================================
=== Device Information ===
Manufacturer: Acme Networks
Model: WRT-5000
Device Type: Wireless Router
Hardware Version: 1.2
=== Network Services ===
telnetd
httpd
sshd
ftpd
:80
:23
:22
=== Default Credentials ===
admin:admin
root:password
default username: admin
default password: 12345
=== Listening Ports ===
:22
:23
:80
:443
:8080
:8443
=== Command Injection Risks ===
system(cmd)
popen("/bin/sh", "r")
exec /bin/sh
=== Update Mechanism ===
http://firmware.acme.com/updates/
check_for_update()
download_firmware
/tmp/firmware_upgrade.bin
# Bootloader strings:
U-Boot 2019.07
Booting kernel
Loading from NAND flash
Boot command: bootm
# Kernel version:
Linux version 4.9.0 (builder@buildhost)
Firmware often contains: default credentials, debug interfaces, hardcoded keys, update URLs, backdoors. Use -a for firmware (not ELF format). Increase -n to 6-8 to reduce noise. Look for: telnet/SSH access, web interfaces, cloud endpoints, encryption keys. Common findings: default admin:admin, debug ports, insecure update mechanisms.
# Compare strings between two versions
diff <(strings binary_v1.0) <(strings binary_v2.0)
# Show only new strings in v2
comm -13 \
<(strings binary_v1.0 | sort) \
<(strings binary_v2.0 | sort)
# Show only removed strings from v1
comm -23 \
<(strings binary_v1.0 | sort) \
<(strings binary_v2.0 | sort)
# Create detailed comparison
cat > compare_versions.sh << 'EOF'
#!/bin/bash
FILE1="$1"
FILE2="$2"
echo "Binary Comparison"
echo "================="
echo "File 1: $FILE1"
echo "File 2: $FILE2"
echo ""
STRINGS1=$(mktemp)
STRINGS2=$(mktemp)
strings "$FILE1" | sort > "$STRINGS1"
strings "$FILE2" | sort > "$STRINGS2"
TOTAL1=$(wc -l < "$STRINGS1")
TOTAL2=$(wc -l < "$STRINGS2")
COMMON=$(comm -12 "$STRINGS1" "$STRINGS2" | wc -l)
NEW=$(comm -13 "$STRINGS1" "$STRINGS2" | wc -l)
REMOVED=$(comm -23 "$STRINGS1" "$STRINGS2" | wc -l)
echo "Statistics:"
echo " $FILE1: $TOTAL1 strings"
echo " $FILE2: $TOTAL2 strings"
echo " Common: $COMMON strings"
echo " New in $FILE2: $NEW strings"
echo " Removed from $FILE1: $REMOVED strings"
echo ""
echo "New strings in $FILE2:"
comm -13 "$STRINGS1" "$STRINGS2" | head -20
echo ""
echo "Removed strings from $FILE1:"
comm -23 "$STRINGS1" "$STRINGS2" | head -20
rm "$STRINGS1" "$STRINGS2"
EOF
chmod +x compare_versions.sh
./compare_versions.sh app_v1.exe app_v2.exe
# Detect tampering
cat > detect_tampering.sh << 'EOF'
#!/bin/bash
ORIGINAL="$1"
SUSPECT="$2"
echo "Tampering Detection Analysis"
echo "============================"
# Compare string counts
ORIG_COUNT=$(strings "$ORIGINAL" | wc -l)
SUSP_COUNT=$(strings "$SUSPECT" | wc -l)
echo "Original strings: $ORIG_COUNT"
echo "Suspect strings: $SUSP_COUNT"
# Look for suspicious additions
echo ""
echo "Suspicious new strings:"
comm -13 \
<(strings "$ORIGINAL" | sort) \
<(strings "$SUSPECT" | sort) | \
grep -iE '(backdoor|hack|inject|malware|trojan)' | \
head -10
# Check for removed security strings
echo ""
echo "Missing security-related strings:"
comm -23 \
<(strings "$ORIGINAL" | grep -iE '(verify|auth|secure|encrypt)' | sort) \
<(strings "$SUSPECT" | grep -iE '(verify|auth|secure|encrypt)' | sort) | \
head -10
EOF
chmod +x detect_tampering.sh
# Track version changes
cat > version_tracker.sh << 'EOF'
#!/bin/bash
BINARY="$1"
echo "Version Information Extraction"
echo "=============================="
# Extract version strings
echo "Version strings:"
strings "$BINARY" | \
grep -iE 'v?[0-9]+\.[0-9]+(\.[0-9]+)?|version' | \
head -10
# Extract build information
echo ""
echo "Build information:"
strings "$BINARY" | \
grep -iE '(build|compiled|date|time)' | \
head -10
# Extract copyright/author
echo ""
echo "Copyright/Author:"
strings "$BINARY" | \
grep -iE '(copyright|author|company|\(c\))' | \
head -10
EOF
chmod +x version_tracker.sh
./version_tracker.sh /usr/bin/gcc
# Compare library versions
for lib in /lib/x86_64-linux-gnu/libc*.so*; do
echo "=== $(basename $lib) ==="
strings "$lib" | grep -i "version" | head -3
echo ""
done
# Find modified system binaries
cat > find_modified.sh << 'EOF'
#!/bin/bash
# Compare installed binary with package version
BINARY="/bin/ls"
PACKAGE_FILE="/var/cache/apt/archives/coreutils*.deb"
if [ ! -f "$PACKAGE_FILE" ]; then
echo "Package file not found"
exit 1
fi
# Extract package binary
mkdir -p /tmp/pkg_extract
dpkg-deb -x "$PACKAGE_FILE" /tmp/pkg_extract 2>/dev/null
PKG_BINARY="/tmp/pkg_extract/bin/ls"
echo "Comparing $BINARY with package version"
diff <(strings "$BINARY" | sort) <(strings "$PKG_BINARY" | sort) || \
echo "Binaries differ!"
rm -rf /tmp/pkg_extract
EOF
chmod +x find_modified.sh
# Clean up
rm -f compare_versions.sh detect_tampering.sh version_tracker.sh find_modified.sh
Binary Comparison
=================
File 1: app_v1.exe
File 2: app_v2.exe
Statistics:
app_v1.exe: 1234 strings
app_v2.exe: 1456 strings
Common: 1123 strings
New in app_v2.exe: 333 strings
Removed from app_v1.exe: 111 strings
New strings in app_v2.exe:
New feature: Cloud sync
Enable telemetry
Send usage data
api.newservice.com
Updated to version 2.0
Removed strings from app_v1.exe:
Legacy mode
Old API endpoint
Deprecated function
# Tampering detection:
Tampering Detection Analysis
============================
Original strings: 2341
Suspect strings: 2389
Suspicious new strings:
backdoor_init
inject_payload
disable_security_check
Missing security-related strings:
verify_signature
authenticate_user
secure_connection
# Version information:
Version strings:
GCC version 11.4.0
Build: 20230917
Built for x86_64-linux-gnu
Use comm to compare sorted string lists: -12 shows common, -13 shows unique to file2, -23 shows unique to file1. String comparison reveals: new features, removed functionality, version changes, potential tampering. Always compare same encoding types. Useful for: patch analysis, malware variants, backdoor detection, integrity checking.
# Extract only long strings (reduce noise)
strings -n 20 binary.exe
# Find strings matching specific pattern
strings binary | grep -E '^[A-Z][a-z]+[A-Z][a-zA-Z]*$' # CamelCase
# Extract IPv4 addresses
strings -a binary | \
grep -oE '\b([0-9]{1,3}\.){3}[0-9]{1,3}\b' | \
sort -u
# Find base64 encoded data
strings binary | \
grep -E '^[A-Za-z0-9+/]{20,}={0,2}$'
# Extract hex strings
strings binary | \
grep -E '^[0-9A-Fa-f]{32,}$'
# Find UUIDs
strings binary | \
grep -E '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'
# Extract Windows registry paths
strings binary | \
grep 'HKEY_' | \
grep -E 'HKEY_(LOCAL_MACHINE|CURRENT_USER|CLASSES_ROOT)'
# Find SQL queries
strings app.exe | \
grep -iE '^(SELECT|INSERT|UPDATE|DELETE|CREATE)' | \
head -10
# Extract file extensions
strings binary | \
grep -oE '\.[a-z]{2,4}$' | \
sort | uniq -c | sort -rn
# Advanced pattern extraction
cat > extract_patterns.sh << 'EOF'
#!/bin/bash
BINARY="$1"
echo "Pattern Extraction: $(basename "$BINARY")"
echo "======================================="
# Email addresses
echo ""
echo "=== Email Addresses ==="
strings -a "$BINARY" | \
grep -oE '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' | \
sort -u | head -10
# URLs
echo ""
echo "=== URLs ==="
strings -a "$BINARY" | \
grep -oE 'https?://[a-zA-Z0-9./?=_%:-]+' | \
sort -u | head -10
# IP:Port combinations
echo ""
echo "=== IP:Port ==="
strings -a "$BINARY" | \
grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}:[0-9]{2,5}' | \
sort -u
# Windows file paths
echo ""
echo "=== Windows Paths ==="
strings -a "$BINARY" | \
grep -E '^[A-Za-z]:\\' | \
head -10
# Unix file paths
echo ""
echo "=== Unix Paths ==="
strings -a "$BINARY" | \
grep -E '^/[a-z]+/' | \
head -10
# Function names (likely)
echo ""
echo "=== Potential Functions ==="
strings -a "$BINARY" | \
grep -E '^[a-z_][a-z0-9_]*\(' | \
head -15
# Error codes
echo ""
echo "=== Error Messages ==="
strings -a "$BINARY" | \
grep -iE '^(error|exception|fatal)' | \
head -10
EOF
chmod +x extract_patterns.sh
./extract_patterns.sh application.exe
# Statistical analysis
cat > string_stats.sh << 'EOF'
#!/bin/bash
BINARY="$1"
echo "String Statistics: $(basename "$BINARY")"
echo "======================================"
TOTAL=$(strings "$BINARY" | wc -l)
UNIQUE=$(strings "$BINARY" | sort -u | wc -l)
echo "Total strings: $TOTAL"
echo "Unique strings: $UNIQUE"
echo "Duplicate ratio: $(awk "BEGIN {printf \"%.2f%%\", (1-$UNIQUE/$TOTAL)*100}")"
echo ""
echo "Length distribution:"
strings "$BINARY" | \
awk '{print length}' | \
sort -n | \
uniq -c | \
tail -20
echo ""
echo "Most common strings:"
strings "$BINARY" | \
sort | \
uniq -c | \
sort -rn | \
head -10
echo ""
echo "Longest strings:"
strings "$BINARY" | \
awk '{print length, $0}' | \
sort -rn | \
head -5
EOF
chmod +x string_stats.sh
./string_stats.sh /bin/bash
# Context extraction
strings -a binary | \
grep -B 2 -A 2 "interesting_string"
# Filter by character class
strings binary | \
grep '^[A-Z][A-Z_]*$' # ALL_CAPS constants
strings binary | \
grep '^[a-z][a-z_]*$' # all_lowercase
# Exclude common noise
strings binary | \
grep -v -E '^(and|the|for|with|from|that|this|have|been)$'
# Clean up
rm -f extract_patterns.sh string_stats.sh
Pattern Extraction: application.exe
=======================================
=== Email Addresses ===
admin@company.com
support@vendor.net
info@example.org
=== URLs ===
http://api.service.com/v1/
https://update.company.net/check
https://login.example.com/auth
=== IP:Port ===
192.168.1.100:8080
10.0.0.5:443
172.16.0.1:22
=== Windows Paths ===
C:\Windows\System32\
C:\Program Files\Application\
C:\Users\Public\Documents\
=== Unix Paths ===
/usr/bin/
/etc/config/
/var/log/
=== Potential Functions ===
main()
init_application(
process_data(
connect_to_server(
validate_input(
# String statistics:
String Statistics: bash
======================================
Total strings: 3456
Unique strings: 2891
Duplicate ratio: 16.35%
Length distribution:
100 4
150 5
200 6
250 7
300 8
Most common strings:
15 bash
12 error
10 invalid
8 cannot
7 command
Longest strings:
156 bash: command not found: very long error message...
Combine strings with grep/awk for powerful pattern extraction. Common patterns: email regex, IP addresses, UUIDs, paths, URLs. Use -o with grep to extract only matching parts. Statistics reveal: duplicate strings (possible compression/optimization), length distribution, common patterns. Filter noise with grep -v to exclude common words.
#!/bin/bash
# File: binary_analyzer.sh
# Comprehensive binary analysis using strings
set -euo pipefail
# ============================================
# Configuration
# ============================================
readonly ANALYSIS_DIR="./analysis_results"
readonly MIN_STRING_LENGTH=6
readonly MAX_REPORT_ITEMS=50
# ============================================
# Initialize
# ============================================
mkdir -p "$ANALYSIS_DIR"
# ============================================
# Logging
# ============================================
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
}
# ============================================
# String Extraction
# ============================================
extract_strings() {
local binary="$1"
local output_dir="$2"
log "Extracting strings from $(basename "$binary")"
# ASCII strings
strings -a -n "$MIN_STRING_LENGTH" "$binary" \
> "$output_dir/strings_ascii.txt"
# UTF-16 strings (Windows)
strings -a -e l -n "$MIN_STRING_LENGTH" "$binary" \
> "$output_dir/strings_utf16.txt"
# With offsets
strings -a -t x -n "$MIN_STRING_LENGTH" "$binary" \
> "$output_dir/strings_with_offsets.txt"
log "Extracted $(wc -l < "$output_dir/strings_ascii.txt") ASCII strings"
log "Extracted $(wc -l < "$output_dir/strings_utf16.txt") UTF-16 strings"
}
# ============================================
# Pattern Detection
# ============================================
detect_patterns() {
local strings_file="$1"
local output_dir="$2"
log "Detecting patterns..."
# Network indicators
grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' "$strings_file" | \
sort -u > "$output_dir/ip_addresses.txt" 2>/dev/null || true
grep -oE 'https?://[a-zA-Z0-9./?=_%:-]+' "$strings_file" | \
sort -u > "$output_dir/urls.txt" 2>/dev/null || true
grep -oE '[a-zA-Z0-9.-]+\.(com|net|org|io|edu|gov)' "$strings_file" | \
sort -u > "$output_dir/domains.txt" 2>/dev/null || true
# Email addresses
grep -oE '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' "$strings_file" | \
sort -u > "$output_dir/emails.txt" 2>/dev/null || true
# File paths
grep -E '^[A-Za-z]:\\|^/' "$strings_file" | \
sort -u > "$output_dir/file_paths.txt" 2>/dev/null || true
# Registry keys
grep 'HKEY_' "$strings_file" | \
sort -u > "$output_dir/registry_keys.txt" 2>/dev/null || true
log "Pattern detection complete"
}
# ============================================
# Threat Analysis
# ============================================
analyze_threats() {
local strings_file="$1"
local output_dir="$2"
log "Analyzing potential threats..."
local threats_found=0
{
echo "# Threat Analysis Report"
echo "# Generated: $(date)"
echo ""
# Suspicious keywords
echo "## Suspicious Keywords"
if grep -iE '(password|passwd|pwd|secret|key|token|api_key)' "$strings_file" > /dev/null; then
echo "⚠ Potential credential strings found:"
grep -iE '(password|passwd|pwd|secret|key|token|api_key)' "$strings_file" | \
head -$MAX_REPORT_ITEMS
((threats_found++))
fi
echo ""
# Malicious indicators
echo "## Malicious Indicators"
if grep -iE '(backdoor|rootkit|keylog|inject|exploit|payload|shell)' "$strings_file" > /dev/null; then
echo "🔴 CRITICAL: Malicious indicators detected:"
grep -iE '(backdoor|rootkit|keylog|inject|exploit|payload|shell)' "$strings_file" | \
head -$MAX_REPORT_ITEMS
((threats_found++))
fi
echo ""
# Cryptographic operations
echo "## Cryptographic Operations"
if grep -iE '(encrypt|decrypt|cipher|crypto|aes|rsa|base64)' "$strings_file" > /dev/null; then
echo "ℹ Cryptographic operations detected:"
grep -iE '(encrypt|decrypt|cipher|crypto|aes|rsa|base64)' "$strings_file" | \
head -$MAX_REPORT_ITEMS
fi
echo ""
# Network operations
echo "## Network Operations"
if grep -iE '(socket|connect|listen|send|recv|http|ftp)' "$strings_file" > /dev/null; then
echo "ℹ Network operations detected:"
grep -iE '(socket|connect|listen|send|recv|http|ftp)' "$strings_file" | \
head -$MAX_REPORT_ITEMS
fi
echo ""
# Process operations
echo "## Process Operations"
if grep -iE '(CreateProcess|exec|spawn|fork|kill)' "$strings_file" > /dev/null; then
echo "ℹ Process operations detected:"
grep -iE '(CreateProcess|exec|spawn|fork|kill)' "$strings_file" | \
head -$MAX_REPORT_ITEMS
fi
echo ""
# Summary
echo "## Summary"
echo "Threat indicators found: $threats_found"
if [ $threats_found -gt 0 ]; then
echo "⚠ THIS BINARY REQUIRES DETAILED ANALYSIS"
else
echo "✓ No obvious malicious indicators (does not guarantee safety)"
fi
} > "$output_dir/threat_analysis.txt"
log "Threat analysis complete: $threats_found indicators"
}
# ============================================
# Statistical Analysis
# ============================================
generate_statistics() {
local strings_file="$1"
local output_dir="$2"
log "Generating statistics..."
local total=$(wc -l < "$strings_file")
local unique=$(sort -u "$strings_file" | wc -l)
{
echo "# Statistical Analysis"
echo "======================"
echo ""
echo "Total strings: $total"
echo "Unique strings: $unique"
echo "Duplicate ratio: $(awk "BEGIN {printf \"%.2f%%\", (1-$unique/$total)*100}")"
echo ""
echo "## Length Distribution (top 10)"
awk '{print length}' "$strings_file" | \
sort -n | uniq -c | sort -rn | head -10
echo ""
echo "## Most Common Strings (top 20)"
sort "$strings_file" | uniq -c | sort -rn | head -20
echo ""
echo "## Longest Strings (top 10)"
awk '{print length, $0}' "$strings_file" | \
sort -rn | head -10
} > "$output_dir/statistics.txt"
log "Statistics generated"
}
# ============================================
# Report Generation
# ============================================
generate_report() {
local binary="$1"
local output_dir="$2"
log "Generating comprehensive report..."
local report="$output_dir/ANALYSIS_REPORT.txt"
{
echo "========================================"
echo "BINARY ANALYSIS REPORT"
echo "========================================"
echo ""
echo "File: $binary"
echo "Analyzed: $(date)"
echo "File Size: $(stat -c%s "$binary" 2>/dev/null || stat -f%z "$binary") bytes"
echo "MD5: $(md5sum "$binary" 2>/dev/null | awk '{print $1}' || md5 "$binary" | awk '{print $NF}')"
echo "SHA256: $(sha256sum "$binary" 2>/dev/null | awk '{print $1}' || shasum -a 256 "$binary" | awk '{print $1}')"
echo ""
echo "========================================"
echo "THREAT ANALYSIS"
echo "========================================"
cat "$output_dir/threat_analysis.txt"
echo ""
echo "========================================"
echo "NETWORK INDICATORS"
echo "========================================"
echo "IP Addresses: $(wc -l < "$output_dir/ip_addresses.txt" 2>/dev/null || echo 0)"
if [ -s "$output_dir/ip_addresses.txt" ]; then
head -20 "$output_dir/ip_addresses.txt"
fi
echo ""
echo "URLs: $(wc -l < "$output_dir/urls.txt" 2>/dev/null || echo 0)"
if [ -s "$output_dir/urls.txt" ]; then
head -20 "$output_dir/urls.txt"
fi
echo ""
echo "Domains: $(wc -l < "$output_dir/domains.txt" 2>/dev/null || echo 0)"
if [ -s "$output_dir/domains.txt" ]; then
head -20 "$output_dir/domains.txt"
fi
echo ""
echo "========================================"
echo "STATISTICS"
echo "========================================"
cat "$output_dir/statistics.txt"
echo ""
echo "========================================"
echo "FILES GENERATED"
echo "========================================"
ls -lh "$output_dir"
} > "$report"
log "Report generated: $report"
echo ""
cat "$report"
}
# ============================================
# Main Analysis Function
# ============================================
analyze_binary() {
local binary="$1"
if [ ! -f "$binary" ]; then
log "Error: File not found: $binary"
return 1
fi
local basename=$(basename "$binary")
local output_dir="$ANALYSIS_DIR/${basename}_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$output_dir"
log "========================================="
log "Starting analysis: $basename"
log "Output directory: $output_dir"
log "========================================="
# Extract strings
extract_strings "$binary" "$output_dir"
# Detect patterns
detect_patterns "$output_dir/strings_ascii.txt" "$output_dir"
# Analyze threats
analyze_threats "$output_dir/strings_ascii.txt" "$output_dir"
# Generate statistics
generate_statistics "$output_dir/strings_ascii.txt" "$output_dir"
# Generate report
generate_report "$binary" "$output_dir"
log "========================================="
log "Analysis complete"
log "========================================="
}
# ============================================
# Main
# ============================================
main() {
if [ $# -eq 0 ]; then
echo "Usage: $0 <binary_file>"
echo ""
echo "Comprehensive binary analysis using strings"
echo "Results saved to: $ANALYSIS_DIR"
exit 1
fi
analyze_binary "$1"
}
main "$@"
[2025-12-14 20:00:00] =========================================
[2025-12-14 20:00:00] Starting analysis: suspicious.exe
[2025-12-14 20:00:00] Output directory: ./analysis_results/suspicious.exe_20251214_200000
[2025-12-14 20:00:00] =========================================
[2025-12-14 20:00:00] Extracting strings from suspicious.exe
[2025-12-14 20:00:01] Extracted 2456 ASCII strings
[2025-12-14 20:00:01] Extracted 1834 UTF-16 strings
[2025-12-14 20:00:01] Detecting patterns...
[2025-12-14 20:00:02] Pattern detection complete
[2025-12-14 20:00:02] Analyzing potential threats...
[2025-12-14 20:00:02] Threat analysis complete: 2 indicators
[2025-12-14 20:00:02] Generating statistics...
[2025-12-14 20:00:03] Statistics generated
[2025-12-14 20:00:03] Generating comprehensive report...
[2025-12-14 20:00:03] Report generated: ./analysis_results/.../ANALYSIS_REPORT.txt
========================================
BINARY ANALYSIS REPORT
========================================
File: suspicious.exe
Analyzed: Sun Dec 14 20:00:03 EST 2025
File Size: 2456832 bytes
MD5: a1b2c3d4e5f6...
SHA256: 1a2b3c4d5e6f...
========================================
THREAT ANALYSIS
========================================
## Suspicious Keywords
⚠ Potential credential strings found:
admin_password=
api_key_secret
default_token
## Malicious Indicators
🔴 CRITICAL: Malicious indicators detected:
backdoor_init()
inject_shellcode
keylogger_start
## Summary
Threat indicators found: 2
⚠ THIS BINARY REQUIRES DETAILED ANALYSIS
========================================
NETWORK INDICATORS
========================================
IP Addresses: 5
192.168.1.100
10.0.0.5
172.16.0.1
URLs: 8
http://command-control.net/api
https://malicious-site.com/payload
========================================
FILES GENERATED
========================================
strings_ascii.txt
strings_utf16.txt
strings_with_offsets.txt
ip_addresses.txt
urls.txt
domains.txt
threat_analysis.txt
statistics.txt
ANALYSIS_REPORT.txt
This production framework provides comprehensive binary analysis: string extraction (multiple encodings), pattern detection (IPs, URLs, emails), threat analysis (malware indicators), statistical analysis, and detailed reporting. Suitable for: malware triage, security analysis, forensics, reverse engineering. Always combine with other tools for complete analysis. Automate with cron for continuous monitoring.
strings -a to scan entire
file for: firmware, disk images, memory dumps, unknown binaries, or any non-ELF/PE file.
strings -e l for little-endian
UTF-16. You'll miss important strings if you only check ASCII on Windows binaries.
strings -t x to show hexadecimal offsets. Essential for forensics and
correlating strings with hex editor or disassembler. Helps locate specific strings in large files.
strings binary | grep -E 'https?://'. Much faster than manual searching.
strings binary | sort -u to remove duplicates and organize output. Easier
to spot patterns and anomalies. Use uniq -c | sort -rn to find most common strings.
comm -13 <(strings v1 | sort)
<(strings v2 | sort) shows new strings. Great for patch analysis and tamper detection.