0

I am trying to learn GDB to better understand buffer overflows but I can't find an answer to my problem which is how can I send a Python-generated output to the program when the program asks for user input (the gets function in my code below). I can type CTRL+C to send SIGINT but I have not found any way to send the output back to the program.

Sample program (disregard the buffer overflow):

#include 
int main(int argc, char **argv)
{
char buf[8];
gets(buf);
printf("%s\n", buf);
return 0;
}

Sample Python script I want to do:

python -c "print 'A' * 10"

The Python output I want the gets function to read:

AAAAAAAAAA
0

You can specify the input you want to pass to the program when executing "run" via GDB:

(gdb) r <<< $(python -c "print 'A' * 10")

Example:

(gdb) r <<< $(python -c "print 'A' * 10")
Starting program: /media/sf_CTFs/stackoverflow/24610/test <<< $(python -c "print 'A' * 10")
AAAAAAAAAA
[Inferior 1 (process 953) exited normally]
(gdb)

[Edit, based on comment]

If you want to be able to interactively decide what the next input you want to send is, without scripting the whole thing beforehand (and assuming that you can't or don't want to use a library such as pwntools to automate the decision process), you might be able to make use of named pipes. However I can't promise that this is the best or most convenient way. At the very least, this method is OS dependent.

First, create a named pipe:

root@kali:~# mkfifo my_pipe

Then, open two shells.

On one shell, redirect GDB's input as the pipe's output:

root@kali:/media/sf_CTFs/stackoverflow/24610# gdb -nh test < ~/my_pipe

On the other shell, open a Python REPL and connect to the named pipe:

>>> f = open("/root/my_pipe", "w")

The moment you open the pipe, you should see GDB get unblocked on the first shell:

Reading symbols from test...
(No debugging symbols found in test)
(gdb)

Now, define the following function in the Python REPL:

>>> def cmd(f, s): f.write(s); f.write("\n"); f.flush()
...

You should be able to enter input for GDB using the newly defined cmd command. For example, to run the program, enter:

>>> cmd(f, "r")

This will run the program in the other shell:

(gdb) Starting program: /media/sf_CTFs/stackoverflow/24610/test
Please enter input

You can break GDB with CTRL+C, just remember that all commands need to be entered via cmd.

When the time is right, you can send your Python command:

>>> cmd(f, 'A' * 10)

It will be received in the other side:

(gdb) Continuing.
AAAAAAAAAA
[Inferior 1 (process 1187) exited normally]

Don't forget to close the named pipe when you're done:

>>> f.close()

If this works for you, you can go ahead and create a Python script that acts as an interactive shell, instead of using the REPL.

| improve this answer | |
  • For this to work, if the program requested more inputs, I would have to script all inputs that are sent from STDIN. Is it possible to do this if I interrupt the program manually and then want to perform another redirection from STDIN? – Tomik Apr 4 at 15:17
  • Edited my answer with a suggestion (if I've understood your intention correctly). There might be a straightforward way to achieve the same thing which I'm not aware of. – Dvd848 Apr 4 at 19:08
  • This is exactly what I needed, thank you. I tried it and it works. It is not as convenient and straight-forward as I hoped, but it gets the job done. – Tomik Apr 5 at 10:17

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.