BackdoorCTF 2016 - enter the matrix

BackdoorCTF is the annual flagship CTF competition conducted by SDSLabs and InfoSecIITR.

Points: 350

Description:

Can you reach Zion and find the flag? You can download a copy of the Matrix to play with here, but the flag can only be found on Zion, through the real Matrix at nc hack.bckdr.in 9004

Write-up

For this one I went a long way around to finally get the solution. Since this is my first writeup with pwning, I’ll be writing about the whole journey around the binary so if you want to just quickly see the solution, jump here

So they gave a 32-bit ELF non-stripped executable. I opened it up in IDA and saw a function named zion. According to the description this is where we have to reach to get the flag. This function was making some _system call which is what I had to finally exploit. I decided to go into its details later and rather focus on reaching there first.

1. Red Pill - It asked for a name. I filled some random string. The binary said it was expecting “Neo” and exited. Then I tried with the name “Neo”. It said “See you on the other side, Neo… Knock knock.” and exited. I wonder what other side it’s talking about :P

2. Blue Pill - Learning from before I tried with the name “Neo”. Ah so we got something here. Something related to Matrices as I wanted. I tried random matrix sizes and inputs and landed no-where. It just gave back AxB for the two matrices. Ofcourse that meant I need to look at the disassembly.

But first I decided to try the Exit option as well just to be sure. It had nothing worthwhile.

So now I looked at the disassembly.

Here ds:choice is where our inital choice is stored which was 2(Blue pill) in this case. So we see that it calls the function with function name at certain offsets to ds:dispatcher. I saw the data section to see what was being called for which choice.

So following is the relation between choice and function call.

0 - zion()
1 - red_pill()
2 - blue_pill()
3 - exit_out()

On seeing this I though what if I just call zion by entering choice as 0. But they had checks on the value of the choice(1-3).

So I proceeded to the disassembly of blue_pill(). It had lots and lots of assembly. But I decided to go through it to reach zion. I saw this line “So, you found the hidden multiplier. Good for you.” and decided thats where I must reach. I went through a lot of assembly trying to understand the control flow. Finally I deciphered that a lot of assembly corresponded to loops for taking all the inputs terms for each Matrix and then multiplying them together.

The above shows the code where the matrix size is being compared to the number 7 and I also saw that this size was necessary to reach zion. I tried running the binary with size = 7 but nothing. I expected there to be some check on values entered in the two matrix or the terms of AxB. So what I was that they had a variable set to the value 49. This value was decremented once in for each term of AxB if it matched a certain value stored in the data section. In the end if the value of this variable was 0, it went into zion.

Variable set to 0x31 = 49

moveax,expected_mult[eax*4]# Moved the value at a certian position in the array `expected_mult` to `eax`cmpecx,eax# Compare it to `ecx` which was actually storing the multiplied value after all calculationssetzal# Sets the `al` register to 1 if the zero register is set to zero i.e. if eax == ecx in prev. stepmovzxeax,al# Copy that to eaxsub[ebp+var_12D8],eax# This is where 1 is being subtracted.add[ebp+var_12D0],1# This is just loop variable updation.

So I checked all the required values from the data section; converted them to decimal; made it into one of the Matrices and kept the other as an Identity matrix. So I finally had the input file ready:

So, you found the hidden multiplier. Good for you.
I shall now prepare a spaceship to Zion, Neo

Woot! I was so happy at having completed this challenge. Now all the was left was send the same thing to the binary running on the server.

cat input | nc hack.bckdr.in 9004

I got back the same resonse as above but no flag. This was bad. After all this work! I remembered that I hadn’t actually looked at what zion() was actually doing.

The actual Solution

From zion()

So all zion was doing was to execute the following command printf '[name]'. The name in our case was ‘Neo’. There is no chance we can get a flag with that. I tried different combinations like Neo\0;cat flag etc. I was expecting the string comparison to stop at \0. Nothing like that happened so I was unable to get into zion without keeping the name ‘Neo’.

Probably this wasn’t the right path afterall. I check at what all places zion function was being called. There was this other option which we had rejected earlier - setting the choice to 0. There was a posibility that I maybe able to overwrite the choice while entering the name. I checked how they were being stored.

So the name could have 64 characters an just after that in the memory our choice was being stores.

So I tried to overwrite it:

python -c"print '2\n' + 'a'*64 + '\000'" | ./matrix

And voila! It did enter zion. So now I used the appropriate string so as to print the flag. This was a bit tricky. But this is what I finally used.