Input redirection from file gdb - c

I can't get gdb to redirect a file to the stdin of my program.
Outside of gdb ./prog.x < someinput.txt does exactly what I want.
Inside gdb, when I run (gdb) run < someinput.txt my program doesn't seem to "see" the input file, and instead stdin seems to be reading what I type into the console.
(gdb) run < testinput.txt
Starting program: /Users/alexpatch/Documents/krc/misc/sandbox.x < testinput.txt
[New Thread 0x1603 of process 8308]
My cursor appears on a blank line beneath that, where I can type some text. C-d breaks out of that, then the output of the program run with what I just typed appears, and the process exits normally.
/* trivial code example */
#include <stdio.h>
int main(void)
{
int c;
while ((c = getchar()) != EOF)
putchar(c);
return 0;
}
I found a few answers related to similar issues, but the solution that seemed to work for them was what I'm already doing, namely (gdb) run < someinput.txt. In case it's helpful, I'm working on a 64bit MacBook Air running macOS Sierra.

Related

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 :-/
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.

Why I can't reach stdin at startup on Raspberry-Pi Jessie Lite?

I have this code. what I want to do is to wait for user to press 'q' to end the program.
.
...starting few threads, which use fflush(stdout) (just saying...)
.
char n = 0;
while (n != 'q') {
n = getchar(); //tried to use scanf() here as well
printf("%c", n);
}
...killing all threads...
return 0;
When I run this in a normal Linux enviroment it works fine.
The problem starts when I run this program at startup on my raspberry-pi with debian jessie lite distribution (I added the path to the program to /etc/rc.local) - it ends in an infinite loop, scanf is still returning -1 and getchar() some weird character and the program won't end, when I press q. Ctrl+C doesn't work either so there is no way, how to end the program.
Any suggestions? (at least how to kill the program...?)
Edit: To let you know what the program does.
Raspberry-pi with this program is attached to some serial ports and converts and transfers some GPS data. It should work "out of the box" without any keyboard or mouse or monitor. = Just plug the device to some cables and do nothing more. In some cases someone would like to see log files on the raspberry, so he needs to stop the program, obviously.
Edit2: when I did the same with some normal Raspbian, it worked fine too.
Update:
I tried to debug it - shrinked the code to this only
int main(void){
char n=0;
int x;
while (n != 'q'){
clearerr(stdin);
x=scanf("%c",&n);
printf("%c %d\n",n,x);
}
return 0;
}
added service start udev to rc.local and tried command update.rc.d udev enable
output on raspberry-pi when launched at startup is still
-1
-1
-1
.
.
so there definitely have to be something wrong with stdin.
After startup and on other systems, the output is obviously q 1 (when I press 'q' (and enter) ...)
when I tried to read from /dev/tty, fopen() returned NULL
Really need a help with this
The idiomatic way to write this loop is:
int c;
while ((c = getchar()) != EOF && c != 'q'){
putchar(c);
}
Your implementation cannot detect end of file and will loop forever, printing funny characters such as ÿ.
Just a wild guess that stdin maybe redirected to something else and you need to read from keyboard directly. try the following code:
FILE *tty = fopen("/dev/tty", "r");
if (!tty) {
exit(1);
}
int n=0;
while (n != 'q'){
n=fgetc(tty); //tried to use scanf() here as well
printf("%c",(char)n);
}

how to use a GDB input file for multiple input

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

Segmentation fault in fscanf() function

I am writing some code for a C wordsearch program and, while compiling one of the files, i get segmentation fault on fscanf function but i don't know where the error is.
I already searched for the answer and i understood that on integer variables I must initialize the value of them (and I already done it) and that i must refer the types inside fscanf() with '&' (done it too).
Here is the code( in the main() function):
int i;
int nl = 0;
int nc = 0;
int a, b, d;
char mat[1000][1000];//character matrix for wordsearch letters
int x[1000], y[1000];
int l, c, n;
printf("Chose the wordsearch you want to use.\n For example: t01.in, t02.in, t03.in, t04.in, (...),t30.in\n");
char wordsearch_file[8];
fgets(wordsearch_file,8,stdin);//user enters f.e. 't01.in'
FILE *stream;
char buffer[1024];
sprintf(buffer, "home/adminuser/Desktop/LA/ETAPA2/sopas/%s", wordsearch_file);
stream = fopen(buffer,"r");
if((fscanf (stream,"%d%d", &nl, &nc)) > 0){ // SEG. FAULT happens here
for(l = 0; l < nl; l++) {
for(c = 0; c < nc; c++)
mat[l][c] = fgetc(stream) != EOF;
fgetc(stream);
}
}
I wanted 'nl' (number of lines) to read 3 and 'nc' (number os columns) to read the other 3.
The 't01.in' file:
3 3
SIA
ORR
EDI
Anytime you open an external resource (file, database, socket), or make any system call whatsoever, you always check for a valid stream or return code.
The first thing you should do is add a check for stream instead of blindly calling fscanf(stream,...) without knowing if the fopen() call succeeded.
Then decide why fopen() failed. I suggest printing out the filenamne, or checking that it exists, and/or using perror() to print the system error. perror() will tell you exactly what is wrong, and if I had to guess, it would be as #BLUEPIXY mentioned, a newline in the filename.
stream = fopen(buffer,"r");
if(!stream) {
perror("what the problem: ");
}
Lastly, learn how to use the debugger to analyze the core file. If you aren't getting a core dump, set your ulimit correctly. From memory, you want "ulimit -c unlimited". Find out your current ulimits by typing simply "ulimit" at the shell prompt. Then re-run your crashing program. Once you get a core file, run GNU debugger on it.
gdb program.exe core

Setting up Eclipse to call my program with the following argument " < fileName.txt"

I am developing a application that reads from the stdin and does some computations on the data. I have currently set on Eclipse's Program's Arguments the following string:
< "input.txt"
where input.txt is the file I want to read from, but it doesn't seem to be working, as with the following code only "abc" is being printed:
char c;
printf("abc\n");
while ((c = getchar()) != EOF) {
printf("%c", c);
}
What am I doing wrong?
The < symbol is not a program argument, its a shell operator - it only works in a shell that understands it as part of parsing a command line.
Apparently, Eclipse doesn't use a shell to start up a Java programs and it doesn't itself process shell operators like < for starting up. I'll bet if you printed the command arguments in your program, you'd see < and input.txt. A shell would have processed them and not passed them to the program.
Unfortunately, I don't see anything in my version of Eclipse that suggests how to redirect the standard input to come from a file.

Resources