{"id":15389237,"url":"https://github.com/m4b/rdr","last_synced_at":"2025-04-15T12:19:16.301Z","repository":{"id":67890716,"uuid":"37824852","full_name":"m4b/rdr","owner":"m4b","description":"Rdr is a cross-platform binary analysis and reverse engineering library, utilizing a unique symbol map for global analysis.","archived":false,"fork":false,"pushed_at":"2023-03-15T15:39:23.000Z","size":3619,"stargazers_count":84,"open_issues_count":4,"forks_count":10,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-04-15T12:18:53.693Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"OCaml","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/m4b.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-06-21T20:33:21.000Z","updated_at":"2025-03-31T21:25:26.000Z","dependencies_parsed_at":null,"dependency_job_id":"8db86860-fec0-4c22-9a87-e6c851e8f74f","html_url":"https://github.com/m4b/rdr","commit_stats":{"total_commits":302,"total_committers":4,"mean_commits":75.5,"dds":0.08609271523178808,"last_synced_commit":"2bf1f73fc317cd74f8c7cacd542889df729bd003"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m4b%2Frdr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m4b%2Frdr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m4b%2Frdr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m4b%2Frdr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/m4b","download_url":"https://codeload.github.com/m4b/rdr/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249067787,"owners_count":21207396,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-01T14:59:49.111Z","updated_at":"2025-04-15T12:19:16.273Z","avatar_url":"https://github.com/m4b.png","language":"OCaml","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Rdr 3.0 - Welcome\n\n[![Floobits Status](https://floobits.com/m4b/rdr.svg)](https://floobits.com/m4b/rdr/redirect)\n\nWelcome to the `rdr` project.\n\n**MAJOR UPDATE**\n\nThis project is _completely_ finished, and as such, is no longer under active development.  Once I get some spare time, I will publish to opam this version, fix the mach threads hack (or wait until Rust no longer uses the unix threads load command), and probably call it a day!\n\nOf course, if anyone has any suggestions for improvement, pull requests can still be submitted and I'll probably merge it (but we know that's never going to happen) --- and I might add a feature every now and then, but, I consider `rdr` to be stable enough that I use it on a day to day basis, and that I just simply don't have the time to implement some of the nicer features.  But I hope you enjoy, and have fun with it!\n\n\u003e `rdr` is now version 3.0, supporting tools like [bin2json](http://github.com/m4b/bin2json), which further supports tools like [the silicon element suite](http://github.com/SiliconElements).  Here are some (new) features:\n\u003e\n\u003e * PE32 support\n\u003e * Unified export/import model using the Goblin binary format, a kind of IR for binaries\n\u003e * Disassemble symbols in a binary (as opposed to just symbols in the map) --- this is _still_ experimental and very much hacky, llvm-mc must be installed.  I'll figure out a better way soon, or write my own x86-64 and ARM64 disassembler, cause I'm crazy.\n\u003e * Print Goblin representation `rdr -g`\n\u003e * A slightly better symbol tree\n\u003e * Import library resolution for ELF, which looks up the imported symbol for a binary using the symbol map/tree\n\u003e * Better byte-coverage printing in addition to more extensive coverage\n\u003e * Scan the binary with a hexadecimal scan string - _no spaces or 0x_. `rdr --scan 5589e58b450839450c0f4d450c bin/pe/libbeef.dll` or `rdr --scan deadbeef bin/pe/libbeef.dll`\n\u003e * Disassemble at a particular offset (experimental): `rdr --do 0x51f bin/pe/libbeef.dll`\n\u003e * Print the particular binaries version of a \"section\". Section headers for ELF, segments for mach-o, and section tables for PE: `rdr --sections bin/elf/deadbeef.elf`\n\n`rdr` is an OCaml tool/library for doing cross-platform analysis of binaries.  I typically use it for looking up symbol names, finding the address offset, and then running `gdb` or `lldb` to mess around (you should be using both if you even know what you're doing).\n\nI also find that it's useful for resolving linking errors if you're trying to build some project, especially some random, misconfigured XCode project, or what have you.\n\nBasically it's the best, free, cross-platform reverse engineering tool out there.\n\nSee the [usage section](#usage) for a list of features.\n\nCurrently, only:\n\n* 64-bit **ELF**\n* 64-bit **Mach-o** (also will suck out the first 64-bit binary found in a fat universal binary)\n* 32-bit **PE32**\n\nbinaries are supported (64-bit PE32, i.e. PE32+ coming soon).\n\nAlso, 32-bit binaries aren't cool anymore; stop publishing reverse engineering tutorials on them (in nix land at least: apparently Microsoft [still publishes 32-bit binaries](https://go.microsoft.com/fwlink/?LinkId=532606\u0026clcid=0x409) for general consumption).\n\nHappily, the project has no dependencies (besides the standard libs and `unix` and `str`).  I have switched to an `oasis` build system however, and it's awesome, but does add some slight extra complexity (not really).  See the [install section](#install) for more details.\n\n# Install\n\n#### Easy (OPAM)\n\nInstall with OPAM: `opam install rdr`\n\n#### Slightly Less Easy (Manual)\n\n**NOTE** This will _not_ build on 32-bit systems.\n\n* You must have OCaml and `findlib` installed, and OCaml must be at least version 4.02 (I use the `Bytes` module and ppx annotations).  You can install findlib through your package manager; on Arch it's currently `ocaml-findlib`.\n* You must run `make`, or execute `ocaml setup.ml -configure \u0026\u0026 ocaml setup.ml -build` (especially if on 64-bit windows) in the base project directory.\n* You may then `sudo make install` (or `sudo ocaml setup.ml -install`) to copy the `rdr` binary to your `/usr/local/bin`, in addition to installing the library with findlib.  Or you can just `mv` the generated binary, `main.native`, wherever you want, with whatever name, if that's your fancy.\n\n# Usage\n\nEssentially, `rdr` performs two tasks, and should probably be two programs.\n\n## Binary Analysis\n\nThe first is pointing `rdr` at a binary.  Example:\n\n````bash\nrdr /usr/lib/libc.so.6\n````\n\nIt should output something like: `ELF X86_64 DYN @ 0x20920`.  Which is boring.\n\nYou can pass it various flags, `-e` for printing the exports found in the binary (see this post on [ELF exports](http://www.m4b.io/elf/export/binary/analysis/2015/05/25/what-is-an-elf-export.html#conclusion) for what I'm counting as an \"export\"), `-i` for imports, etc.  For mach-o and PE32 binaries, exporthood and importhood are clearly defined, so blog posts detailing this isn't necessary (unless you want a [detailed analysis of the mach binary format](http://www.m4b.io/reverse/engineering/mach/binaries/2015/03/29/mach-binaries.html)).\n\nSome examples:\n\n* `rdr -v` - prints the version\n* `rdr -h` - prints a help menu\n* `rdr -h /usr/lib/libc.so.6` - prints the program headers, bookkeeping data, and other bureaucratic aspects of binaries specific to the format your analyzing\n* `rdr -f printf /usr/lib/libc.so.6` - searches the `libc.so.6` binary for an exported symbol named _exactly_ \"printf\", and if found, prints its binary offset and size (in bytes).  _Watch out for_ `_` prefixed symbols in mach and compiler private symbols in ELF. Definitely watch out for funny (`$`) symbols, like in mach-o Objective C binaries; you'll need to quote the symbol name to escape them, otherwise bash gets mad.  Future: regexp multiple returns, and searching imports as well.\n* `rdr -D -f printf /usr/lib/libc.so.6` - disassembles the printf symbol if it's found.\n* `rdr -l /usr/lib/libc.so.6` - lists the dynamic libraries `libc.so.6` _explicitly_ depends on (I'm looking at _you_ `dlsym`).\n* `rdr -i /usr/lib/libc.so.6` - lists the imports the binary depends on.  **NOTE** when run on linux ELF binaries, if a system map has been built, it will use that to resolve the import's library.  Depending on your machine, can add a slight delay; sorry bout that.  On mach-o and PE this delay caused by an extra lookup isn't necessary, since imports are required to state where they come from, because the format was built by sane people (more or less).\n* `rdr -G /usr/lib/libz.so.1.2.8` - graphs the libraries, imports, and exports of `libz.so.1.2.8`; run `dot -O -n -Tpng libz.so.1.2.8.gv` to make a pretty picture.  Does a simple, hackish check to see if `dot` is in your `${PATH}`, and if so, runs the above dot command for you - you should probably just install it before you run this.  [See the examples](#examples) for `rdr` output.\n* `rdr -s /usr/lib/libc.so.6` - print the nlist/strippable symbol table, if it exists.  Crappy programs like `nm` _only_ use the strippable symbol table, even for exports and imports.\n* `rdr -v /usr/lib/libc.so.6` - print everything; you have been warned.\n* `rdr -c /usr/lib/libc.so.6` - prints the byte coverage `rdr` generated for the binary\n\n## Symbol Map\n\n`rdr` can create a \"symbol map\" for you, in `${HOME}/.rdr/`.  What's that you ask?  It's a map from `exported symbol name -\u003e list of exported symbols`, where symbol information is offset, size, exporting library, etc.  In the future I will add tags to the symbol; I'll explain what that means when the time comes.\n\nBut in other words, this is a map from keys of symbol names to _lists_ of symbol information, because symbol-to-symbol information is _not a function_.  To put that less technically: for any given symbol name, `malloc` for example, you can have multiple libraries which provide (export) that same exact symbol.  It is a one to many relationship.\n\nNevertheless, with such a map, we can perform a variety of useful activities, like looking up a symbol's offset in a library, its size, etc.\n\nWhy hasn't this existed before?  I don't know.\n\nYou build the map first by invoking:\n\n````bash\nrdr -b\n````\n\nWhich defaults to scanning `/usr/lib/` for things it considers \"binaries\".  Basically, it works pretty well.\n\nIf you want to recursively search, you give it a directory (or supply none at all, and it uses the default, `/usr/lib`), and the `-r` flag:\n\n````bash\nrdr -b -r -d \"/usr/lib /usr/local/lib\"\n````\n\nSpaces or colons (':') in the `-d` string separate different directories; with `-r` set, it searches _each_ recursively.\n\nBe careful (patient); on slow machines, this can take a whole bunch of time, especially on linux, where everything and their mother put their garbage in `/usr/lib` (I'm looking at _you_ node).  But on the brightside, if you're lucky enough to have one, on a recent MBP, it's so fast it can build the map in realtime, and then do a symbol lookup (I don't do that).\n\nAnyway, after you've built the map, you can perform _exact_ symbol lookups, for example:\n\n````bash\n$ rdr -m -f printf\nsearching /usr/lib/ for printf:\n           30f90 printf (334) -\u003e /usr/lib/libtsan.so.0.0.0 [libtsan.so.0]\n           4ed10 printf (161) -\u003e /usr/lib/libc-2.22.so [libc.so.6]\n           60c00 printf (284) -\u003e /usr/lib/libasan.so.2.0.0 [libasan.so.2]\n````\n\nWhere the output format for each symbol is `offset symbol_name (size) -\u003e /path/to/exporting/library [alias]`.  The alias is important for ELF, as it allows import resolution in the analyzed binaries (basically what the dynamic linker does --- it's awesome).\n\nIf you find a symbol you admire, you can disassemble it by adding the `-D` flag, using `llvm-mc`.  This is an experimental feature and subject to change (it'll definitely have to stay in though, cause it's awesome).\n\nAgain, I do a simple, hackish check to see if `llvm-mc` is in your `${PATH}`, and if so, the program is run, otherwise an error message is printed.  However, to quote a C idiom: \"this behavior is undefined\" if `llvm-mc` isn't installed and in your `${PATH}`.\n\nExample with `llvm-mc` correctly installed:\n\n````bash\n$ rdr -D -m -f printf\nsearching /usr/lib/ for printf:\n           4f0a0 printf (161) -\u003e /usr/lib/libc-2.21.so\n\t.text\n\tsubq\t$216, %rsp\n\ttestb\t%al, %al\n\tmovq\t%rsi, 40(%rsp)\n\tmovq\t%rdx, 48(%rsp)\n\tmovq\t%rcx, 56(%rsp)\n\tmovq\t%r8, 64(%rsp)\n\tmovq\t%r9, 72(%rsp)\n\tje\t55\n\tmovaps\t%xmm0, 80(%rsp)\n\tmovaps\t%xmm1, 96(%rsp)\n\tmovaps\t%xmm2, 112(%rsp)\n\tmovaps\t%xmm3, 128(%rsp)\n\tmovaps\t%xmm4, 144(%rsp)\n\tmovaps\t%xmm5, 160(%rsp)\n\tmovaps\t%xmm6, 176(%rsp)\n\tmovaps\t%xmm7, 192(%rsp)\n\tleaq\t224(%rsp), %rax\n\tmovq\t%rdi, %rsi\n\tleaq\t8(%rsp), %rdx\n\tmovq\t%rax, 16(%rsp)\n\tleaq\t32(%rsp), %rax\n\tmovl\t$8, 8(%rsp)\n\tmovl\t$48, 12(%rsp)\n\tmovq\t%rax, 24(%rsp)\n\tmovq\t3464671(%rip), %rax\n\tmovq\t(%rax), %rdi\n\tcallq\t-44329\n\taddq\t$216, %rsp\n\tretq\n````\n\nIf you don't like AT\u0026T syntax (FYI you should probably become a real hacker and learn to read and understand both syntax flavors), the lack of options, and a host of other issues w.r.t. disassembly, then you're out of luck for now.  Maybe make a pull request?\n\nYou can also graph the library dependencies (the `.gv` file is generated _at build time_ in `${HOME}/.rdr/`) with `rdr -m -G`.  Currently, it creates a `library_dependency.png` file; in the future, this will be named after the map it was generated from, once named maps become a thing.  Also, this `.png` will be probably be enormous.\n\nThis can be useful, if for example, you collate a series of binaries and shared libraries into a directory, and then have `rdr` build a map from that directory, and want to graph their interrelated dependencies.  If you want it to lookup the correct `/usr/lib` deps, then the full command might be something like: `rdr -b -G -D \"$(pwd):/usr/lib/\"`, and that map's dependency graph will be in `${HOME}/.rdr/lib_dependency_graph.png`.\n\nFinally, and again at build time, a `stats` file is generated from the system map in `${HOME}/.rdr/`; this simply counts the number of times a symbol was _imported_ by every binary analyzed when the system map was built (so with a `-d` directory specified, the default is `/usr/lib/`, and so it counts every time some symbol `x` was imported in every binary found in `/usr/lib`).  Expect this file to change, or various other statistical files to be created in the `${HOME}/.rdr/` directory.\n\nOnce versioned/named maps are implemented, the stats will be per map.\n\nThere are also times that you will want to `grep` symbols, maybe because you only know a part of it, or etc.\n\nFor now, this facility is enabled by writing a _flattened_ symbol map to disk, using `rdr -m -w`, located at `${HOME}/.rdr/`.  This file is named `symbols` and you can `grep` it to your heart's content.  It is flattened because each element in the list of symbol information a symbol maps to is output to disk.\n\nSo, for example, `grep -w \"malloc\" ~/.rdr/symbols` yields:\n\n````\n0x16a50 malloc (13) E -\u003e /usr/lib/ld-2.21.so \n0x576f0 malloc (303) E -\u003e /usr/lib/libasan.so.1.0.0 \n0x7a7b0 malloc (394) E -\u003e /usr/lib/libc-2.21.so \n0x346f0 malloc (137) E -\u003e /usr/lib/libgvpr.so.2.0.0 \n0x5f90 malloc (1543) E -\u003e /usr/lib/libjemalloc.so.1 \n0xb290 malloc (267) E -\u003e /usr/lib/liblsan.so.0.0.0 \n0x19c0 malloc (299) E -\u003e /usr/lib/libmemusage.so \n0x1200 malloc (33) E -\u003e /usr/lib/libtbbmalloc_proxy.so.2 \n0x1210 malloc (33) E -\u003e /usr/lib/libtbbmalloc_proxy_debug.so.2 \n0x367a0 malloc (2395) E -\u003e /usr/lib/libtcmalloc.so.4.2.6 \n0x3a640 malloc (2395) E -\u003e /usr/lib/libtcmalloc_and_profiler.so.4.2.6 \n0x3d740 malloc (718) E -\u003e /usr/lib/libtcmalloc_debug.so.4.2.6 \n0x1d2b0 malloc (2395) E -\u003e /usr/lib/libtcmalloc_minimal.so.4.2.6 \n0x242a0 malloc (702) E -\u003e /usr/lib/libtcmalloc_minimal_debug.so.4.2.6 \n0x4d020 malloc (175) E -\u003e /usr/lib/libtsan.so.0.0.0 \n````\n\n# Project Structure\n\nBecause I just knew you were going to ask, I made this _sweet_ graphic, just for you:\n\n![project deps](project_deps.png)\n\n# Examples\n\n* `rdr -G /usr/lib/libz.so.1.2.8`: ![libz so hard](http://www.m4b.io/images/libz.so.1.2.8.gv.png)\n* See my [gallery](http://www.m4b.io/gallery) for more inspiring images of what you can do with `rdr`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fm4b%2Frdr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fm4b%2Frdr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fm4b%2Frdr/lists"}