Scripting r2 in Vala

Under some situations you need to automatize or extend the features of radare. There are so many scripting languages out there: python, ruby, perl, lua between others.

All of them are supported by the radare package and you can use them from inside r2 using r_lang plugins and the '#!' command or externally with the r2-swig.

The main issue on scripting languages is performance. The code is interpreted and all the api bindings are wrapped, so linked list accesses and function calls are highly penalized.

Here's where Vala joins the party.

Vala compiles into C and generates native code with no wrappers, but providing a higher-level interface than C, so it is harder to segfault.

Let's see how to run scripts for r_lang in the r2 prompt:

[0x8048520]> #!
 vala: VALA language extension

The '#!' (hashbang) command is used to invoke the r_lang REPL prompt or run the code of the given file.

The command has reported that it our build of r2 has built-in support for running Vala code from the core. So let's try it using the read-eval-print-loop mode.

[0x8048520]> #!vala
vala> print ("%p\n", core)  

This is what it's happening after each newline in the prompt:

  • wraps line with: 'using Radare; public static void entry(RCore core) {}
  • compiles temporary .vala file into a shared library against r_core library
  • loads the library and resolves the symbol named 'entry'
  • calls the entry point with the RCore instance as argument
  • unloads the library and removes temporary files

You can also write the vala code in a separated file named 'foo.vala':

[0x80498d2]> cat foo.vala 
using Radare;

