TransWikia.com

Is it possible to find a running process's arguments to main from an attached GDB?

Reverse Engineering Asked on December 1, 2020

Given a very basic program,

perl -e'$|=1; print $$; sleep 500;' HELLO WORLD

How can I find HELLO WORLD using GDB? I thought bt -full but when I attach and run, I get

#0  __GI___clock_nanosleep (clock_id=clock_id@entry=0, flags=flags@entry=0, req=req@entry=0x7ffe3b266bb0, rem=rem@entry=0x7ffe3b266bb0)
    at ../sysdeps/unix/sysv/linux/clock_nanosleep.c:79
        r = -516
#1  0x00007f99fe824403 in __GI___nanosleep (requested_time=requested_time@entry=0x7ffe3b266bb0, remaining=remaining@entry=0x7ffe3b266bb0) at nanosleep.c:27
        ret = <optimized out>
#2  0x00007f99fe82433a in __sleep (seconds=0) at ../sysdeps/posix/sleep.c:55
        save_errno = 0
        ts = {tv_sec = 474, tv_nsec = 980286586}
#3  0x000055d533c98518 in Perl_pp_sleep ()
No symbol table info available.
#4  0x000055d533c38d06 in Perl_runops_standard ()
No symbol table info available.
#5  0x000055d533baca7c in perl_run ()
No symbol table info available.
#6  0x000055d533b82472 in main ()
No symbol table info available.

I would expect something to be able to parse the arguments to main.


Note: I’m not looking for /proc/$$/cmdline. That can be changed. I want the actual arguments to main

One Answer

What you want is not possible in any generic fashion in absence of the debug symbols and persistently stored addresses for those function arguments (argc, argv). Only debug symbols will give you a generic way of accessing the argc and argv symbols from the frame that represents main. Theoretically. Example from x86-64:

(gdb) bt
#0  __GI___clock_nanosleep (clock_id=clock_id@entry=0, flags=flags@entry=0, req=req@entry=0x7fffffffdd30, rem=rem@entry=0x7fffffffdd30) at ../sysdeps/unix/sysv/linux/clock_nanosleep.c:79
#1  0x00007ffff7d25eb7 in __GI___nanosleep (requested_time=requested_time@entry=0x7fffffffdd30, remaining=remaining@entry=0x7fffffffdd30) at nanosleep.c:27
#2  0x00007ffff7d25dee in __sleep (seconds=0) at ../sysdeps/posix/sleep.c:55
#3  0x00005555556b38ec in Perl_pp_sleep ()
#4  0x0000555555653a56 in Perl_runops_standard ()
#5  0x00005555555c78dc in perl_run ()
#6  0x000055555559d432 in main ()
(gdb) f 6
#6  0x000055555559d432 in main ()
(gdb) info frame
Stack level 6, frame at 0x7fffffffdf30:
 rip = 0x55555559d432 in main; saved rip = 0x7ffff7c670b3
 caller of frame at 0x7fffffffdee0
 Arglist at 0x7fffffffded8, args: 
 Locals at 0x7fffffffded8, Previous frame's sp is 0x7fffffffdf30
 Saved registers:
  rbx at 0x7fffffffdf08, rbp at 0x7fffffffdf10, r12 at 0x7fffffffdf18, r13 at 0x7fffffffdf20, rip at 0x7fffffffdf28
(gdb) p (char*)rdi
No symbol "rdi" in current context.
(gdb) p argc
No symbol "argc" in current context.
(gdb) p argv
No symbol "argv" in current context.

As you can see, the registers preserved are hardly sufficient to guide you to the proper location of argc and argv in memory. The first few to be used for argument passing would be RDI, RSI, RDX, RCX ... and those are volatile across stack frames.

So whatever values were passed to main() are no longer available from any location that we know about for certain.

It's possible that with knowledge about the target you may find the pointers saved in local stack variables, but the register values will no longer exist. Possible locations (if you fancy depending on a particular C runtime implementation) would be looking at __libc_start_main and friends. Also, info args (basically the arguments you can set with set args ... which is also one long string) might give you something, but again usually not without symbols available.

You can dig around your stack from frame 6 (main) yourself after switching to it and issuing x/16xg $sp ... you can then attempt to look at all those addresses, e.g. by printing them as char* with p (char*)0x7fffffffded8 and similar ...

Original answer below.


How about this?:

(gdb) info proc cmdline 
process 27856
cmdline = '/usr/bin/perl -e$|=1; print $$; sleep 500; HELLO WORLD'

Should be equivalent to querying /proc/$$/cmdline ...

Answered by 0xC0000022L on December 1, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP