Reversing a Self-Modifying Binary with radare2



It took me three months to finish writing this article. I had so many tasks on my to-do list that sadly this one was pushed down to the bottom of the list. Last weekend I made a promise to myself that until Sunday I’m going to finish writing it, I successfully kept my word and here it is, another radare2 tutorial.

Today we’ll solve a very nice challenge, “packedup”, written by ad3l for r2con 2017 competition. It is not the first writeup that I publish from r2con competition, you can check out “Reverse engineering a Gameboy ROM with radare2” as well, make sure not to miss the cool swags I got from winning the competition.

This article is aimed to those of you who are familiar with radare2. If you are not, I suggest you to start from part 1 of my series “A Journey Into Radare2”.

So, without further ado, let’s dig into the binary.


Getting radare2


Radare2’s development is pretty quick – the project evolves every day, therefore it’s recommended to use the current git version over the stable one. Sometimes the stable version is less stable than the current git version!

If you don’t want to install the git version or you want the binaries for another machine (Windows, OS X, iOS, etc.) check out the download page at the radare2 website.


As I said before, it is highly recommended to always use the newest version of r2 from the git repository. All you need to do to update your r2 version from the git is to execute:

And you’ll have the latest version from git. I usually update my version of radare2 in the morning with a scheduled task, so I can wake up to the latest version available. If you’re using radare2 often, I recommend you do the same.


You can download packedup from here. I suggest you to star () the repository to get updates about more radare2 tutorials 🙂

First thing to do, obviously, is to execute the binary and get a basic feeling of what we are going to face.

packedup is executed, it requests us to give it a flag. It then probably does some calculations at the backend to see if the inputted flag is the right one. I entered “MEGABEETS” which is likely not the correct flag and finished with the fail message — “Try again!”.

Reversing time!

Now for our favorite part, let’s open the binary with radare2 and try to figure out how packedup is checking the submitted flag:

$ r2 ./packedup
— Here be dragons.
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze len bytes of instructions for references (aar)
[x] Analyze function calls (aac)
[*] Use -AA or aaaa to perform additional experimental analysis.
[x] Constructing a function name for fcn.* and sym.func.* functions (aan)


I usually begin with executing aa (analyze all) or with aas (to analyze functions, symbols and more). The name is misleading because there is a lot more to analyze (check aa?) but it’s enough to start with for most of the binaries I examined. This time we’ll start straight with aaa to make things simpler and due to the binary’s small size. You can also run radare2 with the -A flag to analyze the binary straight at startup using aaa (e.g r2 -A ./packedup).

Note: as I mentioned in the previous posts, starting with aaa is not always the recommended approach since analysis is very complicated process. I wrote more about it in this answer — read it to better understand why.

Getting Information

So now that we opened our binary with radare2, we have been located automatically at the program’s entrypoint. But before we start working on the code itself It’s a good approach to get to know our binary characteristics. radare2 can show us the information we need using the i command (I removed some information for the sake of readability):

The i command used for getting info about the opened file. It’s a wrapper around rabin2 which is an information extractor tool in the radare2 framework. radare2 offers us tons amount of information about the binary. Check out i? to list the information’s subcommands.

packedup is a 64-bit stripped ELF binary. Cool. Let’s move on.


One of my favorite ways to figure out where to start my analysis is to check the binary for indicative strings, and especially where they’re referenced from. To list all the strings in the data section we’ll use iz:

[0x004004d0]> iz
001 0x000007d0 0x004007d0 46 47 (.rodata) ascii Welcome to packedup for r2crackmes :)\nFlag <<
002 0x00000800 0x00400800 11 12 (.rodata) ascii Try again!\n
003 0x0000080d 0x0040080d 26 27 (.rodata) ascii Yep! you got the flag 🙂 \n

Nice! We have our “welcome” message and both the “Good-boy” and the “Bad-boy” messages. Let’s see where each is referenced from. To do this we’ll use a simple trick that radare2 has – built in loops:

[0x004004d0]> axt @@ str.*
main 0x400619 [data] mov esi, str.Welcome_to_packedup_for_r2crackmes_:___Flag
main 0x4006b8 [data] mov esi, str.Try_again
main 0x4006de [data] mov esi, str.Yep__you_got_the_flag_:

