# glibc-all-in-one: finding the libc behind a leak, offline and online

> A Python command line tool for glibc binary analysis that identifies an unknown libc by BuildID or symbol fingerprint, looks up symbol offsets, diffs two libc builds, and can compile a chosen glibc version from source, with a personal use only licence.

**matrix1001/glibc-all-in-one** — 🎁A convenient glibc binary and debug file downloader and source code auto builder

- Repository: https://github.com/matrix1001/glibc-all-in-one
- Stars: 826 · Forks: 85
- Language: Python
- License: NOASSERTION
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/matrix1001-glibc-all-in-one

## One problem, repeated every time: which libc is this?

The project describes itself as a glibc swiss army knife for pwn players, covering download, search, identification, comparison and compilation across the lifecycle of a glibc binary in that context. The central problem it solves is mundane and repeated: you have a leak, an offset, or an unfamiliar libc file, and you need to know exactly which glibc build it is.

Getting that wrong is expensive. The `puts` offset that works against one build will crash against another, and the fix is usually a long detour through symbol tables by hand.

The tool is the `glibc-aio` command, and the project notes call it a full v2 rewrite. The older shell script version still exists but has been moved to a `legacy/` directory and is no longer maintained. The project is written in Python, is packaged as `glibc-aio` version 2.0.0, and exposes a single console entry point, `glibc-aio = "glibc_aio.cli.main:main"`. The only runtime dependencies are `pyelftools` for ELF parsing and `zstandard` for decompressing `.deb` archives that use zstd.

The repository layout matches: a `glibc_aio/` package directory, a `tests/` directory, a `pyproject.toml`, the legacy scripts, and both a Chinese README and an `README_EN.md`.

There is also an explicit stance in the project notes worth noting for anyone worried about it: it says the tool does not record flags, it is a bring-and-use utility rather than something that hunts for the exploit.

## Identification runs two paths: BuildID first, fingerprint as fallback

The `identify` command is the core of the tool and it works in two directions. The first path reads the `.note.gnu.build-id` section out of the ELF file and queries libc.rip online with that BuildID. The second path computes a fingerprint from the symbol table and matches it against a local database. The local database grows automatically every time you download a libc.

The documented behaviour is a fallback, so it works with or without a network:

```bash
$ glibc-aio identify ./libc.so
Method:    buildid
Version:   2.27-3ubuntu1.5_amd64
BuildID:   4176c5eec6b8c6e04aa1eae2cd4b76b1

$ glibc-aio identify --offline ./libc.so          # 不联网，仅本地指纹
Method:    fingerprint
Version:   2.27-3ubuntu1_amd64
```

The distinction between the two versions in that output is instructive. The BuildID path found `2.27-3ubuntu1.5_amd64`, the fingerprint path found `2.27-3ubuntu1_amd64`, and those are different package versions of the same upstream release line. That is the sort of difference that matters when a build ships with an Ubuntu patch level.

For the offline path to have anything to match against, the local index has to be populated, which happens as a side effect of downloading. On a fresh machine with no network, `identify --offline` will have an empty database until something is downloaded.

The `search` command covers the online direction more broadly, including reverse lookups by a single symbol offset, by several symbols combined with AND, with a byte tolerance around the offset, and by BuildID.

## Local symbol search covers the cases online lookups miss

The most capable part of the tool is its local search, which works on any libc file you point it at, downloaded or not. Searching for a symbol by name gives an address and a symbol type:

```bash
$ glibc-aio search --libc ./libc.so --symbol system
000000000004f440  STT_FUNC  system
```

Glob patterns work on symbol names, which is how you find a family of functions at once:

```bash
$ glibc-aio search --libc ./libc.so --symbol "*exec*"
00000000000cbfa0  STT_FUNC  execl
00000000000cbde0  STT_FUNC  execv
...
[*] 14 symbol(s)
```

The end-of-address matching option is the interesting one. It finds symbols whose address ends with a given suffix, which is the shortcut for the partial overwrite technique where only the low bytes of an address are controlled:

```bash
$ glibc-aio search --libc ./libc.so --ends-with f30
00000000000abf30  STT_FUNC  wcpncpy
000000000004f430  STT_FUNC  __libc_system
[*] 7 symbol(s)
```

That can be combined with a glob filter, which narrows to a single result:

