Skip to content

Crackme0x04 Dissected with Radare2

All the exercises solved so far, had one thing in common: there was only one solution for the problem. Crackme0x04 does not inherit that characteristic because it has multiple solutions and has some tricks to calculate those solutions when compared to the previous crackme.


Getting the Crackme0x04 password through analysis

afll shows two functions, the main and the check. Let’s print them.

main of Crackme0x04

Well, we can see the same as in the previous exercises, the prints of all those strings and the request for input.

I put a breakpoint right after the scanf instruction, ran the program to insert 957 as input, but when I went to check the value stored in the variable local_78h, I was surprised. Instead of seeing 0x3bd in the variable I saw this.


That’s ASCII. This means that our input is being treated as a string. Not a problem!

Let’s see what’s in the check function.


Check function is not a dummy function anymore… But let me guide you through the code!

First, the length of our “string” is calculated and the value is saved in eax. Don’t forget that our input is represented by arg_8h variable.

local_ch saves the position our string, so it’s an index.

The next instruction suggests that we’re about to enter in a loop, that will only end when we reach the end of our string. But this doesn’t seem the best path to follow, because if this happens, we’ll jump to the string “Password incorrect”.

The next two instructions, makes our position in the input string move forward. The following instructions until sscanf, extract a digit (a char, actually) from the input string in the index local_ch. The sscanf seems to be converting the ASCII to hexadecimal.


As you can see, the number converted will be added to local_8h, so this variable will be a counter. And guess what? If that counter happens to hold 0xf (or 15 in decimal)… JACKPOT!!! If not, we keep converting the chars in the string that we inserted until the sum results in 0xf or the string ends.

Can you see the big picture now?

This crackme just collects our input and sum the digits in it, from left to right. If it sums to 15 at any point, you’ll get a “Password OK” message. That’s all.


Getting the Crackme0x04 password through program modification

At this point, program analysis is far more difficult than crack the program. Personally, I’m much more interested in dissect this exercises and understand how they work than crack them.

If you’re like me and want to understand what is happening on the program stack and, at the same time keep tabs in all variables and registers you will “waste” much more time when compared to program patch. Consequently, you’ll get a deeper knowledge not only in this particular program but also in assembly. That’s where I’m aiming.

Moving to program patch, if you’re lazy, you can just replace a jump instruction at the right place, making the program accept any input.

I tried save the value 0xf in local_8h between the sscanf and compare instructions but sadly I couldn’t. I think it has something to do with the instructions size but I’m still looking into it. Let me show you.

Cracking Crackme0x04

I’ve been trying to get around this for the last couple days, but I guess I need to dedicate some time to this issue. If you know the reason for this to happen, leave me a comment or email me. I’ll be very grateful!

So I moved on, and contrary to what I wanted, I used a lazy method: inserted a compare instruction and a jump to the “Password OK” string. Here’s the code.

Simple. Let’s test it.



How did you crack this one? Let me know!!!

Walkthrough video

Published inRadare2


  1. noob noob

    You will need to also insert a NOP instruction in your “mov dword [epb-0x8],0xf” patch or else you are not aligning up with the “cmp dword ..” instruction.

    This should do the work:
    >s 0x080484ce
    >”wa mov dword[ebp-0x8],0xf ; nop”

    • moveax moveax

      Hello noob,

      You’re right! I tested it and it worked.
      Thank you for the help.

      Best regards,

  2. nizscusa nizscusa

    I discovered your blog website on google and test a couple of of your early posts. Continue to keep up the superb operate. I simply additional up your RSS feed to my MSN News Reader. Seeking ahead to studying more from you later on!


      Hi nizscusa,

      Happy to know you’re enjoying 🙂

      All the best,

  3. vlo vlo

    Hello, I find what you are doing very interesting, I’ve started learning reversing few time ago, so apologize me if what I ask is not correct.

    How can you know that that the value returned by sscanf is stored in local_4h. (I think here is where it is stored, correct me if I’m wrong). Why is not in eax instead?


      Hello vlo,

      I’m going to give you two answers: the lazy and the hard-working one.

      Lazy: the local_4h variable changed it’s value only after the sscanf returned and the value of eax will be lost in two instructions. So, it’s likely that local_4h variable holds the value converted. You can check this, by putting a breakpoint before the sscanf and watch the values it gets before and after the call to this function.

      Hard-working: deep down in the sscanf function you can see this set of instructions. As a password, I wrote 957 and the address of local_4h was 0xbfec1144. In the image you can see the value of eax (0x9) being moved to 0xbfec1144 address, saved in edx.

      Hope this helps,

  4. jaehyun jaehyun

    i just did it the cheap way *shrug*

    wx 90 @ 0x080484da
    wx 90 @ 0x080484db

    instead of the jae that was at 0x080484da, it now nop slides (awfully short ‘slide’) into the PASSWORD OK string and prints it.


      Hello Jaehyun,

      Nice, but it’s still the lazy method xD
      Keep up the good work!!!

      All the best,

  5. find this find this

    I just want to tell you that I am all new to weblog and truly liked this web blog. Most likely I’m want to bookmark your website . You actually have incredible articles and reviews. Thanks for sharing your blog.



      I’m very glad to know that you’re enjoying!!!

      Happy Reversing,

  6. programmersn programmersn

    Thanx so much bro for all the tips and advices.
    You’ve made mastering r2 so much easier !
    All the best and keep up with that


      Hi programmersn,

      In the next month or so, I’ll start another series of exercises, using Radare2.
      Thanks for your support.

      Keep tuned!

      • programmersn programmersn

        Cool ! Looking forward for that !!
        Regarding the issue you encountered when you tried to insert the move instruction before the cmp to 0xf, I think I’ve figured it out. Here is the corresponding chunk of code :
        0x080484c9 e8d6feffff call sym.imp.sscanf
        0x080484ce 8b55fc mov edx, dword [local_4h]
        0x080484d1 8d45f8 lea eax, dword [local_8h]
        0x080484d4 0110 add dword [eax], edx
        0x080484d6 837df80f cmp dword [local_8h], 0xf

        Actually mov instruction in x86 takes 7 bytes and this program it begins at the offset 0xce, thus expanding all the way to the offset 0xd5 while the cmp begins at the offset 0xd6.
        What I think actually happens, is that as the disassembler begins interpreting the following instructions from the offset 0xd5 which is just garbage leftover from the previous overwritten opcodes, it then jeopardizes the whole interpretation of the subsequent instructions (including the cmp instruction).
        Now if you insert a nop opcode at the offset 0xd5, everything goes smoothly and the cmp instruction is well interpreted and retrieved by the disassembler.

        Notice that instead of simply typing in the interactive assembler the mov instruction as you did, you might instead insert it with the nop opcode alltogether, like this:
        mov dword [ebp – 0x8], 0xf; nop

        This way it should work.
        Please tell me if this solution works for you


          Hi again programmersn,

          In the first comment, noob gave me this solution, but you went a step forward and explained everything. Thank you for that.
          By now, I read some things about instructions alignment on x86 and I’m more comfortable with changing to the assembly.
          Answering to your question, yes, this solution works!

          I appreciate your contribution,

Leave a Reply

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