Solved by 4rbit3r
This was the first of a 3 part challenge that contained flags for each part.
The first part is a reversing challenge. The given files are a MIPS-32 bit executable and an emulator for the same. I had to refresh a what was left from my memory on MIPS architecture. And then a lot of googling also took place. But in the end, it was a challenge that I enjoyed doing.
Going through the code of main
function, we see that there are a lot of functions being called. Of those, a few functions are of importance to us. Namely:
- doshuffle.
- validate.
- get_first_flag.
Obviously, we need to get to the get_first_flag
function. So now let’s try and figure out what the binary actually does.
It calls opens /dev/urandom
and reads 8 bytes from it and stores it in a buffer. This buffer is then used by the doshuffle
function to create a string of lenth 16. I spent a lot of time trying to figure out what the doshuffle
function did (and eventually developed a pseudo-code). I had thought that we needed to figure out the value of the 8 byte random value from the string being printed out to us. I was too lazy to actually reverse the functionality of the doshuffle
function. So instead I patched the binary. I changed the string ‘/dev/urandom’ to a file that I created and filled with 8 ‘A’s. So now, the random value read in and the string generated by the doshuffle
function will be constant. And then, trying the input of 8 “A”‘s, we find that it’s not what we need to pass the validate function.
So after that, I moved on to the validate function. In spite of being a very large function, what it does is very simple. It multiplies a lot of constants around and finally stores a value at a particular location. Since none of our input comes into the equation, we can say that those values will be constant in every execution. So, then the validate function boils down to a simple comparison between the user input and the string printed out.
Using a debugger, we can easily set breakpoints at those locations, and identify the constraints on our input with respect to the string being printed out. Once, we’ve finished that, we can easily write a script that creates a string that can pass all the checks of the validate function.
And well, here’s the script:
from pwn import * mychars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" HOST,PORT = 'bender_safe.teaser.insomnihack.ch',31337 def findstr(chall): final_str='' final_str+=chall[0] final_str+=chall[15] if chall[7] >= 'A': a=ord(chall[7])^ord('K')^0x61^10 final_str+=str(chr(a)) elif chall[7] < 'A': a=ord(chall[7])^(0xffffffa6)^(0xffffff99)^(0x7f) final_str+=str(chr(a)) if chall[3] >= 'A': a=mychars.index(chall[3])+10 final_str+=mychars[a] elif chall[3] < 'A': a=mychars.index(chall[3])-10 final_str+=mychars[a] if chall[4] >= 'A': final_str+=mychars[mychars.index(chall[4])+10] elif chall[4] < 'A': final_str+=mychars[mychars.index(chall[4])-10] val = abs(ord(chall[1])-ord(chall[2])) final_str+=mychars[val%(len(mychars)-1)] val = abs(ord(chall[5])-ord(chall[6])) final_str+=mychars[val%(len(mychars)-1)] if chall[8]>='A': val = ord(chall[8])^0x4b^0x61^0xa final_str+=str(chr(val)) elif chall[8]<'A': val=ord(chall[8])^0xffffffa6^0xffffff99&0x7f final_str+=str(chr(val)) return final_str p=remote(HOST,PORT) p.recvuntil(':') p.recvline() msg = p.recvline().strip() retval = findstr(msg) p.sendline(retval) print p.recvall(timeout=1)
And well, running that gave the flag
Here it is : INS{Angr_is_great!_Oh_angr_is_great!_Angr_angr_angr}
Leave a Reply