```bash
$ glibc-aio search --libc ./libc.so --symbol "*exec*" --ends-with fa0
00000000000cbfa0  STT_FUNC  execl
[*] 1 symbol(s)
```

String search is scoped to the `.rodata` and `.data` segments rather than scanning the whole file the way a general strings utility would, which is why the project notes distinguish it from running strings yourself:

```bash
$ glibc-aio search --libc ./libc.so --str "/bin/sh"
  0x001b3e9a  /bin/sh
[*] 1 match(es)
```

All subcommands support `--json` output, which matters if you intend to drive the tool from a script rather than read its terminal output.

## Smart dispatch reads your arguments instead of demanding subcommands

The more interesting design decision is that you do not have to remember the subcommand names. When you run `glibc-aio` without a subcommand, it infers what you mean from the shape of the arguments, and the project notes give the rules: an existing file path means a libc file, something starting with `0x` or a pure hex string of five digits or more is an address, a `number.number` pattern is a version, and anything else is a symbol name.

Once a file has appeared earlier in the argument list, later hex values are not length restricted, so `0x80` and `f30` both work as suffixes in that position.

The mapping in practice:

```bash
$ glibc-aio puts 0x80970 system 0x4f440
[Online (libc.rip)]
  libc6_2.27-3ubuntu1.5_amd64          ← 精准命中
```

Two symbols given as name and address pairs are combined with AND, so a libc that satisfies both offsets is a candidate. Passing a path alone identifies the file, and passing a path plus a symbol name returns the offset within that file.

The convenience is real for a tool you use under time pressure, but it is also a discovery cost. The dispatch table in the project notes is the only documentation of this behaviour, and there is no single flag that disables it in favour of explicit subcommands. If you want predictable behaviour in a script, use the explicit `search`, `identify`, `download`, `diff` and `build` subcommands rather than relying on inference.

## Downloads come from four mirrors and unpack the deb for you

The download path tries four mirrors in order, tuna, ustc, ubuntu-archive and then old-releases as a fallback, stopping at the first success without telling you which one it used unless you ask. You can pin one mirror with `--mirror`, skip the debug symbols with `--no-dbg`, or keep the downloaded `.deb` with `--keep-deb`.

After downloading, the tool does the unpacking itself: it decompresses the `.deb` handling xz, gz and zstd, extracts the symbols to build the local index used later by `search` and `identify`, and cleans up the temporary files.

```bash
$ glibc-aio download 2.27-3ubuntu1_amd64
[+] Downloaded to libs/2.27-3ubuntu1_amd64
$ ls libs/2.27-3ubuntu1_amd64/
x86_64-linux-gnu/  .debug/                            ← libc 文件 + debug symbols
```

Two directories come out of it, the libc itself and the debug symbols. Getting the debug symbols is the reason to use this rather than a plain apt download, because the symbol table is what makes the local fingerprint and offset lookups work.

The first run needs a mirror index, which the project notes say takes about five seconds and writes a `list` file:

```bash
$ glibc-aio mirror update
[+] Saved 32 + 48 old packages to "list"
```

Until that file exists, the online package search has nothing to work with, so this step is not optional in practice.

## Diffing two libcs, and building one from source

The `diff` command compares two libc files on symbol level and on security properties. It reports added and removed symbols, offset changes and differences in RELRO, NX, Canary, PIE and RUNPATH.

```bash
$ glibc-aio diff libs/2.27/libc.so libs/2.35/libc.so.6
--- libs/2.27/libc.so
+++ libs/2.35/libc.so.6
+ 000000000012e3f0 STT_FUNC STB_GLOBAL posix_spawn_file_actions_addtcsetpgrp_np
- 0000000000091d40 STT_FUNC STB_GLOBAL __strspn_c1
~ system: 0x4f440 -> 0x50d60                        ← 偏移变化
~ puts: 0x80970 -> 0x80ed0
! relro: full -> partial                            ← 安全属性退化
```

That last line is the one that generalises beyond this use case. Comparing two builds for how their hardening differs is useful to anyone assessing a binary, not only to someone looking for offsets.

The `build` command compiles glibc from source. By default it runs inside a Docker container and picks the Ubuntu image from the version number: 2.19 maps to 14.04, 2.23 to 2.27 maps to 16.04, 2.28 to 2.29 maps to 18.04, 2.30 to 2.34 maps to 20.04, and 2.35 and later map to 22.04. Output lands in `libs/build/<version>/<arch>/`. When Docker is unavailable it falls back to building on the host, and `--no-docker` forces that path.

