First, let’s take a look at the main menu of this Dr Von Noizeman’s nuclear bomb.
Yellow phase, it’s probably the easiest one in this binary bomb. It starts by asking you for a password that will be stored in obj.buffer. Looking at the code, you can see every char of your password being compared to a fixed value. The multiple movzx eax, byte [0x804c2XX] ensure that al has every char in your password. If a single char doesn’t match… KABOOM!
If you group all the values being compared, you’ll have the final password: 84371065.
So, this turned out to be a fairly simple phase. Notice that when you return to the main menu, the option “YELLOW” it’s gray and the yellow stripe is almost missing, which means we have defused this phase. Let’s move on.
This phase probably looks simple to you, because you can see a comparison between a string and your input, and if you try that string present in the code, the program will actually accept it. But if you take a closer look, the green phase option didn’t get gray, which means you still need to defuse this phase! Let’s take it slow…
In preflight function, notice that fgets will read up to 20 chars. After this preflight, you can also see that strncmp will only compare 8 chars, which means that you can pass more chars than those that will be compared. Now, the comparison between your input and “dcaotdae” string takes place. If you already tried this string you will see that it will be accepted. But notice that you didn’t defuse this phase (option 2 is still available and the green bar is still there). Why?
This is the section of code that will show the phase as defused. We need to rebuild the steps that made possible to get here!
Right above this piece of code, we can see that local_8h needs to be 0 in order to get here. This variable is manipulated at 0x08049989, 0x08049960 and 0x08049915 (this is where its initial value is set). In 0x08049989, local_8h needs to be 0, so at 0x0804997b it needs to be 1. Check the image below to understand why.
In 0x08049960, local_8h needs to be 1, then at 0x08049952 it needs to be 0. See the problem? At this point, local_8h will always be 1 because that’s the value stored at 0x08049915. So, what now??? From this point forward, it’s better if you’re familiarized with buffer overflow vulnerabilities, but you should be able to keep following even if you’re not.
Buffer overflow time!
Take your time to test different inputs and most importantly, how and where they are stored.
Pay attention to the image above. Your input is saved in local_14h and right above (in the stack) there is local_8h. I hope you also noticed that your input is always followed by “0a00” in memory. In the above example, I printed 32 bytes starting in 0xbfcd8a40 so we can understand better what’s going on.
Now, 0xbfcd8a50 holds the content of local_8h, 0 or 1. You still remember that we can input 20 chars, right? Do you think if we give it 3 more chars, “00” will be at 0xbfcd8a50??? Let’s check.
Remember, the program will still test”dcaotdae”. Now, local_8h has the value 0 and we have defused the phase if you test it. Binary bomb status: 2 phases done, 2 more to go!
Blue phase requires more attention than the previous phases of the binary bomb. After preflight call, we see an obj.graph which contains an address and right above the location of this obj.graph is a value, which you can see being moved to eax register.
obj.buffer has your input. In the following instructions, we see the validation of our input, checking if they’re either “L”, “R” or even “\n”. So your input must be a set of these chars.
The next set of instructions can be a little confusing, but I’ll break it down for you shortly, but before let me make a quick aside note. Because I’m a visual guy, I mean, it’s easier for me drawing and write things down so I can be able to understand them better, I mapped the memory between 0x0804c214 an 0x0804c1c0. Let me show you.
Are you able to see the pattern here, right? The white spaces have values stored. obj.graph is the name of 0x0804c160 address. Now, it’s time to talk about the algorithm. The first part of the algorithm is different for “L” and “R”, but the second one is the same.
If we got an “L”, we’ll extract the value stored in local_4h which is an address. In that address, is stored another address that we are also going to extract and copy to local_4h. You can confirm this with the picture above, but let me give you an example.
Imagine that your input starts with an “L”. In the beginning, local_4h will hold 0x0804c160 which is the first address in the above picture. That address points to 0x0804c19c which will be the new value of local_4h.
If it’s an “R”, we also extract the value in local_4h. Then, we add 8 bytes to that same address and let it in local_4h again. Let’s confirm it also with an example.
Consider that our input starts with an “R”. Again, local_4h contains 0x0804c160. Now, instead of extracting the value stored at this address, we’re going to extract the value stored 8 bytes above, so eax will hold 0x0804c178 and this is the new value of local_4h.
In the second part of this algorithm, you add 4 bytes to the address stored in local_4h and extract the value stored in the address obtained. Now, you take that value and XOR it with the hold stored in local_8h, and put the result back in local_8h again.
After you do this process for the entire path and if the value stored in local_8h matches the one in obj.solution, then you have defused the phase. One possible solution is LLRR but there are tons of solutions.
This is the last phase of the binary bomb, but isn’t a hard phase even if it require some work to figure out the solution. At the beginning of this phase, the program shows 3 values. Let’s call them A, B and C.
So first, you take C and execute an AND with 0x1F, which means that in the last five bits of C, we want all of those that are set. That will give you the index of the string in local_4h which will be compared to the current index of your input.
After this, you perform all the calculations for the next iteration. Let’s go through those calculations.
Now, you take C and shift it right by 5, which will result in a value that we’re calling C1. Then, you take B and shift it left by 1B (27 bits), which will result in B1. Now, you perform an OR between C1 and B1 and you get the new C value.
After this, take B again and shift it right by 5, and call B2 to the result. Take A and shift it left 1B (again, 27 bits), and call A1 to the result. Now, you take B2 and A1 and perform an OR between them both and you’ll get the new B value.
In order to get the new value of A, you just shift it right by 5.
This is the process to get the solution, which is recalculated in every iteration. To get the solution, you can pass some random 19 chars and just before cmp instruction at 0x08049864 you can match dl and al, using the dr command to change dl value. This is just an example. Another option, is to write a short script in your favorite programming language in order to obtain the solution. In both cases you’ll get KDG3DU32D38EVVXJM64.
The end of the binary bomb…
At the end of all these phases, you have disarmed the binary bomb.
Did you find this binary bomb difficult? Easier than last one?