Files
david942j 54c5db03b5 Release 2.1.1 (#470)
Every pre-generated entry is current again -- and a release is what
delivers it, since a remote BuildID lookup reads from the latest tag, so
until this one exists users still get the 2023-era gadgets.

Also stops telling people on the newest version to update it.
2026-09-05 20:55:19 +08:00

15 KiB

Changelog

Notable changes to one_gadget, newest first. The format follows Keep a Changelog and the project follows Semantic Versioning.

A change worth a user's attention lands with its entry under Unreleased; releases are cut by giving that section a version and a date.

v2.1.1 - 2026-09-05

Changed

  • The pre-generated gadgets for the libcs the gem does not ship were rebuilt (#468) -- all 883 entries are now current. They dated from 2023 and predate a year of emulator work, so a BuildID lookup could report gadgets that no longer work and miss ones that do: 10,326 recorded gadgets became 43,410.

Fixed

  • Looking up a BuildID the gem does not ship no longer advises updating the gem (#467). The gem carries 34 of 883 builds by design, so that advice reached almost every remote lookup, and updating would not have added them. It now says the build is being fetched.

v2.1.0 - 2026-09-05

Two more architectures, and a libc that ships without section headers -- as an embedded one usually does -- can now be searched at all.

Added

  • RISC-V (RV64) support, alongside i386, amd64, aarch64 and arm (#420, #421, #422, #423, #425). Every gadget it reports has been run under a debugger and seen to spawn a shell (#424).
  • MIPS (32-bit o32) support, in both byte orders (#448), verified the same way.
  • Reads a libc that ships without section headers, as OpenWrt's musl does (#432). Every architecture reports the same gadgets as the intact file.
  • A terminal posix_spawn whose symbol carries no version marker, as musl's does not, is no longer passed over (#432).

Changed

  • The gem no longer carries gadgets for the three glibc 2.26 builds it shipped (#443) -- no supported Ubuntu LTS ships 2.26. Those BuildIDs now answer from the remote database.
  • Searching a MIPS libc takes 0.7s, was 2.3s (#453).
  • Searching the same file twice in one process reuses what the first search found (#455).
  • Further search speedups, gadgets unchanged: objdump is asked what it supports once per binary rather than once per command (#454), the scan locating calls decodes far fewer words (#456), and a quarter as much is disassembled around each call (#457).
  • Requires elftools >= 2.2.0 (#442, #465), which reads a symbol table without building an object per symbol. A libc with no section headers searches in 0.24s, was 0.44s; one with its sections intact is unchanged.

Fixed

  • 67 more gadgets across the test corpus (#460): a backward walk threw away any path that hit its length limit, so what a libc reported depended on how far back it had been disassembled. Every new gadget was run under a debugger.
  • MIPS gadgets that could not work are no longer reported (#460). Entering at a call leaves the callee without the address o32 requires in t9, and six such gadgets were verified not to spawn a shell.
  • arm found nothing at all in a libc with no section headers (#441): Thumb code was read as A32, symbol addresses were off by one, and literal-pool loads went unresolved.
  • A libc with no section headers lost the calls at an address its symbol table gives more than one name, such as sigaction/__sigaction -- 20 aarch64 gadgets (#440).
  • A libc with no section headers reported fewer gadgets on aarch64 and RISC-V than the same libc intact -- 84 across the corpus (#439).
  • amd64 discarded every execl candidate before emulating it (#434). No fixture reports a new gadget as a result, but one could.
  • A search could abort with TypeError where it should have dropped the candidate (#434).

v2.0.0 - 2026-08-29

Reported gadgets are not offset-for-offset comparable with 1.x: constraints are more precise, an output level means one thing everywhere, and every gadget the test corpus reports has been run under a debugger and seen to spawn a shell.

Added

  • ARM32 support, alongside the existing amd64, i386 and aarch64 (#316).
  • Output level 2, which lists every gadget including the ones lower levels drop as duplicate or harder-to-satisfy (#350). --level is documented in the README with what each level shows (#397).
  • Aletheia, a verification harness that loads a libc under gdb (natively or through qemu-user), applies a constraint-satisfying plan, and requires a real shell to run ls / before a gadget counts as real (#399). Run it with rake "aletheia:verify[level, target]". Every gadget the fixtures report is verified this way.
  • Gadgets say which file descriptors they close on the way to the exec, so a reader knows when the spawned shell would lose its I/O (#371).
  • rake builds:refresh rebuilds the shipped gadget database from what the Ubuntu archive publishes now, and rake builds:check fails when a shipped entry has gone stale -- at most once a week, never on CI (#405, #406).
  • posix_spawn gadgets on aarch64 (#317), and the string a gadget reaches through the GOT is shown rather than left opaque (#372).

Changed

  • The gem ships a curated gadget database -- 33 entries, taking the packaged gem from 3.4MB to 112KB (#405). Any other BuildID is fetched on demand as before, so an offline -b for an arbitrary libc no longer answers from the gem alone.
  • An output level means the same thing however a libc is looked up. -b now honours --level, where it previously handed back whatever the database stored, and level 1 picks the same gadget however the emulator happened to find it (#402).
  • The database was regenerated; entries had been built before a year of constraint work and reported gadgets their libc no longer produces (#405).
  • Constraints read consistently: pointers compare to NULL and values to hex, never a bare 0 (#334), and readability is stated as readable: <reg> (#344). A mask a gadget applies is named rather than given up on (#370), and a value required to be zero scores the same however it is spelled (#377, #401).
  • Emulation stops at the terminal exec* call instead of running past it (#325), and a candidate whose path cannot hold is rejected (#359, #360).
  • Searching a libc got roughly five times faster: the test corpus at level 0 went from 42.5s to 8.6s (#388, #389, #390, #393, #394, #395, #396).
  • Requires Ruby >= 3.3 (#293) and elftools >= 2.0.0.

Fixed

  • Gadgets that could not actually spawn a shell, each found by running them: a dereferenced pointer argument of a "safe" libc call went unconstrained (#323, #340), a writable constraint was lost when its base was reassigned (#341), frame-pointer stores did not require the frame be writable (#345), an argv that disables shell execution was reported as usable (#348), an uncontrolled dereference was not required to be readable (#354), and a slot was read back as its entry value rather than what the gadget had put there (#364).
  • A GOT-base register the window establishes itself was seeded as a precondition (#385), and the GOT-base constraint is now only stated where a caller can actually put it -- in a register (#404).
  • Windowed disassembly lost gadgets whose branch predecessor sits after the call, and could invent gadgets by falling through a window boundary (#391, #392).
  • The "not glibc" check did not fire for aarch64 files (#311).
  • Certificates are verified again when fetching a gadget database entry. Verification had been off, and the response is written to a file and required as Ruby -- so anyone able to answer that request could run code as the user.
  • Shipped entries reported fewer gadgets than reading the same libc as a file. They are regenerated, and rake builds:audit now fails when one stops matching its libc.
  • An architecture is recognised by the machine type its ELF header states, not by the name elftools prints for it, whose wording changed in 2.0.0 and left every aarch64 and amd64 file reading as unknown.

v1.10.0 - 2024-10-04

  • Added JSON output, --output-format json (#225).
  • Requires Ruby >= 3.1 (#216).

v1.9.0 - 2023-11-30

  • Sharper constraints for argv and envp (#206).
  • Added --dwarf-start=0 so the output carries no local file path (#205).

v1.8.1 - 2022-03-25

  • Stack registers score higher on writable constraints, so easier gadgets rank first (#190).

v1.8.0 - 2022-03-20

  • posix_spawn call sites are treated as one-gadgets (#183).
  • amd64: loosened the restriction on gadgets reached by jmp (#178).

v1.7.4 - 2021-01-13

  • Writable constraints on the x86 architectures (#156).

v1.7.3 - 2019-10-25

  • Added the --base option (#100).
  • Constraints for XMM alignment, and stack alignment scores higher (#87).

v1.7.2 - 2019-05-05

  • Added --near, ordering gadgets by distance from given functions (#76).
  • Introduced the CLI module (#81).

v1.7.1 - 2019-04-19

  • Added gemspec metadata (#75).

v1.7.0 - 2019-03-07

  • AArch64 support (#64).
  • Constraints are scored, so the easiest gadgets are reported first (#67).

v1.6.2 - 2018-10-25

  • one_gadget is usable as a library (#47).

v1.6.1 - 2018-09-13

  • Improved update checking (#43) and custom error classes (#40).

v1.6.0 - 2018-04-28

  • Added the xmm instructions and glibc 2.27 builds (#27).
  • Added --info, showing what is known about a BuildID (#25).

v1.5.0 - 2017-11-06

  • Emulator rework, and the build database is generated from libc files (#15).

v1.4.1 - 2017-11-01

  • Checks for a newer version automatically (#13).

v1.4.0 - 2017-06-23

  • Warns when a BuildID is not found, and added Ubuntu 16.04/17.04 libcs (#9).

v1.3.8 - 2017-05-26

  • one_gadget() simplified for use from a script.

v1.3.7 - 2017-04-04

  • Added the gem version option, and 256-colour output.

v1.3.6 - 2017-04-01

  • Added builds for glibc >= 2.19; a given libc file is no longer looked up remotely (#6).

v1.3.5 - 2017-03-27

  • Raises a clear error for an unknown architecture.

v1.3.4.1 - 2017-03-22

  • Fixed running on Ruby 2.1.

v1.3.4 - 2017-03-21

  • Fixed failure on libc-2.15; switched to optparse.

v1.3.3 - 2017-03-16

  • Reads ELF files with rbelftools instead of shelling out to binutils/readelf.

v1.3.2 - 2017-03-07

  • ANSI colour output, and one_gadget() for use from Ruby.

v1.3.1 - 2017-02-21

  • Unrecognised instructions are handled instead of aborting the search.

v1.3.0 - 2017-02-21

  • amd64: consider the jmp case.

v1.2.0 - 2017-02-17

  • Introduced the instruction and lambda emulator objects.

v1.1.1 - 2017-02-14

  • Added gadgets for more libcs.

v1.1.0 - 2017-02-13

  • i386 support.

v1.0.0 - 2017-02-12

  • Gadget database fetched from the repository when a BuildID is not shipped.

v0.1.0 - 2017-02-11

  • First release.