This command reveals us more of radare2 features. The axt command is used to “find data/code references to this address” (see ax?).
@@ is like foreach iterator sign, used to repeat a command over a list of offsets (see @@?), and str.* is a wildcard for all the flags that start with str..

This combination helps me not just to list the strings but also to list the function name, where they’re used and the referenced instruction.


As I mentioned before, all this time we were at the entrypoint of the program, now it’s time to move on. The strings we just listed are all referenced by ‘main’. In order to navigate from offset to offset we need to use the ‘seek’ command, represented by s. As you already know, appending ? to (almost) every command is the answer to all your problems.

[0x08048370]> s?
|Usage: s  # Seek commands
| s                 Print current address
| s addr            Seek to address
| s-                Undo seek
| s- n              Seek n bytes backward
| s–                Seek blocksize bytes backward
| s+                Redo seek
| s+ n              Seek n bytes forward
| s++               Seek blocksize bytes forward
| s[j*=]            List undo seek history (JSON, =list, *r2)
| s/ DATA           Search for next occurrence of ‘DATA’
| s/x 9091          Search for next occurrence of \x90\x91
| s.hexoff          Seek honoring a base from core->offset
| sa [[+-]a] [asz]  Seek asz (or bsize) aligned to addr
| sb                Seek aligned to bb start
| sC[?] string      Seek to comment matching given string
| sf                Seek to next function (f->addr+f->size)
| sf function       Seek to address of specified function
| sg/sG             Seek begin (sg) or end (sG) of section or file
| sl[?] [+-]line    Seek to line
| sn/sp             Seek next/prev scr.nkey
| so [N]            Seek to N next opcode(s)
| sr pc             Seek to register

So basically, the seek command accepts an address or math expression as an argument. The expression can be math operations, flag, or memory access operations. Since we want to seek to the main function, we don’t need anything special, we can do it by executing s main.

[0x004004d0]> s main


Now that we are at the main function we want to print its disassembly to examine it. There are many ways to disassemble a function using radare. You can use pdf (print disassembly function) or you can use more interactive ways – the Visual Mode (v) and the Visual Graph Mode (VV). You can use the way you find most comfortable to you. I usually use the visual modes since they’re more rich and interactive. Sadly, because this is not radare2 101 writeup I’m not going to explain how to use it, I explained it thoroughly in the previous articles.

Visual Graph Mode vs Visual Mode

Let’s start with having a look at the first block of main:

[0x0040060c]> pdf
 (fcn) main 244
   main ();
           ; var int local_10h @ rbp-0x10
           ; var int local_ch @ rbp-0xc
           ; var int local_8h @ rbp-0x8
              ; JMP XREF from 0x00400605 (entry2.init)
              ; DATA XREF from 0x004004ed (entry0)
           0x0040060c      55             push rbp
           0x0040060d      4889e5         mov rbp, rsp
           0x00400610      4883ec10       sub rsp, 0x10
              ; DATA XREF from 0x00400653 (main)
              ; DATA XREF from 0x004005e7 (entry2.init)
           0x00400614      ba30000000     mov edx, 0x30
           0x00400619      bed0074000     mov esi, str.Welcome_to_packedup_for_r2crackmes_:___Flag ; 0x4007d0 ; “Welcome to packedup for r2crackmes :)\nFlag << “
           0x0040061e      bf01000000     mov edi, 1
           0x00400623      b800000000     mov eax, 0
           0x00400628      e853feffff     call sym.imp.write      ; ssize_t write(int fd, void *ptr, size_t nbytes)
           0x0040062d      ba2c000000     mov edx, 0x2c           ; ‘,’ ; 44
           0x00400632      be80106000     mov esi, 0x601080
           0x00400637      bf00000000     mov edi, 0
           0x0040063c      b800000000     mov eax, 0
           0x00400641      e84afeffff     call       ; ssize_t read(int fildes, void *buf, size_t nbyte)
           0x00400646      4898           cdqe
           0x00400648      488945f8       mov qword [local_8h], rax
           0x0040064c      c745f0000000.  mov dword [local_10h], 0
           0x00400653      b814064000     mov eax, 0x400614
           0x00400658      bbf6064000     mov ebx, 0x4006f6
           0x0040065d      29c3           sub ebx, eax
           0x0040065f      31c9           xor ecx, ecx

After the function’s prologue, we can see arguments passed (System V AMD64 ABI) to write() to print the “Welcome” message and then another arguments passed to read() to read stdin input. read() is reading 0x2c (Decimal: 44) bytes from stdin and stores them into a buffer at 0x601080. We can assume that the flag would probably be 44 characters long. Let’s rename the address of our input so it’ll be better for us to recognize this address in the disassembly:

[0x0040060c]> f loc.our_input = 0x601080

f is used to create flags, a “bookmark” to a certain address. For more information check f? and read the chapter about flags in radare2book.

Then the program stores the number of bytes read into a local variable. At 0x400653 the program is moving an address (0x400614) to eax and another address (0x4006f6to ebx. The first address is the first instruction after main‘s prologue and the second is the last instruction before main exits. So basically we can say that eax and ebx are storing the start and the end of main. Immediately after that eax is subtracted from ebx so now ebx will store the difference between these two addresses.

In the next block, the program uses the bytes of the code itself in a loop until it finishes to calculate some initial value.

           0x00400653      b814064000     mov eax, 0x400614

           0x00400658      bbf6064000     mov ebx, 0x4006f6
           0x0040065d      29c3           sub ebx, eax
           0x0040065f      31c9           xor ecx, ecx
              ; JMP XREF from 0x0040066b (main)
       ╭─> 0x00400661      670208         add cl, byte [eax]
          0x00400664      c1c904         ror ecx, 4
          0x00400667      ffc0           inc eax
          0x00400669      ffcb           dec ebx
       ╰─< 0x0040066b      75f4           jne 0x400661
           0x0040066d      89ca           mov edx, ecx

Now for a fun part. In the next loop we can see how to program is validating our input. First, let’s have a look at the most relevant part of the code:

           0x0040066d      89ca           mov edx, ecx
           0x0040066f      89d0           mov eax, edx
           0x00400671      8945f0         mov dword [local_10h], eax
           0x00400674      c745f42c0000.  mov dword [local_ch], 0x2c  ; ‘,’ ; 44
              ; JMP XREF from 0x004006f4 (main)
           0x0040067b      8b45f0         mov eax, dword [local_10h]
           0x0040067e      89c0           mov eax, eax
           0x00400680      d1c0           rol eax, 1
           0x00400682      8945f0         mov dword [local_10h], eax
           0x00400685      8b45f0         mov eax, dword [local_10h]
           0x00400688      0fb6d0         movzx edx, al
           0x0040068b      8b45f4         mov eax, dword [local_ch]
           0x0040068e      83e801         sub eax, 1
           0x00400691      4898           cdqe
           0x00400693      0fb688801060.  movzx ecx, byte [rax + 0x601080] ; [0x601080:1]=0
           0x0040069a      8b45f4         mov eax, dword [local_ch]
           0x0040069d      83e801         sub eax, 1
           0x004006a0      4898           cdqe
           0x004006a2      0fb680a00740.  movzx eax, byte [rax + 0x4007a0] ; [0x4007a0:1]=15
           0x004006a9      31c8           xor eax, ecx
           0x004006ab      0fb6c0         movzx eax, al
           0x004006ae      39c2           cmp edx, eax
       ╭─< 0x004006b0      741c           je 0x4006ce

The value that was calculated in the previous loop is now moved into edx (at 0x40066d), which in turn is moving it to eax which is moving it to [local_10h]. Confused? me too. To put things simple, the value that was calculated in the previous loop is now at [local_10h]. Now we are starting the validation loop. The first instruction of this loop moves the value of [local_10h] to eax, then, at 0x400680 the value at eax is being left-rotated with 1 byte and assigned again to [local_10h]. At 0x400688 the lower byte (al) of the value is moved into edxAt address 0x400693 the program takes one char from our input and assign it to ecxAfter that, at 0x4006a2 the program takes one byte from [rax + 0x4007a0] and assigns it to eax. Let’s see what we have at 0x4007a0:

[0x0040060c]> px 44 @ 0x4007a0
– offset –   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x004007a0  0fc9 a886 ace0 1893 8aaf 91a2 e464 7a5a  .............dzZ
0x004007b0  088b a89a b4d1 1f84 b4d1 7152 1c8a 80d2  ..........qR....
0x004007c0  1495 8297 80d2 1f90 8f91 93a6            ............

Cool! It is a predefined byte array of length 44. It is obviously been used somehow in the comparison. Let’s flag it to loc.predefined_array using:

[0x0040060c]> f loc.predefined_array = 0x4007a0

Just for a reminder before we continue. edx now contains the lower byte of  rol(initial_value), eax contains the byte in index 0x2C (Decimal: 44) of the byte array at loc.predefined_array and ecx holds the last character of our input.

At 0x4006a9, ecx (the last char of our input) is bitwise XOR’d with eax (last value of the predefined array), the result is stored in eax. Then al is zero-extended moved into eax and then eax is compared with edx (The lower byte of rol(initial_value)). It will be easier to understand this operation using the following pseudo-python example:

If the result is indeed equal, i.e. ECX ^ EAX == EDX the loop is repeating itself with the next character from our input (2nd from the end), the next character from the predefined array (again, 2nd from the end) and with the result of rol(key)key is actually the result of performing left-rotation on initial_value, since this value changed in every rotation it isn’t “initial” anymore so now we’ll call it key.

The solution: 1st try

Now that we understood the logic of the program we can move to find a solution for this crackme. The key insight from the previous paragraphs is the understanding that there is a loop that contains an equation with three variables: ECX ^ EAX = EDX. We know that both EAX and EDX are predictable since they should always stays the same. EAX is coming from the static-predefined byte-array and EDX is the result of  n times key = rol(key) where n equals the number of the current iteration in our loop. The only variable that changes is EAX which is coming from our input.

So how can we know what input should we give to the program in order to make the equation true? We’ll use one of the coolest properties of Bitwise XOR — XOR is an involutory function (well, not exactly). Thus, and bear with me for a simple math, that means:




And that is awesome, right?! That’s mean that given ECX and EDX we can know what the value of EAX should be, in order to make the comparison return true. All we need to do is to write a python script and figure out what is the value of initial_value (i.e. EDX, key). We’ll start from the python script and then we will figure out the initial value of the key.

First we’ll define a lambda function for rotate left:

Then, we’ll create our predefined array. We’ll use radare for this:

[0x0040060c]>  pcp 44 @ 0x4007a0
import struct
buf = struct.pack (“44B”, *[

The pc subcommands (check pc?) is used to output the bytes in code formats of different languages as C, Python, Javascript and others.

We’ll add it to the script and define two more variables:

And the last thing is to implement the logic and combine it all together:


Awesome! Now we just need to find the initial value for the key. How do we do this? We should put a breakpoint after the loop which generates the initial value and check what is the result of this loop. Let’s open radare2 in debug mode r2 -d packedup or if your radare2 shell is still open you can use the ood command.

[0x0040060c]>  ood
Process with PID 1236 started…
File dbg:///home/beet/Desktop/Security/r2con/crackmes/packedup reopened in read-write mode
= attach 1236 1236

ood is used to re-open the current file in debug mode. It is a subcommand of oo which responsible of handling opened files. There’s also an alias for ood which is doo. I usually use doo since it’s easier to remember and more fun to say 😉

As you can see, our seek address changed to 0x7fb45818cf30 which is an address in the memory map of the dynamic loader ( We can know it by simply execute dm.:

[0x7fb45818cf30]> dm.

dm. is used to show the map name of the current address. You can use dm to list the memory maps of the current process. You can see more subcommand by executing dm?.

We know that the end of the loop is at 0x0040066d, this is where the result of the loop, which is in ecx, is moving into edx. Let’s put a breakpoint on this address and check the value of ecx:

[0x7fb45818cf30]> db 0x40066d
[0x7fb45818cf30]> dc

Welcome to packedup for r2crackmes 🙂
Flag << Blah_blah_blah
hit breakpoint at:

[0x0040066d]> dr ecx

the d? subcommand is used for anything related to debug session.

db stands for debug breakpoint and is used to define a breakpoint. Check db? for its subcommands.

dc stands for debug continue and responsible to continue the execution.

dr, debug registers, is used to display the value of a register. There are tons of subcommand to dr, check it out by executing dr?

Great! So now that we have the initial value of the key we can fill the missing part of the script key = 0xd477d83e and execute it:

What? This flag doesn’t make any sense. We must have made a mistake somewhere along the way, but where?

OH right! Silly me! Remember this sentence I wrote before?

In the next block, the program uses the bytes of the code itself in a loop until it finishes to calculate some initial value.

It totally slipped my mind. Using a software breakpoint as we did when executed db 0x40066d is adding CC (INT3) to the instruction and thus it changed the result of the calculation that is done by the loop at 0x400661. The INT 3 instruction generates a special one-byte opcode (CC) that is intended for calling the debug exception handler.

The solution: 2nd try

So, we need to find a way to get the initial value of the key without changing the code itself. That’s where Hardware Breakpoints come in handy. Let’s disable the software breakpoint and put a hardware breakpoint just at the same address:

[0x40066d]> db- 0x40066d
[0x40066d]> doo
Process with PID 1317 started…
File dbg:///home/beet/Desktop/Security/r2con/crackmes/packedup reopened in read-write mode
= attach 1317 1317

[0x7fcb28f77f30]> drx 1 0x0040066d 1 x
[0x7fcb28f77f30]> dc
Welcome to packedup for r2crackmes 🙂
Flag << Blah_Megabeets_Blahaaa

[0x0040066d]> dr ecx

Awesome! This time we found the right initial value, let’s put it in the python script and find the flag:

Come on… bummer. We failed again. So, what’s now? What are we missing? I’m sure the initial value is correct now that we used a hardware breakpoint. It is probably something in the algorithm that we missed, but what?

Now that we’re still in debug mode let’s seek again to the start of the checking loop at 0x0040067b, follow each step slowly and compare it with quotations from before where I explained it:

The assembly: 0x0040067b 8b45f0 mov eax, dword [rbp - 0x10]
The explanation:

[] Now we are starting the validation loop. The first instruction of this loop moves the value of [local_10h] to eax

The assembly: 0x00400680 d1c8 ror eax, 1
The explanation:

[X] Then, at 0x400680 the value at eax is being left-rotated with 1 byte.

Wait a minute! It was left-rotated (rol eax, 1, now it’s right-rotated (ror eax, 1)?! Of course we’ll get a wrong flag, our algorithm was all wrong. But how did it changed?
To understand that we should first put a hardware breakpoint on write access to this address (0x00400680) to see where this address is changed from.

[0x40066d]> doo
Process with PID 1611 started…
File dbg:///home/beet/Desktop/Security/r2con/crackmes/packedup reopened in read-write mode
= attach 1611 1611

[0x7fc43ae24f30]> drx 1 0x00400680 1 w
[0x7fc43ae24f30]> dc

The debug stopped at 0x400600, let’s print the instruction in this address:

[0x00400600]> pd 1
0x00400600   67c6406dc8   mov byte [eax + 0x6d], 0xc8

That’s it! It modify the instruction on this address. If before the opcodes of rol eax, 1 were d1c0, now it changes it to d1c8! We can use another great feature of radare2 to disassemble hex-string:

[0x00400600]> pad d1c0
rol eax, 1
[0x00400600]> # changed to
[0x00400600]> pad d1c8
ror eax, 1

Let’s print the whole function to understand it more thoroughly.

[0x00400600]> pdf
 (fcn) entry2.init 77
   entry2.init ();
           0x004005bd      90             nop
           0x004005be      90             nop
           0x004005bf      90             nop
           0x004005c0      90             nop
           0x004005c1      b87d000000     mov eax, 0x7d               ; ‘}’ ; 125
           0x004005c6      bbff0f0000     mov ebx, 0xfff
           0x004005cb      f7db           neg ebx
           0x004005cd      ffcb           dec ebx
           0x004005cf      81e314064000   and ebx, 0x400614
           0x004005d5      b9f6064000     mov ecx, 0x4006f6
           0x004005da      81e914064000   sub ecx, 0x400614
           0x004005e0      ba07000000     mov edx, 7
           0x004005e5      cd80           int 0x80
           0x004005e7      b814064000     mov eax, 0x400614
           0x004005ec      67c64050c1     mov byte [eax + 0x50], 0xc1 ; [0xc1:1]=255 ; 193
           0x004005f1      67c64051c1     mov byte [eax + 0x51], 0xc1 ; [0xc1:1]=255 ; 193
           0x004005f6      67c6405203     mov byte [eax + 0x52], 3
           0x004005fb      67c6406cd1     mov byte [eax + 0x6c], 0xd1 ; [0xd1:1]=255 ; 209
;– rip:

           0x00400600      67c6406dc8     mov byte [eax + 0x6d], 0xc8 ; [0xc8:1]=255 ; 200
       ╭─< 0x00400605      e902000000     jmp main

We see that this function named by radare2 as entry2.init and it contains a code that manipulates the main function. You can see how 0x7d is moved into eax at 0x4005c1 and then a syscall (int 80) instruction is performed at 0x4005e5. This syscall is for mprotect as can be found here. mprotect will make the code section writeable. After that, an address at the beginning of main() is moved to eax and some instructions are manipulated by the next instructions using eax and relative offsets. This is exactly where our rol became ror .


So what is this entry2.init function and how we missed it? entry2.init, as hinted by its name, is an initialization function. The function is executed prior to the execution of main. I’ll explain it a bit more.

Before transferring control to the application, the runtime linker processes any initialization sections found in the program. The addresses of the functions which are executed by the dynamic linker are contained in the .preinit_array and .init_array sections. The .init_array section contains an array of pointers to functions which will be executed when the program starts. The section contains only function pointers and not code. These functions are also related as constructors. Like the initialization functions, there are also termination functions (destructors) which are contained in the .fini_array section. These functions will be executed when the program exits normally.

radare2 also recognized the .init_array section. Let’s print its contents:

[0x00400600]> f~init_array
0x00600e08 16 section..init_array
0x00600e18 0 section_end..init_array
[0x00400600]> pxW 24 @ section..init_array
0x00600e08 0x00400590 entry1.init
0x00600e0c 0x00000000 section.
0x00600e10 0x004005bd entry2.init
0x00600e14 0x00000000 section.
0x00600e18 0x00400570 entry3.fini
0x00600e1c 0x00000000 section.

f is used to list the flags created by radare.
~ is radare’s internal grep.
pxW is stands for print hexadecimal Words (32bit).

We can see that there are three functions in this array, including our beloved entry2.init.

Just as an extra, you can define an initialization routine in a gcc compiled programs by using a template similar to this one:


The solution: 3rd try

So now that we know that entry2.init changed rol to ror we need to modify our script according to this new information. We’ll replace the rol lambda with ror and execute it again.

This is our new script:

And now let’s execute it for the third time:



Here another article about radare2 is coming to an end. In this writeup I showed you more of the powers within radare2, this time its capabilities to analyze a self-modifying binary. I’m aware that it’s hard, at first, to understand the powers within radare2 or why you should put aside some of your old habits and get used working with radare2. Having radare2 in your toolbox is a very smart step whether you’re a reverse engineer, an exploit writer, a CTF player or just a security enthusiast.

If you want to learn more about radare2 I suggest you to start from the part 1 of my series “A Journey Into Radare2” and from the second part which is more exploitation focused.

As always, please post comments to this post or message me privately if something is wrong, not accurate, needs further explanation or you simply don’t get it. Don’t hesitate to share your thoughts with me.

Subscribe on the left if you want to get the next articles straight in your inbox.


Reverse engineering a Gameboy ROM with radare2



A month ago in Barcelona I was attending to r2con for the first time. This is the official congress of the radare2 community where everyone can learn more about radare2 framework and dive deep into different aspects of reverse engineering, malware analysis, fuzzing, exploiting and more. It also the place where all of us, the contributors and developers of radare2, can meet, discuss and argue about every other line of code in the framework.

This was the second congress of radare2, after the success of the first congress in last year which was also a celebration for radare’s 10 years old birthday. This year the conference was bigger, fancier and probably organized much better. r2con was four days long, starting at September 6 and lasted until September 9. The first two days were dedicated to training and took place at Universitat de Barcelona. The other two days were talks days and took place at the MediaPro.

Crackmes Competition

During r2con this year there was a Crackmes competition where all the attendees were given with the same 5 challenges and had to publish a writeups to all the challenges they had solved. The scoring was based on the quality of the writeups along with the quantity of solved challenges.

I won the competition and got myself some cool swag!

  • Flag of radare2
  • POC | GTFO book
  • Orange PI with 3D printed case of r2con logo
  • Radare2 stickers
  • A beer 🍺


I thought of sharing some of my writeups with you, so you can taste a bit from what we had in the competition and so that others, coming from google, twitter and such, could learn how to use radare2 for solving different challenges. This article is aimed to those of you who are familiar with radare2. If you are not, I suggest you to start from part 1 of my series “A Journy Into Radare2”.

Getting radare2


Radare2’s development is pretty quick – the project evolves every day, therefore it’s recommended to use the current git version over the stable one. Sometimes the stable version is less stable than the current git version!

If you don’t want to install the git version or you want the binaries for another machine (Windows, OS X, iOS, etc) check out the download page at the radare2 website.


As I said before, it is highly recommended to always use the newest version of r2 from the git repository. All you need to do to update your r2 version from the git is to execute:

And you’ll have the latest version from git. I usually update my version of radare2 in the morning, while watching cat videos.


Playing with Gameboy ROM

This post will describe how I solved, a Gameboy ROM challenge written by @condret. It was actually my first time reversing a Gameboy ROM — and it was awesome!

First thing I did was to open the binary in radare2 and check for its architecture and format:

$ r2
— For a full list of commands see strings /dev/urandom
[0x00000100]> i~format
format   ningb
[0x00000100]> i~machine
machine  Gameboy

The i command gives us information about the binary. Check i? for more commands.

Tilde (~) is r2’s internal grep.

Surprise, surprise, it is a Gameboy ROM — dah. After reading a bit about its instruction set we should go to the mission. 

The obvious thing to do is open the ROM in an Gameboy emulator. I downloaded the good old emulator I used back in the days when I played Pokemon: VisualBoy Advance.

Let’s open the ROM in our emulator and see what we have:

Woops, wrong file. Bad habits… Let’s try again:

Cool! It’s a simple game where, by using the arrow keys, you increase/decrease 5 digits. We ‘simply’ need to find the correct password.

Continue reading

A journey into Radare 2 – Part 2: Exploitation



Welcome back to the second part of our journey into the guts of radare2! In this part we’ll cover more of the features of radare2, this time with the focus on binary exploitation.

A lot of you waited for the second part, so here it is! Hope to publish the next part faster, much faster. If you didn’t read the first part of the series I highly recommend you to do so. It describes the basics of radare2 and explains many of the commands that I’ll use here.

In this part of the series we’ll focus on exploiting a simple binary. radare2 has many features which will help us in exploitation, such as mitigation detection, ROP gadget searching, random patterns generation, register telescoping and more. You can find a Reference Sheet at the end of this post. Today I’ll show you some of these great features and together we’ll use radare2 to bypass nx protected binary on an ASLR enabled system. I assume that you are already familiar with the following prerequisites:

It’s really important to be familiar with these topics because I won’t get deep into them, or even won’t briefly explain some of them.

Updating radare2

First of all, let’s update radare2 to its newest git version:

We have a long journey ahead so while we’re waiting for the update to finish, let’s get some motivation boost — cute cats video!


Getting familiar with our binary

Our binary this time is quite similar to the one from the previous post with a few slight changes to the main() function:

  • Compiled without -fno-stack-protector and -z execstac to enable NX bit
  • Receives user input with scanf and not from program’s arguments
  • Uses mostly puts to print to screen
  • Little changes to the program’s output

This was the previous main():


And now main looks like this:


You can download the binary from here, and the source from here.
If you want to compile the source by yourself, use the following command:

The functionality of the binary is pretty simple and we went through it in the previous post — It asks for user input, performs rot13 on the input and compares it with the result of rot13 on the string “Megabeets”. Id est, the input should be ‘Zrtnorrgf’.


It’s all well and good but today our post is not about cracking a simple Crackme but about exploiting it. Wooho! Let’s get to the work.

Understanding the vulnerability

As with every exploitation challenge, it is always a good habit to check the binary for implemented security protections. We can do it with rabin2 which I demonstrated in the last post or simply by executing i from inside radare’s shell. Because we haven’t opened the binary with radare yet, we’ll go for the rabin2 method:

As you can see in the marked lines, the binary is NX protected which means that we won’t have an executable stack to rely on. Moreover, the file isn’t protected with canariespic  or relro.

Continue reading

A journey into Radare 2 – Part 1: Simple crackme



I was playing a lot with radare2 in the past year, ever since I began participating in CTFs and got dAnalyze alleeper into RE and exploitation challenges. I found radare2 very helpful with many CTFs tasks and my solutions had shortened significantly. It’s sometimes also my go-to tool for malware analysis tasks such as configuration retrievals. Sadly, I believe that only few people are familiar with radare2. It might be because they’re afraid to break out of their comfort zone (IDA Pro, OllyDBG, gdb) or they have simply not heard of it. Either way, I honestly believe that you must include radare2 in your toolbox.

Because I got really enthusiastic about the project and I want more and more researchers to be familiar with it, use it and hopefully contribute to the project, I decided to create a series of articles and use-cases of r2. Since these articles aim to teach you the basics of radare2, its features and capabilities, I’ll explain much more than you actually need to know in order to solve each task.

Welcome to IDA 10.0. (see radare2/doc/ for more fortunes)


radare2 is an open source framework for reverse engineering and binaries analysis which implements a rich command line interface for disassembling, analyzing data, patching binaries, comparing data, searching, replacing, visualizing and more. It has great scripting capabilities, it runs on all major platforms (GNU/Linux, .Windows *BSD, iOS, OSX, Solaris…) and it supports tons of architectures and file formats. But maybe above all of its features stands the ideology – radare2 is absolutely libre.

This framework is composed of a set of utilities that can be used either together from r2 shell or independently – We’ll get familiar with tools such as rahash2, rabin2, ragg2. Together they create one of the most powerful tools in the field of static and dynamic analysis, hex editing and exploitation (I’ll dive deeper in the following articles).

It is important to note that r2’s learning curve is pretty steep – although r2 have a GUI and a WebUI, none of them is quite enough to compete with the GUI or the convenience of IDA, IMHO. The CLI, however, including its Visual Mode, is still the core of radare2 and where its power lays. Because of its complexity I’ll try to make things as clear and simple as I can.

This is more or less how r2 learning curve works.

This is more or less how r2 learning curve works.

Before we begin you can check out the “Unfair comparison between r2, IDA Pro and Hopper” to get an idea of what we’re dealing with.


Getting radare2


Radare2’s development is pretty quick – the project evolves every day, therefore it’s recommended to use the current git version over the stable one. Sometimes the stable version is less stable than the current git version!

If you don’t want to install the git version or you want the binaries for another machine (Windows, OS X, iOS, etc) check out the download page at the radare2 website.


As I said before, it is highly recommended to always use the newest version of r2 from the git repository. All you need to do to update your r2 version from the git is to execute:

And you’ll have the latest version from git. I usually update my version of radare2 in the morning, while watching cat videos.


I Can’t think of a reason for you to uninstall radare2 so early in the article but if you do have you can simply execute:

Getting Started

You can download the first challenge here.

Now that radare2 is installed on your system and you have downloaded the binary, we are ready to start exploring the basic usage of radare2. I’ll work on a Remnux machine but most of the commands and explanations (if not all of them) would be the same for Windows machines and others.

Command Line Arguments

As most command line utilities, the best approach to reveal the list of the possible arguments is to execute the program with the -h flag.

I won’t paste here the full output, Instead I’ll point out those which I usually use in my daily work:

Continue reading