The Disobey 2020 puzzle https://disobey2020.github.io/ was really interesting, painful and well made. Like it should be. I won't do a full write up of the puzzle, because a good one is available here https://blog.dfir.fi/general/tools/2019/12/23/disobey-writeup.html
The part I enjoyed the most was the reverse engineering. The task was to find one part of the key from a binary file. I decided to use radare2 4.0.0 and QEMU with online helper tool. R2 is seen as a scary tool requiring super human abilities to use. But maybe this write up helps you to get started with it.
The file seems to be a bootloader based on the file command's output. So let's see what it does.
qemu-system-i386 -drive format=raw,file=binary.bin
Not much, but on the serial it reads "WRONG". What is wrong? Let's forward the serial to stdio.
qemu-system-i386 -drive format=raw,file=binary.bin -serial stdio
So it looks like we need to figure out what the flag is. Let's start qemu with debug settings:
qemu-system-i386 -drive format=raw,file=binary.bin -serial stdio -S -gdb tcp::1234
And connect radare:
r2 -D gdb -d gdb://localhost:1234
At this point I don't see anything I would understand. I recon there would be some unpacking about to happen.
But with some searching it looks like it would be a good idea to set a breakpoint to 0x07c00
https://stackoverflow.com/questions/51995987/bios-and-address-0x07c00
Adding a breakpoint is not that easy when dealing with a boot loader.
Luckily there is a way to add breakpoints wherever you want. Or at least on the unmapped memory. Change settings, redo break point and let it run.
Now I try the analyze everything command 'aaaa' and switch to visual mode. I step over bunch of lines and I have no clue what is going on here. So I let it run till the end with another dc command. Nothing useful.
Well, there was the instruction to set flag to 0x3000. Restart and set breakpoint there. Finally we see something sensible. At 0x3043 we see the familiar text about setting the flag. I'll add a breakpoint and let it run there. Do the analyze aaaa and then jump to visual mode with vv and finally hit space. Now we get a graph showing partly what we have to tackle.
Now we can step forward and we encounter our first check at 0x3054.
However, it is pretty hard to read what is being compared. The value of al is 42 ('B'), but no clue what the value of 0x605a:1 is. It turns out my radare required some more settings.
After doing the 'aaaa' analyzing again, the visual mode looked much better.
It is now easy to see that we should swap our 0x97 'a' to 0x42 'B' in order to avoid the jump to WRONG.
Alright, so next character should be also 0x42 'B' in order to avoid jump to fail. The following line reads 0x6665, that being characters 'e' and 'f'. The order is due to little endian byte order of x86. Then 0x32 is added to 0x65 and that should compare true to 0x7b. Well, that is false. We can deduct 0x32 from 0x7b and we get correct character 0x49 'I'. Let's replace 'e' with 'I'.
After that we still have more to go. Register ah has a value of 0x66 'f' still. But it should be 0x54 after deduction of 0x20. So 'f' should be replaced with 't' 0x74. The next ones are a bit more complicated and it might be a good idea to introduce a new tool.
Most likely this could be done in r2 as well (it has all the features, right) but I used this online tool https://carlosrafaelgn.com.br/asm86/
I carefully copy pasted the lines and with stepping through I could try out different values and sort of brute force it.
With some trying out we get 4242 'BB' to replace 'cd' in our original flag string. After this I carry on but there is the call '0x3127'. Some looping happening there, I have no clue so I add breakpoint to 0x000030d1 and let it reach that.
Almost there, I think.
There are couple more checks to pass. First the al + 1 should be 0x47. So the correct character is 0x47 - 1 = 0x46 'F'. That will replace 'g' from our flag. Then there is 'shr' instruction. I had to look it up and it does bit shifting right, in this case 8 times. In practice we have 0x68 in al registry for next comparison. Again, we replace 0x68 'h' in our flag with 0x69 'i', not with 0x47 as it would jump to fail.
The last two characters to be swapped are 0x6a69 'ij' with 0x7374 'ts'.
Finally we reach "Correct!" with flag being BBBBItFits. Our placeholder flag was longer than that but there didn't seem to be any check for the length.
It took some time to finish this task but it was a good learning experience. Even without having 100% understanding of the whole codebase, it is possible to get somewhere and solve puzzles like this. Never stop learning!
The part I enjoyed the most was the reverse engineering. The task was to find one part of the key from a binary file. I decided to use radare2 4.0.0 and QEMU with online helper tool. R2 is seen as a scary tool requiring super human abilities to use. But maybe this write up helps you to get started with it.
— r2gif memes (@r2gif) December 29, 2016
Starting up
The file seems to be a bootloader based on the file command's output. So let's see what it does.
qemu-system-i386 -drive format=raw,file=binary.bin
Not much, but on the serial it reads "WRONG". What is wrong? Let's forward the serial to stdio.
qemu-system-i386 -drive format=raw,file=binary.bin -serial stdio
Place flag to 0x3000 in RAM please :) ' WRONG
So it looks like we need to figure out what the flag is. Let's start qemu with debug settings:
qemu-system-i386 -drive format=raw,file=binary.bin -serial stdio -S -gdb tcp::1234
And connect radare:
r2 -D gdb -d gdb://localhost:1234
At this point I don't see anything I would understand. I recon there would be some unpacking about to happen.
First breakpoint
But with some searching it looks like it would be a good idea to set a breakpoint to 0x07c00
https://stackoverflow.com/questions/51995987/bios-and-address-0x07c00
Adding a breakpoint is not that easy when dealing with a boot loader.
[0x0000fff0]> db 0x07c00 Cannot place a breakpoint on 0x00007c00 unmapped memory.See e? dbg.bpinmaps
Luckily there is a way to add breakpoints wherever you want. Or at least on the unmapped memory. Change settings, redo break point and let it run.
[0x0000fff0]> e dbg.bpinmaps=0 [0x0000fff0]> db 0x07c00 [0x0000fff0]> dc hit breakpoint at: 7c00
Now I try the analyze everything command 'aaaa' and switch to visual mode. I step over bunch of lines and I have no clue what is going on here. So I let it run till the end with another dc command. Nothing useful.
Well, there was the instruction to set flag to 0x3000. Restart and set breakpoint there. Finally we see something sensible. At 0x3043 we see the familiar text about setting the flag. I'll add a breakpoint and let it run there. Do the analyze aaaa and then jump to visual mode with vv and finally hit space. Now we get a graph showing partly what we have to tackle.
Flag setting
It wasn't clear for me how to set anything in memory in r2 but eventually I found out the combination of seek 's' and write 'w' commands were going to do it. In the example I set the flag to be 'abcdefghijklm'[0x0000fff0]> e dbg.bpinmaps=0 [0x0000fff0]> db 0x3043 [0x0000fff0]> dc hit breakpoint at: 3043 [0x00003043]> s.0x3000 [0x00003000]> w abcdefghijklm [0x00003000]> s.0x3043 [0x00003043]>
Now we can step forward and we encounter our first check at 0x3054.
However, it is pretty hard to read what is being compared. The value of al is 42 ('B'), but no clue what the value of 0x605a:1 is. It turns out my radare required some more settings.
e asm.bits=32 e asm.arch=x86
After doing the 'aaaa' analyzing again, the visual mode looked much better.
It is now easy to see that we should swap our 0x97 'a' to 0x42 'B' in order to avoid the jump to WRONG.
Solving the flag starts
As seen above, we can conclude the first character should be 'B'. Let's retry. We are able to proceed a bit furtherAlright, so next character should be also 0x42 'B' in order to avoid jump to fail. The following line reads 0x6665, that being characters 'e' and 'f'. The order is due to little endian byte order of x86. Then 0x32 is added to 0x65 and that should compare true to 0x7b. Well, that is false. We can deduct 0x32 from 0x7b and we get correct character 0x49 'I'. Let's replace 'e' with 'I'.
After that we still have more to go. Register ah has a value of 0x66 'f' still. But it should be 0x54 after deduction of 0x20. So 'f' should be replaced with 't' 0x74. The next ones are a bit more complicated and it might be a good idea to introduce a new tool.
Assembly emulator
With 0x6463 'cd' we are going to do some and and xor. My tired mind doesn't compute those so I'll let the computer do it for me.Most likely this could be done in r2 as well (it has all the features, right) but I used this online tool https://carlosrafaelgn.com.br/asm86/
I carefully copy pasted the lines and with stepping through I could try out different values and sort of brute force it.
With some trying out we get 4242 'BB' to replace 'cd' in our original flag string. After this I carry on but there is the call '0x3127'. Some looping happening there, I have no clue so I add breakpoint to 0x000030d1 and let it reach that.
Finale
Almost there, I think.
There are couple more checks to pass. First the al + 1 should be 0x47. So the correct character is 0x47 - 1 = 0x46 'F'. That will replace 'g' from our flag. Then there is 'shr' instruction. I had to look it up and it does bit shifting right, in this case 8 times. In practice we have 0x68 in al registry for next comparison. Again, we replace 0x68 'h' in our flag with 0x69 'i', not with 0x47 as it would jump to fail.
The last two characters to be swapped are 0x6a69 'ij' with 0x7374 'ts'.
Finally we reach "Correct!" with flag being BBBBItFits. Our placeholder flag was longer than that but there didn't seem to be any check for the length.
It took some time to finish this task but it was a good learning experience. Even without having 100% understanding of the whole codebase, it is possible to get somewhere and solve puzzles like this. Never stop learning!
Comments
Post a Comment