Overview
Binary files are mostly unreadable bytes, but hidden among them are often runs of human-readable text: error messages, file paths, URLs, configuration values — and, in CTF challenges, flags. The strings utility pulls these printable sequences out of any file so you can read them without opening the file in an editor or running it. It is one of the fastest, safest first moves in file analysis.
Learning objectives
- Explain what the
stringstool does and why it is useful. - Run
stringswith the options that matter (-n,-e,-t). - Combine
stringswithgrepto hunt for specific patterns. - Understand the limits of
stringsagainst encoded or compressed data.
Core concept
strings scans a file byte by byte and prints sequences of printable characters that are at least a minimum length long (4 by default). The idea is simple: most binary data looks random, but genuine text — messages, labels, embedded flags — appears as a continuous run of readable characters. By extracting only those runs, strings turns an opaque binary into a short, scannable list of its human-readable fragments. Because it only reads bytes and never executes the file, it is safe to run on unknown or suspicious files.
How it works
strings walks the file looking for consecutive printable characters terminated by a non-printable byte. Useful options:
-n <length>sets the minimum run length (e.g.-n 8shows only longer, more meaningful strings and cuts noise).-e <encoding>selects the character width/encoding. Default is single-byte ASCII;-e lfinds 16-bit little-endian (common in Windows/UTF-16) text that the default mode misses.-t xprints the offset (in hex) of each string, telling you where in the file it lives — helpful for locating it later in a hex editor.-ascans the whole file rather than just certain sections of an executable.
A key limitation: strings only finds text that is stored as plain characters. Data that is compressed, encrypted, or encoded (for example Base64) will not appear as readable words — you must decompress or decode first. Conversely, spotting a long Base64-looking run is itself a useful clue.
Practical example
You are given an unknown binary challenge in an authorized lab. Rather than executing it, you extract its strings and search for a flag pattern:
$ strings -n 6 challenge | head
/lib64/ld-linux-x86-64.so.2
usage: challenge [options]
Enter the password:
config/settings.ini
$ strings challenge | grep -i "flag{"
flag{str1ngs_reveals_secrets}
Piping into grep narrows thousands of strings down to the one you want. Adding offsets shows where a string sits:
$ strings -t x challenge | grep "flag{"
1a2f0 flag{str1ngs_reveals_secrets}
If the flag were stored as UTF-16 (e.g. from a Windows program), the default scan would miss it and strings -e l challenge would find it.
Cybersecurity relevance
strings is a staple of malware triage, reverse engineering, and forensics. Analysts run it on suspicious samples to quickly surface indicators of compromise — hard-coded URLs, IP addresses, file paths, registry keys, command strings, and ransom notes — all without executing the malware. It also reveals hard-coded secrets accidentally compiled into applications (API keys, credentials), which is a real and common security failing. As a defender, you can run strings over your own build artifacts to catch secrets before shipping. It is deliberately a static, read-only technique, which is why it is safe to use as an early, low-risk step.
Common mistakes
- Expecting to find text that is compressed or encrypted —
stringsonly sees plaintext characters; decode or decompress first. - Forgetting non-ASCII encodings — missing UTF-16 text by not using
-e l. - Reading thousands of lines by hand instead of piping to
grepfor the pattern you want. - Setting the minimum length too low, drowning the real clues in short random noise.
Key takeaways
stringsextracts runs of printable characters from any file, revealing embedded text without running the file.- Key options:
-nsets minimum length,-e lfinds UTF-16 text,-t xshows offsets,-ascans the whole file. - Combine with
grep(e.g.grep "flag{") to hunt for specific patterns quickly. - It only finds plaintext; compressed/encrypted/encoded data must be decoded first — but spotting an encoded blob is itself a clue.
Check your understanding
- Why does
stringsfail to reveal a flag that has been Base64-encoded or compressed, and what must you do first? - Which
stringsoption would you use to find 16-bit UTF-16 text left by a Windows program, and why is the default scan not enough?

