Skip to content
View sheratonc's full-sized avatar

Block or report sheratonc

Block user

Prevent this user from interacting with your repositories and sending you notifications. Learn more about blocking users.

You must be logged in to block users.

Content in all repositories owned by your account will be closed.
Maximum 250 characters. Please don’t include any personal information such as legal names or email addresses. Markdown is supported. This note will only be visible to you.
Report abuse

Contact GitHub support about this user’s behavior. Learn more about reporting abuse.

Report abuse
sheratonc/README.md

sheraton: a beginner learning Windows and Linux internals and binary analysis, in Rust, C++, C and Python

About

I'm a beginner teaching myself systems programming and reverse engineering on Windows and Linux. I learn best by building things, so most of my projects are small tools that help me see what happens between source code and a running program: how compilers lay out objects and metadata, how linkers put a binary together, how loaders map it into memory, and how debuggers and unwinders read it back.

Something I've found fascinating so far is the metadata a compiler has to leave in a binary, such as RTTI, vtables, unwind tables and import tables. It survives stripping, and it can tell you a surprising amount about how a program is put together.

The section layout of a Windows PE file and a Linux ELF file, with animated lines from each structure to the tool that reads it: pe-walker and pe-diff read the headers, section table and imports; rtti-dump and vtable-dump read RTTI and vtables in .rdata; pattern-scan scans .text on both; unwind-map reads the program headers, .eh_frame_hdr and .eh_frame

What I'm learning

  • Windows x64 internals: PE/COFF layout, the MSVC C++ ABI, RTTI and class hierarchies, vtables, imports and exports
  • Linux internals: ELF, the System V AMD64 ABI, DWARF call frame information and .eh_frame, program headers and the dynamic loader
  • Reverse engineering: reading stripped binaries with Ghidra, GDB, x64dbg and WinDbg, and writing small tools to help along the way
  • Languages: C++ for my Windows tools, Rust for cross-platform command-line tools, C for the low-level parts, and Python for scripts and tests

How I'm learning

  • By building: I learn each file format by writing a tool that reads it, and test it on binaries I've built myself
  • By checking my work: I compare my results with established tools like readelf and llvm-readobj, so I find out when I've got something wrong
  • By keeping it small: each tool does one thing and has no third-party dependencies, so I can understand every line
  • By writing it down: each README explains the format the tool reads, which helps me check that I really understand it

Toolbox

The languages and tools I've been learning with so far:

Languages Rust C++ C Python
Platforms Windows Linux
Build CMake  ·  Cargo  ·  MSVC  ·  MinGW-w64  ·  GCC  ·  Clang / LLD
Analysis Ghidra  ·  x64dbg  ·  WinDbg  ·  GDB  ·  readelf / objdump
Formats & ABIs PE/COFF  ·  ELF  ·  DWARF CFI  ·  MSVC C++ ABI  ·  System V AMD64  ·  Microsoft x64 calling convention

Projects

These are my learning projects: two small toolkits for taking binaries apart, one for each binary format. The PE tools are C++17 with CMake and build on Windows, Linux and macOS; the ELF tool is Rust. They're all MIT-licensed, tested in CI, and have no third-party dependencies.

My biggest project so far. It works out where functions start and end in stripped Linux ELF binaries by reading the .eh_frame unwind tables, which strip can't remove. It also works when the section headers are gone, flags functions with exception handling, points out code that has no unwind info, can put symbols back with objcopy, exports to Ghidra and JSON, and draws the binary as a Hilbert-curve map. I checked it against llvm-readobj's decoder on x86-64, x86 and AArch64 test binaries, and it found every function with unwind info without any false starts.

Terminal demo: unwind-map recovers 578 functions from a stripped binary and objcopy puts the symbols back Hilbert-curve map of the same stripped binary: every recovered function as a colored trace

Linux  Rust  ELF  DWARF CFI  x86-64 · x86 · AArch64  CI-tested

A command-line inspector I wrote to learn the Portable Executable format. It prints the DOS and NT headers, section layout, imports and exports.

pe-walker --summary app.exe

Windows  C++17  PE/COFF  x86 / x64

Compares two PE files: headers, sections, imports and exports. It exits non-zero when something changed, so it can be used in a CI pipeline.

pe-diff -T old.dll new.dll

Windows  C++17  PE/COFF  patch diffing

Rebuilds class hierarchies from stripped MSVC x64 binaries by following the RTTI structures: Complete Object Locator → Class Hierarchy Descriptor → Base Class Array.

rtti-dump --demangle app.exe

Windows  C++17  MSVC RTTI  class recovery

A companion to rtti-dump. It finds each class's vtable through its Complete Object Locator back-reference and lists the virtual function slots.

vtable-dump -f exception app.exe

Windows  C++17  MSVC ABI  vtables

A single-header C++17 library for IDA-style byte signature scanning. It uses memchr to find candidates before doing the full compare, which made it about 11× faster than a byte-by-byte scan in my benchmark, and a randomized test checks every result against a simple reference scanner.

const auto sig = patscan::parse("48 8B ?? E8 ?? ?? ?? ?? 85 C0");
const auto* hit = patscan::find(data, size, sig);

cross-platform  C++17  header-only  signature scanning


I'm still a beginner, so if you spot something wrong or have tips, please open an issue. Every tool here is built and tested against my own test binaries.

Pinned Loading

  1. unwind-map unwind-map Public

    Recover function boundaries from stripped Linux ELF binaries using the .eh_frame unwind tables that strip can't remove.

    Rust

  2. pe-walker pe-walker Public

    Command-line inspector for the Portable Executable format. DOS/NT headers, sections, imports, exports.

    C++

  3. pe-diff pe-diff Public

    Structural diff tool for Portable Executable files — compares headers, sections, imports, exports between two .exe or .dll binaries. Pairs with pe-walker.

    C++

  4. rtti-dump rtti-dump Public

    MSVC x64 RTTI extractor. Recovers class hierarchies from stripped Windows binaries.

    C++

  5. vtable-dump vtable-dump Public

    x64 Windows vtable locator — finds class virtual function tables via MSVC Complete Object Locator back-references. Pairs with rtti-dump.

    C++

  6. pattern-scan pattern-scan Public

    Single-header C++17 library for IDA-style byte signature scanning. Header-only, no dependencies.

    C++