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.
After randomly choosing digits and pressing the Enter key we receive the badboy message:

Okay let’s start analyzing the code and search for the function that checks our input:

[0x00000100]> aaa
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze len bytes of instructions for references (aar)
[x] Analyze function calls (aac)
[x] Use -AA or aaaa to perform additional experimental analysis.
[x] Constructing a function name for fcn.* and sym.func.* functions (aan)

Usually my plan in such cases is to start from the end, i.e from where the “FAIL!” message is printed. That’s because the checking function should probably be near by.

[0x00000100]> izzq~FAIL
0x2f3 6 5 FAIL!

izzq would print us strings that exist in the whole binary, q is for quieter output.

Cool, now that we know the address of FAIL! let’s find where it referenced from. Sadly xrefs doesn’t work this time so I did it the ugly way — grepping.

[0x00000100]> pd 1024~2f3
0x000002e4      21f302         ld hl, 0x02f3

pd stands for print disassembly. Check pd? for more commands.

We found that it referenced at 0x2e4 so let’s seek to this address and print the function:

[0x00000100]> s 0x2e4
[0x000002e4]> pdf
(fcn) fcn.00000274 107
  fcn.00000274 ();
0x00000274      f802           ld hl, sp + 0x02
0x00000276      5e             ld e, [hl]
0x00000277      23             inc hl
0x00000278      56             ld d, [hl]
0x00000279      210400         ld hl, 0x0004
0x0000027c      19             add hl, de
0x0000027d      4d             ld c, l
0x0000027e      44             ld b, h
0x0000027f      0a             ld a, [bc]  <.. truncated ..> 0x000002bd      fe01           cp 0x01 ; comparison
0x000002bf      c2e402         jp nZ, 0x02e4
0x000002d3      1803           jr 0x03
| 0x000002d5      c3e402         jp 0x02e4          ; jump to badboy
   ; JMP XREF from 0x000002d3 (fcn.00000274)
0x000002d8      21ee02         ld hl, 0x02ee ; another string
0x000002db      e5             push hl
0x000002dc      cd660f         call fcn.00000f66
0x000002df      e802           add sp, 0x02
0x000002e1      c3ed02         jp 0x02ed
0x000002e4      21f302         ld hl, 0x02f3 ; our badboy
0x000002e7      e5             push hl
0x000002e8      cd660f         call fcn.00000f66
0x000002eb      e802           add sp, 0x02
   ; JMP XREF from 0x000002e1 (fcn.00000274)
0x000002ed      c9             ret

s is used to seek to address and pdf stands for print disassembly function

radare recognized that our function begins at 0x274. We can see at the bottom some comparison, then it jumps to our badboy message or to another message which is a string at 0x02ee. Let’s see what string is hiding there:

[0x000002e4]> ps @ 0x02ee


ps stands for print string. @ is a temporary seek.


Great! We found our goodboy!
Let’s rename the function to check_input and start analyze it:

[0x000002e4]> afn check_input 0x274
[0x00000274]> s check_input
[0x00000274]> VV

The afn command stands for  analyze function name. VV will open the Visual Graph Mode

I used Visual Graph mode for convenience, the function combined from a lot of jumps and if-conditions so it’s much more easier that way.

Use p and P to toggle between the different visual modes.

Seems like we found the place where the function checks each digit and compares it with the correct one. On the left we can see the flow of valid digits. Let’s have a quick view of the blocks. We’ll toggle again between the views using p until we reach the regular graph mode.

This is just a snip of the full graph since it is too long to put as an image.

From a quick view, and without fully understanding the instructions, it seems like the binary is checking whether the digit in each place is equals to a specific immediate value. It checks it by using cmp imm in this order: 3, 7, 5, 1, 9.
Hooray! That was so easy, let’s just enter this value and get the WIN! message:

What? Fail?? Okay, okay, maybe the other way:


Bummer… So it’s not so easy after all. I probably need to have a closer look at this function.

After a while and a deeper understanding of the function and each condition (radare2 isn’t able to debug the program so it was even harder) I understood that the blocks are not so different from each other, except several lines. Although it’s a simple lines of code, the disassembly looked awful. the register bc is holding the address of our array and being manipulated during the execution of the program. All we had to do is to follow its changes and understand which digit is being checked in every block.

Let’s take a look, for example, on these blocks for example:

At the first block, 0x4 is moved (ld instruction) to hl which in turn moved to register bc and then the value which is referenced in bc is compared to 0x3. As I said, bc points to our input so this check checks whether bc+4 is equals to 0x4. In the next block we can see that bc, which returned to its original value, now increased (inc) twice and the value it is referenced to is compared with 0x7. In the last block of our example, bc returns to its initial value and then incremented once and its referenced value is compared with 0x5..

Finally I came up with this pseudo Pythonic code:

Let’s see if we got it right:

Yes! We did it and ended up with our beloved goodboy.


In this writeup I showed you more of the powers within radare2, this time its capabilities to analyze a non-trivial binary. Thanks condret and all of the great people in the radare community for this great challenge! Another thanks goes to all these angels who helped creating r2con this year, it was absolutely awesome.

If you want to learn more about radare2 I suggest you to start from the part 1 of my series “A Journy Into Radare2”.

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


[Pragyan CTF] The Karaboudjan



The Karaboudjan | Forensics 150 pts

Captain Haddock is on one of his ship sailing journeys when he gets stranded off the coast of North Korea. He finds shelter off a used nuke and decides to use the seashells to engrave a message on a piece of paper. Decrypt the message and save Captain Haddock.





This was funny challenge, I struggled with that Brainfuck but all it was is just brainfuck. Nothing more, we don’t need it to solve the challenge. Sorry guys.

I downloaded the zip file which was encrypted, I then cracked it using “fcrakzip” and dictionary attack. And found that the password is “dissect“. Inside the zip was a pcap file with one packet:


That’s it, we got the flag 🙂

The flag was pragyanctf{5n00p_d099}

[Pragyan CTF] New Avenger



New Avenger | Stego 300 pts
The Avengers are scouting for a new member. They have travelled all around the world, looking for suitable candidates for the new position.
Finally, they have found the perfect candidate. But, they are in a bad situation. They do not know who the guy is behind the mask.
Can you help the Avengers to uncover the identity of the person behind the mask ?
Those of you who read my blog frequently are already know how much I’m into superheroes. Give me a challenge with superheroes and you bought me. Although I’m more DC guy, this challenge was with the Marvels and still it was awesome! We’re given with a gif file. I ran binwalk on it to find whether it contains another files within.

Yep, the gif file contains two more files within, lets unzip the image:

Nice! We now have two more files: and 1_image.jpg. Now lets try to unzip

Oh-no, it requires a password. Lets have a look at 1_image.jpg.
Haha, funny image. Now I want to have a deeper look at this picture, I opened it in hex editor and found the password:

So the password is “sgtgFhswhfrighaulmvCavmpsb”, lets unzip the file:

Again?! We got 2 more files, and the password to the new zip was at the end of the new image, and the new zip contained another zip and an image. Well, I see where it going to, so I opened python and automate the process:

Ta-dah! We extracted all the zip files and gםt 16 images and 15 passwords. This was the last image:


So now we have 15 passwords, each contains 26 characters:

The password looks like garbage, it’s not Base64 or some known encoding. The first thing to pop up is the capital letter inside each password. Every password contains one or two capital letters. I know that the English alphabet contains 26 letters, so maybe I can map the location of each capital to the matching letter in the alphabet. i.e, if ‘F’ is in passw[4] i’ll take alphabet[4] which is ‘e’ and so on. I added this code to my script:

I ran the script and got meaningless string: “etitgepgztgxhiwthexstgbpc”. Damn! I was so sure that the mapping is the solution, how can’t it be?! All the facts point towards mapping the alphabet. I decided not to give up and ran Caesar Cipher on the string:

YAY! I was so happy to find Spidey is the new Avenger!

Here’s the full script:

The flag was: pragyanctf{peterparkeristhespiderman}

[Pragyan CTF] Roller Coaster Ride



Bobby has been into Reverse Engineering and Binary Exploitation lately.
One day, he went to an amusement park in his city. It was very famouse for its Roller Coaster Rides.
But, Bobby, being 12 years old, was not allowed on those rides, as it was open for people who were 14 years or older.
This made Bobby very angry. On reaching home, he hacked into the servers of the amusement park, got hold of the validation software for the Roller Coaster rides, and modified it, so that nobody is allowed to have a ride on those Roller Coasters.



We are given with a file, lets run file command on it determine its type.

Okay, it’s an ELF file. Lets execute it:


Okay let’s disassemble the file and look at the functions call tree:

Oh, we have lot of functions. All of them looks something like this:

An hex value is moved to r9 (smetimes r8) and then xord with hex value that was moved to rax. I manually xord all the values by order of calls, turn the results to characters and end up with the flag:

The flag was pragyanctf{r01l+th3m_411-up/@nd~4w@y}

[Pragyan CTF] The Vault



[!@# a-z $%^ A-Z &* 0-9] [1,3]
All we got is a file and regular expression.
Lets run file command on the file to determine its type:

The file is KDB file which is Keepass password database. Keepass is a famous opensource password manager.

I tried open it using KeePassX for windows, but we need a password to open the database. The password probably should match the regex, so I generated a dictionary with all the possible passwords (more then 300,000 words).


And I the ran John the Ripper to crack the password and went to eat lunch.

When I came back I saw that John found the password, now lets open the file:


The flag was pragyanctf{closed_no_more}

[Pragyan CTF] Lost Friends



Lost Friends Stego 300

Moana and her friends were out on a sea voyage, spending their summer joyously.
Unfortnately, they came across Charybdis, the sea monster. Charybdis, furious over having
unknown visitors, wreaked havoc on their ship. The ship was lost.

Luckily, Moana survived, and she was swept to a nearby island. But, since then, she has not seen her
friends. Moana has come to you for help. She believes that her friends are still alive, and that you are the
only one who can help her find them


Moana has lost her friends and we need to help her find them. We are given with an image which is absolutely blank. I opened it in Photoshop and saw that it’s completely transparent. So I grabbed python and Pillow and canceled the alpha channel (which is responsible for transparency).

I got this image:

Wooho, Chipmunks! It seems like every chipmunk is on another channel, lets split the channels:

Now we have three images of chipmunks:

I played with them, trying to find the flag but found nothing. So I got back to the original image and opened it with Hex Editor. At the bottom of the file I found this hint: “Psssst, Director, maybe ??”. So the flag is probably the name of the director of chipmunks. According to Wikipedia, Chipmunks has 4 movies, I tried to submit with each director and found that the director of the third movie is the flag.

The flag was praganctf{MikeMitchell}

[Pragyan CTF] Evil Corp



fsociety has launched another attack at Evil Corp. However, Evil Corp has decided to encrypt the .dat file with a CBC cipher. Reports reveal that it is not AES and the key is relatively simple, but the IV might be long. And remember, fsociety and evilcorp are closely linked.

Hint! Snakes serve the fsociety. Hmmm.

Hint! fsociety and evilcorp are too close, even 16 characters long together. Damn


This challenge was tricky for lot of people, the riddle was hiding in the questions itself. The challenge doesn’t require high skills, just understanding the meaning behind the words and hints.

From the question we know it’s a CBC cipher, but which? I got it just after the first hint was released, something to do with snakes. hmm… Serpent! Serpent is another term for Snake, and there’s Serpent-CBC cipher.

What about the IV? We know several things about the IV:

  1. The length of Serpent-CBC IV must be 32 bytes,
    2. Most of the Serpent decrypters are taking the IV as hex sequence
    3. in the question: “but the IV might be long”
    4. in the Hint: “even 16 characters long together…fsociety and evilcorp are closely linked”.

So, this made me believe that the IV is “fsocietyevilcorp” because len(hex("fsocietyevilcorp"))==32.

So we now know the algorithm and the IV, what is the Key? The question says “the key is relatively simple”. So I tried online with some simple and “obvious” keys until I recognize a valid header of file and found that the key was “fsociety“.


We got a leet JPEG image with the flag:

The flag was pragyanctf{hellofriend}

[Pragyan CTF] Supreme Leader



North Korea reportedly has a bioweapon in the making. Hack into their database and steal it.

Link :

For the second web challenge we’re given with a URL, lets open it.

Cute Kim 🙂

Now let’d dump the headers of the response using curl:


We can see an interesting cookie:  KimJongUn=2541d938b0a58946090d7abdde0d3890_b8e2e0e422cae4838fb788c891afb44f. The value of the cookie is looking like 2 MD5 hashes combined with “_”. Let’s try to crack them online using my favorite site.

That’s it! Here is the flag: pragyanctf{send_nukes}

[Pragyan CTF] Answer To Everything



Shal has got a binary. It contains the name of a wise man and his flag. He is unable to solve it.

Submit the flag to unlock the secrets of the universe.


In this challenge we have a binary, I ran file command on it:


Haha, weird. It is actually an ELF file and not exe. Lets execute the binary and give it the answer to everything (’42’) as an input:

At first I though that “#kdudpeh” is the flag but it isn’t, neither “kdudpeh”. The name of the person in the question is Shal, looking like SHA1, and the binary says “submit without any tags”, so “hashtagkdudpeh” without the tag is just “hashkdudpeh”. So I tried to submit the result of SHA1(“kdudpeh”) as answer but failed again. Then I tried Caesar cipher on “kdudpeh” and find “harambe”.

So I again tried submit the flag, this time with Sha1(“harabe”).

The flag was pragyanctf{31a0d851ea10ad886ad4e99ed05892de06998ab9} which is SHA1("harambe")


[Pragyan CTF] Interstellar



Forensics 150 pts

Dr. Cooper, on another one of his endless journeys encounter a mysterious planet . However when he tried to land on it, the ship gave way and he was left stranded on the planet . Desperate for help, he relays a message to the mothership containing the details of the people with him . Their HyperPhotonic transmission is 10 times the speed of light, so there is no delay in the message . However, a few photons and magnetic particles interefered with the transmission, causing it to become as shown in the picture . Can you help the scientists on the mothership get back the original image?


We are given with a photo, I opened it in Photoshop and saw that parts of it are transparent.


I grabbed Python and removed the Alpha layer from the image. The Alpha layer controls pixels’ transparency.

We got the result with the flag:


The flag was pragyanctf{Cooper_Brand}