Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to send arbitary bytes to STDIN of a program in gdb?

I am developing buffer overflow exercises for students. In this context you often have to provide arbitary bytes as input for programs (return addresses).

Assume this example:

#import <stdio.h>
#import <string.h>

void func() {
    char buf[4];
    gets(buf);
}

int main (int argc, char** argv) {
    func();

    return 0;
}

Normally I experiment with gdb, until I found a solution, which can then be formulated like

python -c 'print "A"*8+"\x08\x04\88\72"' | ./program

While developing more and more complex exercises, the difficulty to find a solution increases. Sometimes overwriting the return address in gdb via

 set {int}address_of_address = new_address

works, but the python-approach does not. It would be nice to debug this and to be able to enter bytes like "\x04" in gdb, while the program is running, analyzing the effects.

Is there any way to do this?

This question seems related but is answered with the python-approach: Sending arbitrary bytes to fgets from stdin

Mine goes beyond that :-/

like image 683
Michael Palm Avatar asked Jan 23 '17 19:01

Michael Palm


Video Answer


2 Answers

It would be nice to debug this and to be able to enter bytes like "\x04" in gdb, while the program is running, analyzing the effects

To do this you need 2 consoles: the first one to enter bytes in program stdin, the second one for gdb debug session.

You can first run program in 1st console until it stops waiting for bytes from stdin. Then run gdb in 2nd console and attach to a program by it's pid. You will be able to debug and enter bytes simultaneously from 2 different consoles.

like image 137
ks1322 Avatar answered Oct 21 '22 15:10

ks1322


"while the program is running" is one part of the problem. The other one is being able to set breakpoints beforehand, to "analyze the effects".

GDB's default behaviour is to run the program as a child process, thus using the same standard streams. So it is impossible to write to the child's stdin while being in GDB's CLI because, at this moment, it is being read by GDB, not your program.

The simplest solution, avoiding tty workarounds (tty command + stty setups + reading/writing to /proc/<pid>/fd/{0,1}), is to make your code testable and "callable" from GDB. You'll then be able to pass your string arguments to your functions in order to test and debug them.

For example:

#include <stdio.h>
#include <unistd.h>

void exploitme(char* str)
{
  printf(str);
}

int main()
{
  while (1)
  {
    char str[10];
    fgets(str, sizeof (str), stdin);
    exploitme(str);
  }

  return 0;
}

exploitme() is the exploit case correctly wrapped in a single entry point so that it is now possible to call it once everything it uses is correctly initialized. You can then call it using command call once main() breakpoint is reached (so that the C runtime inits, performed in main's caller, are done).

~/test $ gdb ./a.out                                                                                       
(gdb) call exploitme("hello")
You can't do that without a process to debug.
(gdb) b main
Breakpoint 1 at 0x4005ae: file helloworld.c, line 14.
(gdb) r
Starting program: /home/julio/test/a.out 

Breakpoint 1, main () at helloworld.c:14
14          fgets(str, sizeof (str), stdin);
(gdb) call exploitme("hello")
(gdb) call exploitme("hello\n")
hellohello
(gdb) call exploitme("AAAAAAAA\x08\x04\88\72\n")
AAAAAAA�:
(gdb) b exploitme 
Breakpoint 2 at 0x400592: file helloworld.c, line 6.
(gdb) call exploitme("foo")
Breakpoint 2, exploitme (str=0x602010 "foo") at helloworld.c:6
6         printf(str);
The program being debugged stopped while in a function called from GDB.
Evaluation of the expression containing the function
(exploitme) will be abandoned.
When the function is done executing, GDB will silently stop.

Note that you benefit from GDB's argument expansion which includes the C string evaluation.

The other (longer and more complex) solution, as explained, is to run your program under another tty, so that you can independently write to GDB and your program.

like image 1
Julio Guerra Avatar answered Oct 21 '22 15:10

Julio Guerra