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 :-/
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.
"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.
Related
I have a C program that writes a NOP character to stdout:
#include <stdio.h>
int main(char *argc, char *argv[]) {
fwrite("\x90", 1, sizeof(char), stdout);
return 0;
}
I also have another program that takes input, which i am runnning in gdb (so i can view the stack).
After running the first program i copy the NOP from stdout and paste it in GDB as input for the second program.
When viewing the stack i always get this value:
0x00bdbfef
When it should be
0x00000090
Why is this? The problem also seems to occur with python but i cannot pinpoint why.
The utf-8 sequence ef bf bd (keeping in mind the byte reversal of larger data types in some architectures) is the replacement-character code point, the diamond with a question mark within.
Most likely your terminal is unable to render 90 so it gives you that instead. And, when you mark and copy that character elsewhere, that's what it is.
I am reading The shellcoder's Handbook and im currently at chapter 2 where i have a simple program to exploit by overflowing the expected input and then issuing a new location for the ret instruction so that the function return_input can be executed twice !
Here is the simple program made in C
void return_input (void)
{
char array[30];
gets (array);
printf(“%s\n”, array);
}
main()
{
return_input();
return 0;
}
And this is the disassembled version of the main fucntion where we can see the jump adress of the call function.
I use the following command and input the chars that overflow with the adress following them that should replace ret's content
But as you can see i do not run the return_input function twice instead it just prints out a question mark and says segmentation failed
gets read terminating byte in and replaced it with NULL byte and thus your desired ret was broken with that NULL byte.
The offset you saw in disassembly codes is NOT the real address, you compiled the program with PIE flag set so the real address may look like 0x55555????58a, that's why gdb didn't allow you to insert a break point because you might try to do b *0x58a or something. Compile with -no-pie would make life easier.
EDIT: GDB was not the issue. Bugs in my code created the behaviour.
I am wondering how GDB's input works.
For example I created the following small c program:
#include <stdlib.h>
#include <stdio.h>
int main(){
setbuf(stdout,NULL);
printf("first:\n");
char *inp;
size_t k = 0;
getline(&inp, &k, stdin);
printf("%s",inp);
free(inp);
// read buffer overflow
printf("second:\n");
char buf[0x101];
read(fileno(stdin),buf,0x100);
printf("%s",buf);
printf("finished\n");
}
It reads two times a string from stdin and prints the echo of it.
To automate this reading I created following python code:
python3 -c 'import sys,time; l1 = b"aaaa\n"; l2 = b"bbbb\n"; sys.stdout.buffer.write(l1); sys.stdout.buffer.flush(); time.sleep(1); sys.stdout.buffer.write(l2); sys.stdout.buffer.flush();'
Running the c programm works fine. Running the c program with the python input runs fine, too:
python-snippet-above | ./c-program
Running gdb without an input file, typing the strings when requested, seems also fine.
But when it comes to using an inputfile in gdb, I am afraid I am using the debugger wrongly.
Through tutorials and stackoverflow posts I know that gdb can take input via file.
So I tried:
& python-snippet > in
& gdb ./c-program
run < in
I expected that gdb would use for the first read the first line of the file in and for the second read the second line of in.
in looks like (due to the python code):
aaaa
bbbb
But instead gdb prints:
(gdb) r < in
Starting program: /home/user/tmp/stackoverflow/test < in
first:
aaaa
second:
finished
[Inferior 1 (process 24635) exited with code 011]
Observing the variable buf after read(fileno(stdin),buf,0x100) shows me:
(gdb) print buf
$1 = 0x0
So i assume that my second input (bbbb) gets lost. How can I use multiple input inside gdb?
Thanks for reading :)
I am wondering how GDB's input works.
Your problem doesn't appear to have anything to with GDB, and everything to do with bugs in your program itself.
First, if you run the program outside of GDB in the same way, namely:
./a.out < in
you should see the same behavior that you see in GDB. Here is what I see:
./a.out < in
first:
aaaa
second:
p ��finished
So what are the bugs?
The first one: from "man getline"
getline() reads an entire line from stream, storing the address
of the buffer containing the text into *lineptr.
If *lineptr is NULL, then getline() will allocate a buffer
for storing the line, which should be freed by the user program.
You did not set inp to NULL, nor to an allocated buffer. If inp didn't happen to be NULL, you would have gotten heap corruption.
Second bug: you don't check return value from read. If you did, you'd discover that it returns 0, and therefore your printf("%s",buf); prints uninitialized values (which are visible in my terminal as ��).
Third bug: you are expecting read to return the second line. But you used getline on stdin before, and when reading from a file, stdin will use full buffering. Since your input is small, the first getline tries to read BUFSIZ worth of data, and reads (buffers) all of it. A subsequent read (naturally) returns 0 since you've already reached end of file.
You have setbuf(stdout,NULL);. Did you mean to disable buffering on stdin instead?
Fourth bug: read does not NUL-terminate the string, you have to do that yourself, before you can call printf("%s", ...) on it.
With the bugs corrected, I get expected:
first:
aaaa
second:
bbbb
finished
Can we give input string by it's hex value in gdb. For example, a simple program
#include <stdio.h>
int main() {
char buffer[20];
fscanf(stdin, "%s", buffer);
printf("%s", buffer);
}
Debugging it:
ravi#ravi-desktop:~$ gdb -q ./a.out
Reading symbols from /home/ravi/a.out...done.
(gdb) list 1
1 #include <stdio.h>
2
3 int main() {
4 char buffer[20];
5 fscanf(stdin, "%s", buffer);
6 printf("%s", buffer);
7 }
(gdb) r
Starting program: /home/ravi/a.out
\x41\x41\x41\x41
\x41\x41\x41\x41
Program exited with code 014.
(gdb) quit
I want to input four A's as input using hex value \x41 but it's considering each character separately.
The real requirement is I'm playing with Shellcode in Stack-based Buffer Overflow, and I need to input shellcode in hex at a time of debugging.
Can anybody help me here.
Thank you
Ravi
you can simply read from a socket instead of stdin, which makes it quite easy to set breakpoints in gdb and look what is happening in detail in one shell and inject code in another shell!
that is just an example how you could inject hex into a socket:
echo -e "`perl -e 'print "\x14\xee\xff\xbf"x10 . "\x90"x10'`" | nc 127.0.0.1 1337
--> printing memory addresses and NOPs with perl and pipe it into nc to localhost(or a remote system) on port 1337 in this case.
That is solving your problem i assume!
if you need assistance to communicate via socket i am sure you will find answers on stackoverflow as well!
You seem to be expecting gdb to have this functionality, that it should interpret C-style escapes in the input so that the debugged program gets an 'A' when you type \x41.
Unfortunately that's just not how it works; gdb doesn't sit between the debugged program and the terminal. And terminals don't support that functionality, so it just won't work.
I'm writing a program to implement Dinic's max-flow algorithm over a network. The networks can be written either by hand or loaded from a file using stdin redirection.
I've been able to use gdb to debug the program with small files (around 30 lines), but I'm having trouble when I try to debug the program with bigger files (>1000 lines). The code itself is this:
uint32_t read_lines = 0;
while(!feof(stdin))
{
err = fscanf(stdin, "%u %u %u\n", &n1, &n2, &c);
if (err != 3)
{
printf("read_lines=%u\n", read_lines); /*for debugging purposes*/
}
read_lines += 1;
/* write to debug file */
fprintf(debug, "line %u: %u %u %u\n", read_lines, n1, n2, c);
}
If I run the program without gdb, it runs, not ok as it generates a segmentation fault (which is the reason I'm trying to use gdb), but it goes through this part of "parsing" the input file (and writing it into the output debugging file).
However, if I type:
gdb --args ./dinic --mode=NUM --verbose=LOW
(gdb) b 61
(gdb) run < tests/numterc.in
I get:
(gdb) Program exited with 01 code.
and when I open the debugging file it's about 2000 lines, when it should be at most 1000, which is the input file length.
I repeat, this happens with "big" files, it works correct with small ones.
The question would be, am I missing something when using gdb, or is this a gdb bug?
Ok, I could finally get a work-around. It seems that the --args option ain't working well, at least in my case. I have gdb 6.8-debian and debian 5.0.4.
What I had to do was run gdb without the --args option:
$gdb ./dinic
(gdb) b 61
(gdb) run --mode=NUM --verbose=LOW < tests/numterc.in
and it worked well. Maybe someone can find this useful.
I had the same problem and came up with the same solution to specify args in run. The option --args only can pass arguments, but but cannot do redirection of stdin which is usually (in non-debug context) redirected for you by the shell invoking the command. In the debug session your command is invoked by gdb where both argument list and redirections are specified by the value of the args variable. By using the --args option you initialize this variable (and the program file to debug as well). Just do
(gdb) show args
and this should be initialized to --mode=NUM --verbose=LOW in your case. But no redirection, so you specify them with run, which overrides args! So you have two options:
Specify also the redirection in args:
(gdb) set args --mode=NUM --verbose=LOW < tests/numterc.in
Specify also the redirection when invoking run