
It's been a few day since I try to learn reverse engineering again, so to put up the test for what i have been learn, I try to solve a ctf challenge
Link: https://drive.google.com/open?id=1ikHJC97UzG26nYV8Lay4zFR-5FXHJLk6
the executable is an ELF executable with 32 bit architecture. So this is just to show what we are going up to.
Now, load our executable to our radare tools, type:
~# r2 -A nix_5744af788e6cbdb29bb41e8b0e5f3cd5
for the radare2 analyse the executable for interesting function and, type:
<r2 shell> afl
for listing the function inside the executable
As we can see from the result there are two function that caught our eyes, "sym.comp_key" and "main"
ok before we deep dive to analyze the binary, for me i found three way to solve the CTF, if you are lazy just go to the end of this post to get the quickest method for obtaining the flag.
Lets go to the main function:
~# s main (switch to main function)
~# VV (to change the view of the assembly code)
note: press "p" to switch between the view and press "q" to get back to normal view
Take a look at this assembly code:
0x00001217 833e02 cmp dword [esi], 2
0x0000121a 741c je 0x1238
this two assembly code is show at the start of the program it is basically compare the esi register to value of 2 and if the value is equal it will jump (je) to address 0x1238 but if not it will go to the 0x121c and exit the program.
esi contain the length of the argument that we supply to the binary
if we type:
~# ./nix_5744af788e6cbdb29bb41e8b0e5f3cd5
it will be 1, but if we type:
~# nix_5744af788e6cbdb29bb41e8b0e5f3cd5 12345
it will be 2
after we supply the argument there are checks on the length of the input
0x00001244 e827feffff call sym.imp.strlen;[of]
0x00001249 83c410 add esp, 0x10
0x0000124c 83f80f cmp eax, 0xf
0x0000124f 761c jbe 0x126d
notice that there is cmp code again that compare eax register which is our input length with 0xf (15) and check the condition with JBE
JBE stands for Jump short if below or equal
so the limit our input is 15, if it's bigger than 15 it will exit the program
if we able to pass the two check, we will greet with a loop. Lets take a look again inside the code:
0x00001290 8b45e0 mov eax, dword [var_20h]
0x00001293 3b45dc cmp eax, dword [var_24h]
so the value of register var_20h will be move to eax and compare to register var_24h. To see what is inside these two register you need to run the application in debug mode and put breapoint at the compare code (cmp)
type:
~# ood 123456
~# db <register>
~# dc
NOTE: everytime you try to re run the executable the memory location is changed, so be careful
type "shift+s" to step into the next code inside the visual mode. to examine "var_" register type:
~# afvd
you can see that var_1ch is contain 0 and unfortunately that there is some error in interpreting var_24h and radare2 decide to store the value at arg arg_4h which is 7
so we can conclude that var_1ch is our index loop and var_24h is the limit of the loop which is 7
take a look at the assembly code:
0x56623283 0fb600 movzx eax, byte [eax]
0x56623286 0fbec0 movsx eax, al
0x56623289 0145e4 add dword [var_1ch], eax
0x5662328c 8345e001 add dword [var_20h], 1
basically the eax take one byte of its register and assigned again to itself its common when program want to access index of an array and after that the value of the array is add to var_1ch and the counter (var_20h) is incremented by 1
so we can interpet that each of the character that we input until index 7 will be add to the register.
so for example if we input:
123456
1st loop:
var_1ch += 49 (ascii for 1)
2nd loop:
var_1ch += 50 (ascii for 2)
and so on until the 7th index of our input

afte that the value inside the var_1ch will be compared with 0x321 (801) i just use python to compute the value
0x56623298 817de4210300. cmp dword [var_1ch], 0x321
now all we have to do is to compute a 7 length of char that equivalent to 0x321 (801)
2nd attempt:
actually you can get the key without input the right string by circumenventing the flow of the execution. To do this you need to put break at compare jne code and then change the eip0x56623298 817de4210300. cmp dword [var_1ch], 0x321
0x5662329f 751a jne 0x566232bb
put breakpoint and continue until you get to the memory address:
circumvent the eip to move to the sym.comp_key by assigning the eip register to sym.comp_key memory location
walaa we got it
3rd attempt (the quickest):
the actual flag is stored inside the sym.comp_key function and all you have to do is just go to the function and radare will interpret the byte.~# s sym.comp_key
Thats all folk, good day :)
Comments
Post a Comment