从库中查找argc和argv

如何从共享对象中find程序的argcargv ? 我正在写一个C库,将通过LD_PRELOAD加载。 我已经能够find堆栈两种不同的方式:

  1. 通过内联__asm__调用读取rsp
  2. 读取/proc/<pid>/maps并parsing堆栈的条目。

然后我可以创build一个指针,将它指向堆栈段,然后遍历查找数据。 问题是我找不出一个有效的方法来确定什么字节argc和指向argvstring的指针。

我知道/proc/<pid>/cmdline还包含参数,每个由0x00分隔,但我有兴趣find内存中的所有内容。

在gdb中,我看到一个argcDWORD ,后面跟着一个QWORD ,它是第一个指针。 argc地址前的20个字节是指向主程序代码段的指针。 但是这不是确定argcargv的确定性方法。

我见过几个post,但没有工作代码:

  • http://linux.derkeiler.com/Newsgroups/comp.os.linux.development.system/2005-07/0296.html
  • https://sourceware.org/ml/libc-help/2009-11/msg00010.html

在你的第二个链接中的这个响应包含工作的源代码,对于我来说(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的调用,当我尝试它时,它显然是用argcargv ,后来被传递给main (以及environ的值)。

最可靠的可能是使用/proc/<pid>/cmdline因为它是由内核提供的,不会因C实现而改变(例如取决于您使用的处理器)。

问题是,在某些平台上,函数参数(fx main )将被传递到堆栈上,但在其他平台上,它可能作为寄存器(在x86-64平台上的fx)被传递。 如果它是通过寄存器发送的,那么如果启用了优化, main 不会将这些内容存储在内存中(如果不需要的话),也就是说,如果你自己没有明确地这样做,它可能不会保留在内存中。

即使参数在堆栈上传递, main参数的确切位置也可能因编译器/实现的版本而异。 这意味着几乎没有任何可靠的方法从堆栈中检索它们(正如有人指出,在执行main命令时可能会将其修改为命令行解析的一部分)。

即使内核将参数传递给程序的方式也没什么帮助,因为它们是通过寄存器传递的 – 这意味着它们要存储在哪里完全取决于CRT init(它可能会从版本更改为版)。

简而言之,在稍后检索argvargc ,需要你正在使用的CRT的明确支持(微软的CRT是这样的,但是GNU并不AFAIK)。

你当然可以做的是抓住GCC的来源,并修补CRT的init实际存储argvargc地方,你可以稍后检索它们。 如果在运行程序的CRT init(动态链接期间的fx)之前需要访问它们,这当然不起作用。