public static void entry(RCore core) {  
        core.cmd0 ("pd 2");
        core.cons.flush ();

Execute this file with '#!vala foo[.vala]':

[0x80498d2]> #!vala foo
  0x080498d2        5e  pop esi
  0x080498d3      89e1  mov ecx, esp

For more documentation on bindings see the vapi documentation.

Solving crackmes with LDPRELOAD

This is a translation of this article.

One of the most common technics used in UNIX for analyzing and modifying a program consists in preloading a library to make the dynamic linker priorize the functions in there before the ones coming from external libraries.

In fact, in iOS, the whole MobileSubstrate thing and the Flex app are based on this concept to extend and modify the functionalities of the applications in a very simple way.

The procedure requires defining an environment variable (LD_PRELOAD or DYLD_INSERT_LIBRARIES in iOS/OSX). It is then parsed by the dynamic linker ( or dyld) which will load the library allowing us to:

  • inspect function parameters and contents
  • change the return value of a function
  • extend its functionalities
  • replace the implementation
  • dump backtraces
  • ...

To show up this theory I wrote a small crackme:


The disasm of that crackme in OSX looks like this:

Injecting libraries is only possible on non-static, non-suided executables. This can be checked with ls and rabin2:

$ isSuid() { ls -l $1 |awk '{print $1}' | grep -q s && echo YES || echo NO; }
$ isStatic() { rabin2 -I $1 | grep ^static | grep -q true && echo YES || echo NO; }

$ isSuid ./a.out

$ isStatic ./a.out

We're lucky! This crackme that executable is fine to continue our explanations ;)

At this point we must know which symbols and libraries do the program import or use. For that we will use rabin2, a program that comes with radare2 and will allow us to inspect and extract information from binaries, mostly executable programs and libraries.

$ rabin2 -qi a.out

$ rabin2 -ql a.out

Fine, looks like the executable is using printf and strcmp. We can asume that the program is using strcmp to verify the password provided by the user. So we will write a small library that will override the return value of it whatever which parameters it takes.

$ cat mylib.c
int strcmp(char *a, char *b) { return 0; }
$ gcc -fPIC -shared mylib.c -o mylib.dylib

$ rarun2 program=./a.out preload=mylib.dylib arg1=something
Are you tricking me?

If we change the return value, the crackme will detect it, because at first is doing an always-false conditional that will spot the hooker.

So, we need to create a condition or filter to make it return 0 only when called from the password check 'call'.

In this example we decided to reimplement strcmp to avoid making the example more complex and avoid explaining/depending on lazy binding and rtld-next features.

I wrote this (arch/compiler-specific) macro to retrieve the address of the caller.

#define GETCALLER(x,y)\
    void *x = (void*)*(&x+2+y);

int strcmp (char *a, char *b) {  
    GETCALLER(caller, 2+1); // 2 args + 1 import redirect
    if (caller == 0x100000ee7) {
        write (1, "INT\n", 4);
        return 0;
    int al = strlen (a);
    if (al != strlen (b))
        return 1;
    return memcmp (a, b, al);

The magic number 0x100000ee7 is the address of the next instruction after the call strcmp of the caller that we want to intercept, we takes this address because is the one stored in the stack.

We compile the library and execute the crackme with rarun2 to make him define the environment and inject the library in the program via LD_PRELOAD method or DYLD_LIBRARY_INSERT depending if running on Linux/BSD or OSX.

$ gcc -shared -fPIC mylib.c -o mylib.dylib
$ rarun2 program=./a.out preload=mylib.dylib arg1=something
You Win!

It's important to say that preloading a library allow us to introduce hooks on the calls to external libraries. This is.. we can't hook internal program calls.. or we do?

In the case of having the possibility to modify the program we can patch the calls to the function we want to hook to an external simbol in the PLT, and then let our LD_PRELOAD implementation decide which caller is accessing the hook and perform a redirect to the original destination.

This way we can hook internal or external function calls without having to reallocate the executable program.

Let's make an example to make it clear:

$ cat test.c
int test(char *a) {
    printf ("Testing arguments.. ");
    if (!strcmp (a, "foo")) {
        printf ("LE WIN!\n");
        return 0;
    printf ("FAILE!\n");
    return 1;
int main(int argc, char **argv) {
    return test (argv[0]);

We build and disassemble the program

$ gcc test.c
$ r2 -Aqc 'pD $SS @ $S' a.out

As we can see, the sym._text is defined at 0x100000e90. If we want to reimplement that function with an external one we will need to find a target import and write our call proxy in there, deciding which action take depending on the address of the caller. Import symbols are placed in the process memory and are overwriten by the dynamic linker to set the address of the mapped address of the library in memory.

$ rabin2 -i a.out
ordinal=000 plt=0x100000f38 bind=NONE type=FUNC name=printf
ordinal=001 plt=0x100000f3e bind=NONE type=FUNC name=strcmp
ordinal=002 plt=0x000000000 bind=NONE type=FUNC name=dyld_stub_binder

3 imports

$ rabin2 -s a.out | grep imp.
vaddr=0x100000f38 paddr=0x00000f38 ord=003 fwd=NONE sz=0 bind=LOCAL type=FUNC name=imp.printf
vaddr=0x100000f3e paddr=0x00000f3e ord=004 fwd=NONE sz=0 bind=LOCAL type=FUNC name=imp.strcmp

Once we get the address of the imports we can proceed to patch the program:

$ r2 -qc 'wa jmp 0x100000f38 @ 0x100000e90' -w a.out

If we disassemble sym._test now, we can observe a call to sym.imp.printf:

patched code

If we run the program now we will be able to see the expected password, because we are displaying the argument passed to strcmp

$ ./a.out

And then we run the original crackme with the correct password to verify:

$ ./a.out.orig ./a.out.orig

For this example we didnt felt the need to investigate much further, but this PoC clearly shows how to use r2 to inject LDPRELOADed libraries and how to patch executables. And mixing this with a carefully written library we can trace internal api calls or reimplement them on the outside.


Trainings and Translations

The summer is almost over and everyone is back to the main loop.

Some of us will be in Oct 21-24 at giving a talk and a workshop. See

But pancake (aka Sergi Àlvarez), the author and main contributor to the project will be busy giving two trainings in spanish:

He'll be there on October 2, 3, 4. Giving a free and libre 2h introductory workshop to r2 for reverse engineering.

For more information about the congress, entrance prices and transport check it at

Securizame course

In addition to this workshop, there will be an online course under the title "Curso de Reversing y Exploiting Avanzado en Windows y Linux". Where pancake will be teaching part of the introduction and the linux-reversing part.

The course will be online via the Webex platform and it is composed of different modules:

  • Introduction
  • Windows
    • Reversing
    • Exploiting
  • Linux
    • Reversing
    • Exploiting

As far as we know, there will be several use cases of r2 in the introduction and Linux reversing and exploiting modules. And probably some for windows, so if you know spanish and want to learn reverse engineering, exploiting or just get in touch with practical sessions of radare. This is your course!

NOTE September 15 is the last day for signing up on that training.

The book

The original book (radare1) was already reviewed and updated by maijin to be in sync with the very latest r2 versions.

After the update, we are now publishing the first translation of it, in Persian. Thanks to Mohsen Mostafa Jokar.

The book is still incomplete and should require more reviews, contributions and translations. But it's written in markdown and hosted in github, so we wait for your additions, comments, etc!