I am currently working on fuzzing a program, and the code base is huge. To improve the performance, I am using persistent mode by creating a loop around the necessary function or code that reads from stdin. Right now using gdb, I am able to enumerate all the functions being used by the program like this:
set logging on
set confirm off
rbreak ^[^@]*$
run the binary
continue
This gives me all the functions that the program uses, but I think an easier way than reading hundreds of lines is by finding the function that reads from stdin. How would I be able to find the function that reads from stdin?
Since you're running Linux, virtually every function that reads from a stream (such as stdin) will ultimately do a read system call. (Less often, they will call readv.)
The C prototype for the read function is
ssize_t read(int fd, void *buf, size_t count);
and like most Linux system calls, this is pretty much the prototype for the actual system call (all the integer and pointer types are put into registers.)
On x86_64, the first argument to a system call will be in register rdi
. (See Calling conventions.) A value of 0 means stdin.
So first we will tell GDB to stop the process upon entering the read
system call, adding a condition to stop only when its first argument is 0:
(gdb) catch syscall read
Catchpoint 1 (syscall 'read' [0])
(gdb) condition 1 $rdi == 0
(gdb) run
Starting program: cat
Catchpoint 1 (call to syscall read), 0x00007fffff13b910 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:84
84 ../sysdeps/unix/syscall-template.S: No such file or directory.
Now do a backtrace to see all the functions in the call stack:
(gdb) bt
#0 0x00007fffff13b910 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:84
#1 0x00007fffff0d2a84 in __GI__IO_file_xsgetn (fp=0x7fffff3f98c0 <_IO_2_1_stdin_>, data=<optimized out>, n=4096)
at fileops.c:1442
#2 0x00007fffff0c7ad9 in __GI__IO_fread (buf=<optimized out>, size=1, count=4096, fp=0x7fffff3f98c0 <_IO_2_1_stdin_>)
at iofread.c:38
#3 0x00000000080007c2 in copy () at cat.c:6
#4 0x00000000080007de in main () at cat.c:12
(gdb) fr 3
#3 0x00000000080007c2 in copy () at cat.c:6
6 while ((n=fread(buf, 1, sizeof buf, stdin)) > 0)
(gdb) fr 4
#4 0x00000000080007de in main () at cat.c:12
12 copy();