如何从共享对象中find程序的argc
和argv
? 我正在写一个C库,将通过LD_PRELOAD
加载。 我已经能够find堆栈两种不同的方式:
__asm__
调用读取rsp
。 /proc/<pid>/maps
并parsing堆栈的条目。 然后我可以创build一个指针,将它指向堆栈段,然后遍历查找数据。 问题是我找不出一个有效的方法来确定什么字节argc
和指向argv
string的指针。
我知道/proc/<pid>/cmdline
还包含参数,每个由0x00
分隔,但我有兴趣find内存中的所有内容。
在gdb中,我看到一个argc
的DWORD
,后面跟着一个QWORD
,它是第一个指针。 argc
地址前的20个字节是指向主程序代码段的指针。 但是这不是确定argc
和argv
的确定性方法。
我见过几个post,但没有工作代码:
在你的第二个链接中的这个响应包含工作的源代码,对于我来说(Gnu / Linux elf-based系统),包括在LD_PRELOAD
期间LD_PRELOAD
。
代码很短, 它由一个功能组成:
int foo(int argc, char **argv, char **env) { // Do something with argc, argv (and env, if desired) }
以及.init_array
部分中该函数的指针:
__attribute__((section(".init_array"))) static void *foo_constructor = &foo;
把它放到一个共享库中,然后LD_PRELOADing共享库肯定会触发到foo
的调用,当我尝试它时,它显然是用argc
和argv
,后来被传递给main
(以及environ
的值)。
最可靠的可能是使用/proc/<pid>/cmdline
因为它是由内核提供的,不会因C实现而改变(例如取决于您使用的处理器)。
问题是,在某些平台上,函数参数(fx main
)将被传递到堆栈上,但在其他平台上,它可能作为寄存器(在x86-64平台上的fx)被传递。 如果它是通过寄存器发送的,那么如果启用了优化, main
不会将这些内容存储在内存中(如果不需要的话),也就是说,如果你自己没有明确地这样做,它可能不会保留在内存中。
即使参数在堆栈上传递, main
参数的确切位置也可能因编译器/实现的版本而异。 这意味着几乎没有任何可靠的方法从堆栈中检索它们(正如有人指出,在执行main
命令时可能会将其修改为命令行解析的一部分)。
即使内核将参数传递给程序的方式也没什么帮助,因为它们是通过寄存器传递的 – 这意味着它们要存储在哪里完全取决于CRT init(它可能会从版本更改为版)。
简而言之,在稍后检索argv
和argc
,需要你正在使用的CRT的明确支持(微软的CRT是这样的,但是GNU并不AFAIK)。
你当然可以做的是抓住GCC的来源,并修补CRT的init实际存储argv
和argc
地方,你可以稍后检索它们。 如果在运行程序的CRT init(动态链接期间的fx)之前需要访问它们,这当然不起作用。