Skip to content
Swiftly-TrackerPublic

About

Dump strings from binaries

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

8 Commits

Folders and files

Repository files navigation

strings

License: GPL v3 Build Status Release

Extract readable strings out of a game binary, without the usual flood of hashes, padding, and one-off symbol fragments strings.exe/GNU strings leave behind.

Reads PE, ELF and Mach-O binaries directly (no OS-specific APIs to load them), pulls candidate strings out of the sections that actually hold them, drops the non-string bytes that look like text (import names, relocation targets, unwind data), demangles the C++ symbols that survive, and prints the result sorted and deduplicated.

What it does

  • Format-aware section scanning - PE (.data/.rdata, falls back to .text), ELF (.dynstr, .rodata, .rodata.str*, .data, .strtab, ...), Mach-O (__cstring, __const, __data, ...). No dependency on the host OS matching the binary's format - a .so can be scanned from Windows and vice versa.
  • Symbol filtering - strings of 10 characters or fewer that are mostly symbols are dropped. printf conversions such as %s or %-5.2f count as letters, so short format strings are kept.
  • Fragment filtering - in data sections a string must be followed by a NUL byte (or the end of the section, or a UTF-8 character). This drops chunks of tables, pointers and serialized protobuf descriptors that only look like text.
  • C++ demangling - both Itanium (_Z...) and MSVC (?..., .?AV...) manglings, including the RTTI-only forms compilers emit without the usual mangling prefix, MSVC's array/pointer type descriptors, and nested lambda/local-class names.
  • Sorted, deduplicated output - one string per line, alphabetical, no repeats.
  • Parallel multi-binary processing - pass several binaries at once and they're scanned concurrently, one worker per binary, each written to its own <binary>.txt.

Install

Grab an archive from the latest release:

Archive Needs .NET installed? Use when
strings-win-x64.zip No Windows, just run it
strings-linux-x64.zip No Linux, just run it
strings-win-x64-portable.zip .NET 10 runtime Windows, smaller download
strings-linux-x64-portable.zip .NET 10 runtime Linux, smaller download

Those links always resolve to the newest stable release. On Linux, chmod +x strings after unzipping.

Usage

strings --binary=<path|glob>[,<path|glob>...] [options]

Results are written to <binary-filename-without-extension>.txt (one file per binary, next to each other) - not printed to stdout. Pass multiple binaries (comma-separated, or repeat --binary) and they're processed in parallel, one thread per binary. --binary also accepts glob patterns (*.dll, bin/**/*.so, ...) which get expanded to every matching file. While a binary is being scanned, the console prints its live throughput (strings/s) every half-second; as soon as a binary finishes, its output path and final string count are printed immediately - it doesn't wait for the others.

Flag Description
--binary=<path|glob> Path(s)/glob(s) of the binaries to parse (required); comma-separated or repeat the flag, processed in parallel
--target=<type> Binary format: pe, elf, or macho - auto-detected from magic bytes if omitted
--demangle=<bool> Demangle C++ symbols (default true)
--min-length=<n> Minimum string length to keep (default 3)
--sym-length=<n> Strings at or under this length are dropped if they're majority non-alphanumeric (default 10)
--terminated=<bool> Drop text-like fragments not followed by a NUL byte (default true; set false for Go/Rust binaries, whose strings are not NUL-terminated)
--mask-protobufs=<bool> Blank serialized protobuf descriptors (.proto file descriptors embedded by protoc) before extracting strings (default true)
--print-sections List every section name in the binary and exit
--output-dir=<path> Directory to write <binary-without-extension>.txt results to (default: current directory)

Examples:

# Auto-detect format, demangle, write to libserver.txt
./strings --binary=libserver.so

# Multiple binaries at once, scanned in parallel, one .txt each
./strings --binary=client.dll,server.dll,libserver.so --output-dir=out

# Glob every DLL in a tree, scanned in parallel
./strings --binary='bin/**/*.dll' --output-dir=out

# Skip demangling
./strings --binary=client.dll --demangle=false

# See what sections exist before picking one to inspect further
./strings --binary=server.dll --print-sections

Building from source

Requires the .NET 10 SDK.

git clone https://github.com/Swiftly-Tracker/strings.git
cd strings
dotnet build strings.slnx -c Release

Output lands in bin/Release/net10.0/.

To produce a standalone binary like the release archives:

dotnet publish strings.csproj -c Release \
  -r linux-x64 --self-contained true \
  -p:PublishSingleFile=true -p:PublishReadyToRun=true -p:PublishTrimmed=false \
  -o out/linux-x64

Architecture

strings/
├── src/
│   ├── Entrypoint.cs      # CLI entry point, per-format section lists, filter pipeline
│   ├── CliOptions.cs      # Flag parsing
│   ├── FileReader.cs      # Magic-byte format detection, dispatch, string extraction
│   ├── PeSections.cs      # PE section-table reader
│   ├── PeStrings.cs       # PE blanking and rewrites (imports, relocations, unwind data)
│   ├── EndRule.cs         # End-of-string rule for data sections
│   ├── ElfSections.cs     # ELF32/64 section-table reader
│   ├── MachOSections.cs   # Mach-O32/64 section-table reader
│   └── Util.cs            # Escaping, symbol-density filter, C++ demangling

Community

License

GPL-3.0. See LICENSE.


Made with ❤️ by the Swiftly Development team

About

Dump strings from binaries

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages