Crackme0x09 Dissected with Radare2

Crackme0x09 Dissected with Radare2

The IOLI-Crackme’s exercises have come to an end. Crackme0x09 is the last exercise of this series. Let’s start analyzing the Assembly to see what changed since the last exercise.


Getting the Crackme0x09 password through analysis

When we check the available functions, we’re able to notice that the names have changed again, as they are similar to the native functions.

afll for crackme0x09

Another detail is that there are no strings visible in the code. Although, we can see there are strings in this little program if we list them all.


So, how are they being printed???

If the code wasn’t the same as Crackme0x08, this little trick could have been more difficult to spot. We can only identify strings being printed because of the call to the printf function (the native one). Before of those calls, we always see an address being loaded to EAX register, and then passed to the printf function throughout the stack. Also, we always see a numeric value being subtracted to EBX register, which means that EBX is used as a base pointer.

At the beginning of every function we see a call to fcn.08048766 function, which changes the value of EBX. So after that call, EBX will have the base value from where will be calculated all the addresses that contains our strings.

Let me now guide you step by step so you can understand where the strings are located. Let’s start with sub.strlen_616 function.

  • sub.strlen_616

This function corresponds to sym.check, from the previous exercise.
Here we see two printf calls and the base value of EBX, after the changes at the beginning of this function occur, is 0x08049ff4.

%d string

0x08049ff4 – 0x17a2 = 0x08048852

If we check what’s in that address, using pf command, we get the following output.

pf z


As you should remember, %d is a format that will be passed to the sscanf native function. Let’s see the next string.



0x08049ff4 – 0x1791 = 0x08048863 => wtf?


  • sub.printf_55d

This function corresponds to sym.che, from the previous exercise.

Password Incorrect


0x08049ff4 – 0x17b7 = 0x0804883d => Password Incorrect!


  • sub.sscanf_589

This function corresponds to sym.parell, from the previous exercise.
The first string is already translated. It’s the %d.

Password OK!


0x08049ff4 – 0x179f = 0x08048855 => Password OK!


  • sub.strncmp_4d4

This function corresponds to sym.dummy, from the previous exercise.



0x08049ff4 – 0x17bc = 0x08048838 => LOLO

To finish this translation, let’s also do this for the strings in the main function.

  • main


0x08049ff4 – 0x178b = 0x08048869 => IOLI Crackme Level 0x09


0x08049ff4 – 0x1772 = 0x08048882 => Password:


0x08049ff4 – 0x1767 = 0x0804888d => %s

You can confirm all the addresses in the second image of this post, the one that corresponds to iz command.


And again, the solution for crackme0x09 is this set of conditions:

  • We must sum the digits of the number provided, from the left to right, until we get 0x10
  • We must set the environment variable LOL
  • The number must be even
  • The number must be less or equal than 2,147,299,998


Modifying Crackme0x09 to accept any password

Once more, I’m going to be super lazy and make the program jump right to the “Password OK!” after receiving the input. Let’s do it.

Result of Crackme0x09

That address right after the unconditional jump is the first instruction to print the “Password OK!”.

Password OK code

Time to see if that worked.

Solving Crackme0x09


Walkthrough video

2 thoughts on “Crackme0x09 Dissected with Radare2

  1. I learned a lot from this series. Thank you so much, mate. Would be awesome if you could keep making tutorials like this!

    1. Hello Luis,

      Glad to know that you enjoyed this series.
      Next week I’ll upload a much more exciting exercise, so keep tuned.

      All the best,

Leave a Reply

Your email address will not be published. Required fields are marked *