Extract Useful Text from Windows Binaries with strings
By the end of this guide you will be able to inspect a Windows executable or object file from Linux, find its embedded text, locate each match by offset, and look for UTF-16 strings without changing the input file. The command is installed by the binutils-mingw-w64-x86-64 package. No elevated privileges are needed.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about 10 minutes for a first inspection. You need a shell, a readable file to inspect, and the cross-binutils package. The examples use x86_64-w64-mingw32-strings; the installed x86_64-w64-mingw32ucrt-strings alias has the same manpage and behaviour on this system.
1. Check the installed tool
Confirm which executable will run and record its version. This guide was checked with GNU Binutils 2.41.90.20240122, packaged as 2.41.90.20240122-1ubuntu1+11.4 on the machine used for the examples.
x86_64-w64-mingw32-strings --version
command -v x86_64-w64-mingw32-strings
Expected output starts like this:
GNU strings (GNU Binutils) 2.41.90.20240122
/usr/bin/x86_64-w64-mingw32-strings
If the command is missing, install the package using your distribution's normal package workflow. Do not download a replacement binary into a project directory just to make one inspection work.
2. Scan a file with the default settings
Pass one or more files after the options. GNU strings prints runs of displayable characters that are at least four characters long by default. Newlines and carriage returns end a run; spaces and tabs can remain inside it.
x86_64-w64-mingw32-strings -- /path/to/program.exe
The -- marks the end of options, so a filename beginning with a hyphen is not mistaken for a flag. Replace the placeholder with a real path. The command only reads the file and writes matches to standard output.
For a quick, repeatable check, create a disposable sample in /tmp and scan it:
printf 'noise\000hello-world\000tiny\000' > /tmp/strings-demo.bin
x86_64-w64-mingw32-strings /tmp/strings-demo.bin
Expected output is:
hello-world
tiny is four characters and is therefore also printable, but the sample's embedded NUL and shell quoting can make demonstrations easy to misread. For a clean threshold test, use the next step with an explicit minimum length.
3. Reduce noise with a minimum length
Use -n when short fragments are not useful. The value is the minimum number of displayable characters, not a maximum output size.
x86_64-w64-mingw32-strings -n 8 /path/to/program.exe
The short form -8 and long form --bytes=8 express the same setting:
x86_64-w64-mingw32-strings --bytes=8 /path/to/program.exe
Start with four when looking for filenames, URLs, messages, or symbol fragments. Increase it when a large binary produces too much incidental text. Lowering it below four can be useful for a targeted search, but it usually produces more noise than evidence.
4. Add filenames and offsets to the evidence
When scanning several files, -f prefixes every match with its filename. This makes redirected output useful later instead of losing track of which binary contained a string.
x86_64-w64-mingw32-strings -f /path/to/one.exe /path/to/two.dll
Use -t to print the byte offset before each string. Choose decimal with d, hexadecimal with x, or octal with o. Hexadecimal is usually the easiest format to compare with a hex editor.
x86_64-w64-mingw32-strings -t x /path/to/program.exe
Combine both when recording findings from multiple files:
x86_64-w64-mingw32-strings -f -t x -n 6 /path/to/one.exe /path/to/two.dll
Verify the command produced the expected kind of record by checking the first few lines:
x86_64-w64-mingw32-strings -f -t x /path/to/program.exe | sed -n '1,10p'
5. Look for UTF-16 text
Windows programs commonly store text as 16-bit little-endian characters. The default -e s mode looks for single 7-bit-byte strings, so it can miss text whose bytes alternate with NULs. Select little-endian 16-bit input with -e l.
x86_64-w64-mingw32-strings -e l -n 4 /path/to/program.exe
Use -e b for 16-bit big-endian data. The other supported modes are S for single 8-bit bytes, B and L for 32-bit big-endian and little-endian data, and s for the default single 7-bit-byte mode.
Do not assume a missing result proves that the text is absent. The chosen encoding, minimum length, section selection, and whether the text is compressed or encrypted all affect what can be found. Try the ordinary scan, then the wide-string scan, and compare the results.
6. Choose a full-file scan deliberately
The tool may be configured to scan the whole file by default, or only strings in loaded, initialised data sections. -a or --all explicitly scans every byte. This is useful for raw blobs, packed files, and formats the BFD library does not recognise.
x86_64-w64-mingw32-strings --all /path/to/program.exe
-d or --data restricts the scan to initialised, loaded data sections. It can reduce garbage, but the installed manpage warns that this path uses the BFD library and exposes the program to any security flaws in that library. For an untrusted file, prefer -a, keep the package updated, and run the inspection in an isolated environment if the file is suspicious.
Do not use -d merely because the file is a Windows executable. It is a choice about section-aware scanning, not a guarantee that the output is correct or safe.
7. Save results without changing the input
Redirect standard output when you need to review or search the matches later. The input remains untouched, but the destination file will be replaced if it already exists, so choose a new path or use shell redirection carefully.
x86_64-w64-mingw32-strings -a -f -t x /path/to/program.exe > /tmp/program-strings.txt
rg -n -i 'https?://|password|token|error' /tmp/program-strings.txt
If the output file is disposable, remove it explicitly after review:
rm -- /tmp/program-strings.txt
The removal is irreversible unless you have another copy. There is no need for sudo when working in /tmp or in a directory you own. Do not redirect output into the directory containing the source unless you have checked that the names cannot collide.
Common traps
- Only four-character results appear: that is the default minimum. Use
-n 8for less noise or a smaller value for a narrow search. - Wide text is absent: try
-e lfor UTF-16 little-endian data. Check-e bif the data is big-endian. - Results differ between machines: the default section behaviour is configurable. Compare
-aand-dexplicitly, and record the version. - Offsets look wrong:
-t xreports an offset in hexadecimal, not a line number or virtual memory address. - Output is unreadable: strings are evidence of byte sequences, not proof that a value is active, reachable, or trustworthy. Confirm important findings with a format-aware tool such as
objdumporreadelf.
Done means
- You confirmed the installed GNU Binutils version.
- You scanned the intended file without modifying it.
- You chose a minimum length, offset radix, or encoding that matches the question you are asking.
- You used
-aor-dconsciously, especially for an untrusted binary. - You saved and searched the output separately when the results need to be reviewed or shared.