So, this presentation I will try to show you the project, what's the current state, the
features, most used plugins and which are the main features.
Okay, so first of all, a quick presentation, I'm Sergei Alvarez, everybody knows me by
my nickname, which is Pancake, I'm the author of the tool, I live in Barcelona and I work
at Now Secure, which is a company from US, which we basically use different static and
dynamic instrumentation tools for analyzing applications and find out privacy issues,
like identifying if the application is leaking data, stuff like that, and then generate some
reports for the customers and developers to improve the quality of the applications.
So I work as a senior mobile security analyst, I like command line tools, I like command
text interfaces, I brought many open source software, so my first goal is basically publishing
all the stuff that I'm doing, so I like free software, and I'm maintaining the whole
R2 ecosystem nowadays, so I'm basically focusing on R2, but I also maintain R2-Quitra, R2-Frida
and many other plugins that work with R2.
We'll have to reduce the font size here, this slide is a little bit.
So it's a 17-year-old project, so I started this tool basically as a forensic tool, I
wanted to recover some files that are lost in a hard drive.
The thing is that I was working as a forensic analyst, but I was not going to use the private
software that was in the company, so I wrote a simple hexadecimal editor that was able
to find some patterns in the disk, and then dump like a one megabyte from there.
After this I was interested in participating in CTF and different competitions for reverse
engineering, and I found out that there were so many tools that didn't really solve my
problems, so starting by, for example, GDB, it was not possible to script it at the time
and typing comments all the time, it was kind of tedious, and I just wanted to automate
many things.
Also, there was hexadecimal editors, but it was not possible to extend them with plugins
or anything like this, and there was like disassemblers, but Object Dump is cool, but
it's not interactive, and the only interactive tool was private, which is IDA, and anyway,
there was no real ecosystem for open source to solve any of these problems at once.
And there were so many little tools that were solving one problem, but not really being
able to integrate with the rest of the ecosystem or other tools.
So I decided to start picking ideas, picking tools, developing everything from scratch,
that's why I did R2, because R2 is not depending on anything, so you can, you only depend on
the postics like Slipsy, and all the rest of dependencies are written from scratch,
like console handling, read line interface, all the socket interface, parsing libraries,
disassembling things, etc.
It's licensed under LGPL3, and yeah, I mean, the focus of the project is basically to read
other tools and be useful for hackers.
It's not going to be a general proposed solution for all the problems, because for example,
I don't plan to write like disassemblers from scratch, I think that there are better projects
for this, so I'm integrating them into R2.
Same goes for like Lipoak, it's one of the tools that is able to use R2.
It's fully written in C, I mainly focus on portability because I like the things that
I write to run everywhere.
So the only option nowadays is C, I mean, there is some rast haters around that, anyway.
The thing is that R2 can be run, can be compiled into WebAssembly, so you can run R2 inside
your browser, you can also build it in a statical link at single binary, so you can drop it
in a router.
This year I plan to port it to a UFE, so you can run R2 inside your bootloader, and then
you can use an independent operating system to use R2, mount file systems, and things
like that.
So there is some really high constraints on all the code that are shipping R2, so there
is like a CI that is basically verifying everything, there is like a 24-7 fuzzer that
is running and finding bugs and fixing them, so my policies, I don't let bugs stay for
more than one day.
So the code cannot contain like setJAMP, or Abort, or Asserts, or anything like this,
because if you are doing something in hot, you don't want things to crash or to break.
So the idea is that all the code that is running in R2 must be used from a library, so I don't
want to use like double variables, I don't want to depend on something that, if it's
not parsing properly, I don't want to crash, I want the, if the Moloch is failing, I want
the program to still run, things like this.
So this is the main concern that I have when I write code for R2.
It's developing a single repo, but it's separated in different models, so it's like a big project
in one repository, but there is like a bunch of libraries, each library has like a bunch
of plugins, and many of these plugins are integrated or exposed, interfaces for extending
it with scripting languages.
So at the end is basically like a different layers of capabilities that can be extended
pretty easily at different layers.
So there is like a common line interface, so you have like a prompt, you can type things,
there is like a visual mode, which is basically a list of comments that you execute every
time that you press a key, and then you have the panels mode, which is like you can make
splits, you can have like different tabs, you can have like different frames and so on,
and then there is web interfaces, there is some people writing graphical interfaces
for it, like Yaito, which is the Qt interface for it.
For scripting, the easiest way for scripting R2 is Ertopipe, which is basically the simplest
interface for interfacing with anything, which is basically you run something, you pass a
string with a comment, and then you get the output of the comment as a string, but there
is also bindings for the CAPI, there's automated bindings for Python, for Rust, etc.
And there is also support for using these bindings from different scripting languages.
So what are the libraries implementing or exposing?
So you have the IO library, which is basically abstracting the access to the IO, this basically
defines how you access like a file, everything is abstract, this means that a file doesn't
need to be anything physical, there is support, I mean you cannot map like a full file in
memory and then work on it because this is abstracted by the IO.
So you can map like a remote file in a running in a remote instance of R2, so you can run
R2 as an instance, and then you can map for example like a ptrace backend, which is basically
reading and writing memory from another process, and this is like another IO interface, and
all that stuff is just the file descriptor.
So when you have like one IO open, then you can map this file descriptor into separate
maps, a map is basically a portion of the memory taken from the file descriptor, so
you say that from this offset to this offset from this file descriptor will be mapped in
this virtual address in the IO space of R2, and then there are IO banks, and IO banks
are basically a bunch of maps, so you can have like separate memory spaces, like for
example you want to relate like a thread local stretch, you can have like one IO space that
only contains the contents of the thread local stretch, but then there is like another bank
that contains all the memory layout of the processing memory, and you can do that just
by typing comments, you can do this also by using the API, but anyway, it's also possible
to create like SQL memory maps, memory layouts, for example B850 is like an architecture that
is used for automobiles and things like that, and this architecture basically relies on
having like some solid infrastructure, so you see there is some models that have like
two CPUs executing the same code at the same time, and there is like a verification that
two CPUs are doing exactly the same at runtime, and the memory of this CPU is basically SQL,
so there is some references that are going backward, so you have like one instruction
at the zero address that is referencing something up, and this something up is basically going
to the negative of other space, and this negative other space is not 32-bit in size, it's 26
for example, so you can basically configure this kind of things inside the R2, and you
can basically get emulation, all the flags which are basically naming offsets in all
these things and everything will be shaped properly, you can also define bit sizes memory
spaces like 7-bit bytes and things like this, it's also able to pass binary formats, this
works on any of the memory like I have said before, so you can pass from memory, you can
pass from disk, there is support for the most known well-filed formats from console, binary,
ROM, headers like Gameboy etc, but there is also for LFP, Makrokov etc, it's also parsing
Dwarf, PDB and other debug information, this is only for getting like address of memory,
making like a file name and so on, it's not really exporting all the structures and so
on, but it's also possible to do that in the future, or using several libraries, it's
also parsing like class information from SWIFT, Objective C or C++ binaries, and all that
stuff is integrated inside the R2, so you can, it's subtracting all the information
from all these final formats into single naming, so for example, imports in a PE is not the
same as like an import in ELF, but for R2 is the same, so when you want to list what
a binary is importing from other libraries, you can just use give me the imports, you
don't have to use like different APIs or different comments depending on the file format, so
it's unifying all the formats into a single naming, it's also supporting assembling and
assembling, it's using like one API, so there is like a library that exposes an interface
for doing this, and this library exposes plugins, so there's like plugins that are used by
this API, and then you can basically implement like new architectures, like writing plugins
for this library, but it's not only used for assembling and disassembling, which is basically
text bytes, there is more low level detailed information, like you can, for some architectures
you can get like a structure metadata, like which is the first operand, which is the size
of the second argument, things like this, but it's also exposing a seal, a seal is like
a very simple text interface for explaining what an instruction is doing at low level,
it's kind of, it's very similar to fourth, like a stack based machine, and it's basically
one statement separated by GOMA, so you have like O, GOMA, AX, GOMA equals, means that
it will be pushing the number, then pushing the register name, and then pushing the operation,
which is the equal, and then popping up from the operation to execute the statement.
The reason for that is because there is so many ways to extend or to define an architecture,
and there is some really fucked up things that can be done in so many architectures,
so I was not going to define like extensible structures or doing some really complex things,
because at the end I was always finding like something that was not compatible with another
architecture, and I end up like saying, okay, I just can define like a comma separated string
that it's just located in a single memory chunk, and I can just split it by comma and
then emulate that.
So there is a bunch of tools or libraries that can be, that are using a seal to extract
this information, and then use that for emulation, use that for extracting information from a
specific instruction, or even for the compiling.
It's very portable, so it works on support debugging also, so you can do local and remote
debugging.
This means that you can run R2 as a local debugger in your Linux Mac or iOS device, but you can
also attach to remote GDB or YDBG, et cetera.
It's a functionality for searching for different patterns, so you can search for strings, access
and model values, you can also find me something that is repeated multiple times, and then
it will be finding like if there is any pattern that is repeated many times and give you the
offset of these things, it's also able to generate function signatures, so by taking
all the whole analysis for the program, it will identify all the functions, basic blocks,
et cetera, and then you can generate like metadata for each of these functions, and
this metadata can be imported again to search for this information in our binary.
So you have like one binary with dwarf information, or the back symbols, then you can import this
into a binary that is a stripet, and then you can basically identify these data structures
or functions in another binary that is not containing this data.
It's also possible to div code level, but you can also div data, you can find like using
delta-diffing, so you have like two binaries that contain the same data, but in different
offsets it will identify which offset is the stripet in the binary, and which is the main
difference from that, it's not byte per byte level instruction checking.
You can also div basic blocks, like you get the two control flow graphs, and then identifying
which basic block is added, which removed, or if there is like a percentage of difference,
so you can use that for bin-diffing, and you can also find differences like ABDIF for
getting like there is new symbols removed, or things like that.
I also took code from Grapp, a group, which is basically the bootloader, and I used that
for parsing file systems, things that group is doing a lot of things for like assuming
that the file system is correct, and R2 will never assume that anything is correct, so
if there is like a corrupted file system I want to be able to mount it, so R2 is using
this code basically for mounting file systems, you can have like a fake, or like a virtual
file system interface in starter 2, and you can use that for mounting local or remote
file systems.
You can use R2-free, I will show that later, but I don't have time for showing it, but
anyway, I will, you can use Freeda, which is like a tool for injecting code in remote
applications, and you can use TCP or USB for communicating with that, and then Freeda can
expose like an interface for accessing files remotely, so you can mount zips in a remote
file system, extract the zip contents from one binary, pass the binary in local, mount
that memory layout in local, and then whatever you would like to do with these things.
Okay, obviously there is like a huge amount of things that can be done with that, so there
is a need for a package manager.
So I wrote R2-PM, it was like a 200 line shell script, so it's not really a big thing, but
one year ago I decided to write it in C, so this way you can basically run the package
manager anywhere, even in Windows, so it doesn't depend on anything that is not the same R2.
So this package manager is basically pulling a zip repository, and this repository contains
like scripts, and this script is basically defining a very simple way for installing
and uninstalling, so it defines instructions for compiling and installing the plugin, and
there is like basically a bunch of tools that are installed in your home, and also plugins
that are loaded by R2.
So the most common or most used plugins for R2 are, for example, about the compilers you
have like R2-Dec, you have R2-Gidra, R2-Reddeck, so if you know Gidra for example, they provide
like a compiler, there is like a part of the compiler which is written in C++, not in Java,
and this code can be reused for writing at a compiler without depending on the whole Java
thing, then there is Reddeck, which is the compiler based on LLVM and a bunch of parallel
scripts that mess the thing, and they basically use the compiler toolchain to do the backward
steps, to get from the binary disassembly to get like C like code for the compiling.
Then you can also use the Aphora, there is support for signatures for IDA, there is like
native signatures, there is like some repository of people writing this, and then there is
support for Frida, if you know Frida, who knows Frida, where is your hand, okay, half
of the room.
Is that the compiler, right?
No, Frida is a tool that basically injects code in a remote process, and then there
is an agent that is running in a separate thread inside the process, so you can basically
instrument the process at runtime, and you can basically inject JavaScript code or C
or assembly inside the remote process and instrument that.
You can use that for profiling, you can use that for modifying behavior, you can use that
for tracing APIs, identifying when a specific function is called with some arguments, and
then execute some code inside the remote process.
Most people use JavaScript for doing this, but you can also use C with libgam or whatever,
and yeah, we basically use that for dynamic instrumentation on iOS and Android applications.
So you can use R2 Frida to have like a R2 interface for interfacing with Frida, which
means that you don't need to type long JavaScript one-liners, you can also use R2 comments like
which are pretty mnemonic and easy to type, if you know them, and there is also support
for external assemblers like NuoGas or the Unicorn library, which is kind of like a stripping
code from LVM, and there is also program solvers like Radius, SteelSol for Anger that are plugins
that basically you define some constraints, you have like a function and you define, okay
I want to know which are the arguments that I need to pass to this function to reach these
specific others, like you want to know for example if it's possible to create like a
buffer overflow in a specific variable in a local stack, or you want to define which,
or you want to know which is the password that matches a specific crypto algorithm,
so you can use that to define, okay, I want to know which is the amount, the block of
bytes of one specific length that generate this hash, for example, things like that,
and these won't be brute forcing, it's like using program solvers like Z3 and so on, so
there is like different plugins that are integrated in R2 to use from R2 comments, and then you
can define the preconditions, post-conditions, and the boundaries of the function to emulate.
Then there is also support for parsing that structure, there is support for Kaitai, there
is support for poke, this was integrated last week, because I didn't know it was possible
to have like a library of poke, I was seeing it as a program, not a library, so it's integrated
but it's not fully integrated, so I plan to continue integrating it to use like for disassembling,
for parsing, headers, etc.
So what can you do with R2 Frida?
R2 Frida is basically, as I said before, it's front end for Frida, you can run scripts
in your host, in your agent site, so you can write a JavaScript program that runs in R2,
but it can be also loaded in the remote site, and you can load and unload plugins, so you
can basically extend the R2 Frida comment set with JavaScript plugins that are loaded
and unloaded at runtime.
It's also scriptable with R2 Pipe, so you can write a program in Python, JavaScript,
or the language you like, that interacts and automates comments and actions in the host
site or the remote site of the Frida site.
So you can spawn applications, you can attach to local remote processes, you can use different
protocol or communication channels like USB, TCP, etc.
You can remote the file systems, you can use that for interfacing with tracing APIs, profiling,
and also supports extracting metadata from Java, Dalvik, Objective-C, and Swift support
will be ready by the end of this year, because right now it's supported, but it's kind of
like unstable, and the API is changing, so yeah, sort of like it will get better.
So let's talk about R2 Pipe.
Once the release, well, the first release that they did this year was the 5.8.0, I planned
to keep ABA stable, actually I use ABDF in the CI, so every comment or pull request that
people send to the project, they verify that it's ABA stable.
This means that I'm not breaking the ABI, you can rebuild or update R2 without recompiling
all the plugins or the tools that are using R2 libraries.
This is pretty cool, and the thing is that I was having some kind of contract with myself
that I don't break ABI, but this is something that you end up doing Ruby when code by hand,
and having a tool that can automate this is great.
But I wanted to have a runtime, something that you can run from R2, like interpreter,
that is not a custom language or external library that needs to be integrated and it's
really big.
I was experimenting for some time with different languages and realizing that QuickJS is the
only option, so even Lua is using setjump, so you cannot compile with Lua as a WebAssembly
plugin.
Also, if you want to use setjump with threads, it's kind of a mess.
So I ended up picking QuickJS, which is the same JavaScript runtime that Frida is using.
I picked the code from there, and as long as every comment in R2 is verifying with
fuzzers, other sanitizers, and so on, I end up finding a lot of issues there.
I sent like 12 patches to the project, so it's basically the fork that is used by Frida.
So all these patches are upstream now, and the idea is basically that you can use TypeScript
and JavaScript from R2, and you can write code like this.
So you basically have an R2 pipe interface, but it's running inside R2.
You can use this from WebAssembly, so you can basically open R2.online, and then you have
a terminal that you can run R2, drag and drop a binary inside the browser, and use JavaScript
to automate a bunch of actions for organizing the binary.
Basically as I said before, you have a command that you run, and then you get the output
of the command in exchange.
As long as most of the comments in R2 speed out JSON, you can basically use the cmdj,
which basically get the output of the command and pass the output as JSON.
And then you get like a structure data that you can use for extracting it or processing
it with the tools you like.
I think that JavaScript and JSON are quite standard and useful nowadays, so you don't
need to learn new things, but there is support for so many other languages.
Like I said here, there is Python, support, Rust, Node.js, Rabi, Guile, Nivellisp, Haskell,
Dlang, Swift, etc.
So it's very easy to write this simple interface, and you can use basically different interfaces
to communicate with R2, so you can use like a fork and a pipe, or you can also use like
a TCP socket or an HTTP interface, WebSockets, whatever you like.
And for the TypeScript thing, it's pretty cool, because I'm writing like a Type description
that basically defines the APIs of R2, and also the structures that the commands are
returning in JSON format.
This means that you can get the JSON of a command, and then you can generate a schema
out of that.
And this schema can be used like a Types.
So if you use TypeScript, ListServer, like the language service that autocompletes all
the code, you can basically use that for using Type to autocomplete all the code.
So for example, you can analyze function, you press P dot I, and then you get all the
function name, you can get all the basic blocks, for each basic block you can use Type to get
all the fields of this basic block, like the address, the amount of instructions, etc.
And for each instruction, you can get the mnemonics, etc.
And everything runs.
I mean, you can use, like, Visual Studio Code, or NLVM, or whatever you like, or MX, I guess,
that's also Supercell SP, and use that for automating and scripting using these languages.
So R2 is able to visualize data and code in so many different ways, so all this, I mean,
I can press E, so you can get the source code of the slides.
So you can see here, this is the contents of the slide.
So it's running a bunch of comments in R2, and the output is generated inside the visual
mode that you saw before.
So you can generate graphs, you can, from the control flow graph, you can also generate
like a vertical horizontal line graph, like frame things, you can disassemble, you can
render pictures in bit formats, in RGB format.
You can also generate, like, different, like, comparing data and identifying which bytes
are changing, by changing colors, you can define, like, a color for a specific bunch
of addresses.
So when you are disassembling, you can mark some regions, like, hot code, or this is,
like, a portion of code that you're interested, and then you get headlights for one specific
register, so you want to highlight SP, and then you get SP highlighted in the whole
disassembly, things like that.
But also, there is also UIs, but I'm, like, common line guys, so I prefer to use the shell.
But there is, like, a Qt interface, but also I started to write, like, a new graphic interface
using WX Widgets, because, I mean, Qt is great, because it's big, and it solves so many things,
but I don't like the license, it's so huge, it's getting, like, really huge, and it's
not handy for the kind of things that I like to do, so when I'm developing, I like to have
fun, and I don't want to be suffering because of license, or companies that are developing
things in the background.
So I wrote so many UIs for it, too, like, in GTK, in using InBlip, also other HTML, CSS,
for the web UI, because I do have, like, a web server inside, so at the end, I want to
have fun, and I don't want to spend time, like, learning new APIs, and so on.
So I'm writing, like, a WX Widgets API, a user interface, and the idea for this is to
not follow the same flow, interaction flows that people use.
So I want to have, like, a common line interface, but integrated in the UI.
So I want to be able to have multiple windows using multiple sessions, or drag and drop
things from one window to another one, instead of having, like, a big thing with panels and
the common interaction ways.
So what's the future?
So there are short and long-term plans.
It all depends on my time, because most of the things are maintained or done by me.
There is a lot of contributors, but they come and live, so there is, like, not really a
core developer team, or there is no really big plans for having, like, big organizations,
there is, and so on.
But the thing is that I want to be able to keep patching, like, stable releases.
I want to have, like, ABA stability, mainly because there is some people or companies
or users that are writing tools on top of this, and I don't want them to rewrite things
every time that I make a release or break without updating this.
I want to have, like, a create, so which is a Rust API that you can basically specify
the version of R2 that you want to ship, and then this create will build R2 inside with
a specific version, and then you can use your R2 statically linked inside your program.
So you don't need to depend on system installations or depend on other things like that.
I want to basically reduce the tech depth, because as long as I'm alone doing most of
the things, I don't want to depend on humans.
So I want to reduce the amount of things that are done manually.
So for example, a friend of me brought, like, the flatback integration, so there is, like,
a bot that basically detects when there is, like, a new release in R2 or in Yaito, and
when this happens, it's basically pulling the code from all the projects, generating
a changelog, generating a new build, and publishing that automatically.
And you basically get, like, a graphical interface for Linux and Windows for free.
I want to improve the code coverage and all the testing for fuzzing, and, yeah, I mean,
there is, like, a lot of things that you can see, and if you have questions, please let
me know after the talk with some beers.
And I guess that everyone is hungry, so...
Thank you so much guys.