-4

I'm on Ubuntu 18.04. I'm trying to do a buffer overflow attack.

Here's the C program I wrote and am trying to attack:

// test.c
#include <stdio.h>

void f();

int main(int argc, char *argv[])
{
    printf("argc : %d\n", argc);
    for(int i = 0; i < argc; i++)
    {
        printf("argv[%d] : %s\n", i, argv[i]);
    }
    printf("End of program\n");
    return 0;
}

void f()
{
    printf("You got to the hidden function!\n");
}

... compiled with:

gcc test.c -o test

Here's my Python3 injection script:

# inject.py
push = "A" * 1000
print(push)

I tried 3 methods to pipe the output of inject.py to test:

# attempt 1
$ ./test <(python3 inject.py)
argc : 2
argv[0] : ./test
argv[1] : /dev/fd/63
End of program
$ Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>
BrokenPipeError: [Errno 32] Broken pipe
^C

^ Here it actually made the 2nd $ without my input and I had to ctrl+C out after it froze

# attempt 2
$ python3 inject.py | ./test
argc : 1
argv[0] : ./test
End of program
Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>
BrokenPipeError: [Errno 32] Broken pipe
# attempt 3
$ ./test <(python3 -c "print(\"A\"*1000)")
argc : 2
argv[0] : ./test
argv[1] : /dev/fd/63
End of program
$ Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>
BrokenPipeError: [Errno 32] Broken pipe
^C

^ This one is similar to attempt 1

I believe what I'm doing is similar to the many buffer overflows I've seen on YouTube. I'd expected a SegFault but instead got Broken pipe errors.

What am I doing wrong? Why am I getting Broken pipe instead of SegFaults?

Clarification: What I'm asking for is not "How to do a buffer overflow attack?", but rather "Why am I getting the Broken pipe error and how can I fix it?". Since this is a problem with the *nix command line, I believe this is within this community's scope.

  • Why do you expect a segfault? What buffer do you think you are overflowing? Hint: normally there is a char array on the stack which provides the fixed size memory area that you overfill. The SIGPIPE is because the python is writing data to a pipe that has become closed. – icarus Nov 5 '19 at 3:24
  • I think I did something wrongly with the piping since the same error happens with push = "A"*10 instead of push = "A"*1000 – John Zhau Nov 5 '19 at 3:30
  • Your program doesn't read anything, so to a large extent it doesn't matter if you attempt to write 1 byte or a million. – icarus Nov 5 '19 at 4:37
  • Why doesn't it read? I included (int argc, char *argv[]) to make it read command line inputs. – John Zhau Nov 5 '19 at 4:44
  • 1
    I'm voting to close this question as off-topic because this group is about Unix questions, not how to use exploits. – Rui F Ribeiro Nov 5 '19 at 5:45
2

You get a "broken pipe" error in the Python program since you are not reading the data outputted by it. Your C program totally ignores its standard input stream, and the stream is closed when test terminates, leaving the Python program trying to write to a pipe that nobody is listening to.

A pipe is also used when you employ a process substitution in bash (<(...)), which is why you get the same issue there. In these examples, the data is not arriving over standard input, but from a file indicated by the command's first command line argument. You never open this file.

To fix this, make sure that the C program consumes all input from standard input, or from the pathname indicated by the command's first argument.

Your current code would not cause a buffer overrun, segmentation fault, or any other error, in your C code.

I'm assuming that you'd like to cause a buffer overrun in the C code somehow. You would do that by reading the data from the Python code into a too small buffer, for example.

By the way, the Python code does not need to be Python, it could be a simple shell command that produces a lot of data, such as the yes utility (possibly piped through head -n 500 or similar).

|improve this answer|||||
  • Can you provide an example fix? I've tried what I know but that was the result – John Zhau Nov 5 '19 at 10:32
  • @JohnZhau As I said, you have to read the data coming from the Python program. If the data is received via a pipe or redirection on standard input, just read from there, otherwise open the file in argv[1] and read from that instead. – Kusalananda Nov 5 '19 at 10:39
  • I thought python3 inject.py | ./test does just that. From what I know, python3's print outputs to stdout and int main(int argc, char *argv[]) takes its command line inputs from stdin. If that's true, the python3's stdout should be piped as stdin for ./test, but it seems that's not correct. I'm still unsure as to where my assumption is wrong. – John Zhau Nov 5 '19 at 11:50
  • @JohnZhau Well, that pipeline sends data into your C program's standard input stream. The command line arguments of the C program have nothing to do with the data sent by the Python program in this case. You are not reading the data sent by the Python code, so it blocks. When the C code terminates, the Python program fails with "broken pipe" (because the data was never read). – Kusalananda Nov 5 '19 at 11:55
  • In that case, how should I change my C code to take in the piped stdin? – John Zhau Nov 5 '19 at 12:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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