0

Is there a way to edit argv during runtime using gdb?

I want to get the pid of a c program and pass it as an argument (argv).

For example :

gdb cProgram
(gdb) b *0x000000000040085b
(gdb) r anyway
(gdb) info inferior
  >Num  Description          Executable
  >* 1    process 2597503    /path/to/file

(gdb) #A command to pass 2597503 as argument (argv)
(gdb) c

Thanks :)

Drahoxx
  • 3
  • 1
  • Do you specifically want to have the process see the string value of its pid as its first argument? If so, you can just do `run $$` (on systems that use a shell to run the target program). – Mark Plotnick Dec 13 '21 at 01:53

1 Answers1

2

Yes, it appears to be possible, however, I don't know the implications of doing such a thing, someone else will need to chime in on that. If argv strings are string literals, then modifying them is undefined behavior. Furthermore, if you write past the length of the original string, that probably invokes UB as well. Nevertheless, I found this answer which details how to modify an int, and adapted it to a string. Consider the following program:

#include <stdio.h>

int main(int argc, char* argv[])
{
  for (int i=1; i<argc; i++)
  {
    printf("%s\n", argv[i]);
  }

  return 0;
}

Compiling with

gcc -Wall -Wextra -g -O0 -std=c99 test.c

And then running with gdb:

gdb a.out
// gdb's intro
(gdb) break main
Breakpoint 1 at ...
(gdb) run arg1 arg2 arg3  // pass it 3 arguments
// breakpoint hit at main
(gdb) print argv[1]
$1 = <address> "arg1"
(gdb) set {char*}(&(argv[1])) = "new4"  // change the value of argv[1]
(gdb) print argv[1]
$2 = <differentAddress> "new4"
(gdb) delete 1 // deletes the break point
(gdb) continue
Continuing.
new4
arg2
arg3
[... exited normally]
(gdb)

So there you have it. Whether this is actually safe or not is a different story, but that changed the value of argv[1] for me. I would at least make sure the original string is the same length or longer than the string you want to replace it with.

yano
  • 4,827
  • 2
  • 23
  • 35
  • 1
    Strings pointed to by `argv` are _not_ string literals. They are injected into the address space of the app by the kernel (starting at top of memory and working downwards) before the program is invoked. Likewise for environment variables. The kernel starts up the C wrapper with a call `start(argc,argv,envp)`. Most C wrappers will pass along `envp` to `main` with `main(argc,argv,envp)` even if the spec says no. Both the pointers within `argv` and the strings they point to are _modifiable_ – Craig Estey Dec 12 '21 at 18:39
  • @CraigEstey Thanks a lot for the info, I'll work that into the answer if you don't write your own. – yano Dec 12 '21 at 18:43