```bash
$ glibc-aio build 2.29 amd64                     # Docker ubuntu:18.04 容器内编译
$ glibc-aio build 2.27 i686                       # 32 位交叉编译
$ glibc-aio build 2.35 amd64 --no-docker          # 宿主机直接编译
```

The container path is the one to prefer for older versions, since the mapping exists precisely so that a 2.27 build happens on a 16.04 era toolchain rather than on your current distribution.

## Licence, configuration and the state of the tree

The licence is the first thing to sort out if you are reading this for a work context. The project metadata records a custom licence that GitHub cannot categorise, and the pyproject.toml states it in full as `Personal/Educational Use Only, No Commercial Use`. The LICENSE file at the repository root is where the authoritative text lives, and the classifier reading above is the closest summary the repository itself gives.

For a personal learning project or a security research context, that is straightforward. For a company that wants to use it in a product, a paid engagement or a commercial training pipeline, the terms as written exclude that use, and you need to read the file rather than infer from the topic list.

Configuration lives in a `[tool.glibc-aio]` block in pyproject.toml, with keys for `libs_dir` (default `libs`), `debs_dir` (default `debs`), `keep_debs` (false), `default_mirror` (auto), `dbg` (true), `docker_image` (auto) and `offline` (false). The offline flag is worth knowing about, since it is the switch for running the whole tool without network access.

On maintenance, the repository is not archived and the last push was on 2026-05-30. There are no GitHub releases, so the version to track is the PyPI package version, 2.0.0, matching the pyproject version. The project notes state the legacy shell version has been moved aside and is no longer maintained, with `glibc-aio` as the new v2 rewrite, and the package requires Python 3.10 or newer.

One gap to note: the project description in the package metadata mentions vuln as part of the toolkit, while the command reference does not list a vulnerability subcommand. If that capability matters to you, check the source under `glibc_aio/` before you count on it.

## Conclusion

Adopt glibc-all-in-one if you do reverse engineering work where you need to identify which glibc build a target uses and then fetch that exact libc with matching debug symbols, since the offline symbol fingerprint path works without a network. Do not adopt it in a commercial product, because the project licence is Personal/Educational Use Only with No Commercial Use, and do not expect it to be a general vulnerability scanner, since it ships no advisory database. Verify first that the mirror list is populated with `glibc-aio mirror update` before relying on online lookups, and read the LICENSE file yourself before using it at work.

## FAQ

### How do I install glibc-all-in-one?

Clone the repository, change into the directory and run `pip install -e .`. Python 3.10 or newer is required, and the install pulls in pyelftools for ELF parsing and zstandard for zstd deb decompression, with no other dependencies.

### How do I identify the version of an unknown libc?

Run `glibc-aio identify ./libc.so`. It extracts the BuildID from the .note.gnu.build-id section and queries libc.rip online, falling back to a local symbol fingerprint match. Use `glibc-aio identify --offline ./libc.so` to force the offline path.

### What does glibc-aio search --ends-with do?

It finds symbols in a local libc whose address ends with a given suffix, which supports the partial overwrite technique where only the low bytes of an address are controlled. It can be combined with a glob symbol filter to narrow the result.

### Can glibc-all-in-one be used offline?

Yes for the local operations. Online lookups hit the libc.rip API, but the local symbol database built during downloads is searched alongside it, and the identify command has an offline mode that uses only the local fingerprint. The pyproject configuration also has an offline setting.

### Can glibc-all-in-one compile glibc from source?

Yes, the build command compiles glibc, by default inside a Docker container with the Ubuntu image chosen from the version number, and falling back to a host build when Docker is unavailable. Output is written to libs/build/<version>/<arch>/.

### What licence does glibc-all-in-one use?

A custom licence recorded as Personal/Educational Use Only with No Commercial Use, with the text in the LICENSE file at the repository root. It is not one of the licences GitHub can categorise automatically.

## Sources

- [Issues](https://github.com/matrix1001/glibc-all-in-one/issues)
- [matrix1001/glibc-all-in-one on GitHub](https://github.com/matrix1001/glibc-all-in-one)
- [README](https://github.com/matrix1001/glibc-all-in-one/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/matrix1001-glibc-all-in-one
