Rya*_*yan 38 c linux compiler-construction linker shared-libraries
我的问题如下:
何时是程序中指定的共享对象的地址?链接期间?数据加载中?如果我想在程序system内部找到命令的内存地址,libc我可以很容易地找到它gdb,但是如果我不想将程序带入调试器呢?
这个地址可以从一次运行变为运行吗?是否还有其他静态分析工具可以查看运行时将库或函数加载到该程序的内存空间的位置?
编辑:我想在程序之外的这些信息(即使用实用程序,如objdump收集信息)
osg*_*sgx 64
库由ld.so(动态链接器或运行时链接器也称为rtld,ld-linux.so.2或者ld-linux.so.*在Linux的情况下; glibc的一部分)加载.它被声明为.interp所有动态链接ELF二进制文件的"解释器"(INTERP; 部分).因此,当你启动程序时,Linux将启动ld.so(加载到内存并跳转到其入口点),然后ld.so将程序加载到内存中,准备然后运行它.您也可以使用启动动态程序
/lib/ld-linux.so.2 ./your_program your_prog_params
Run Code Online (Sandbox Code Playgroud)
ld.so做一个实际的open和mmap所有需要的ELF文件,你的程序的ELF文件和所有需要的库的ELF文件.此外,它填充GOT和PLT表并进行重定位解析(它将函数的地址从库写入调用站点,在许多情况下使用间接调用).
您可以通过ldd实用程序获得某些库的典型加载地址.它实际上是一个bash脚本,它设置ld.so的调试环境变量(实际上是LD_TRACE_LOADED_OBJECTS=1在glibc的rtld的情况下)并启动一个程序.您甚至可以在不需要脚本的情况下自己完成,例如使用bash轻松更改单个运行的环境变量:
LD_TRACE_LOADED_OBJECTS=1 /bin/echo
Run Code Online (Sandbox Code Playgroud)
该ld.so会看到这个变量,将解决他们的所有需要的库,并打印负荷地址.但是使用这个变量集,ld.so实际上不会启动程序(不确定程序或库的静态构造函数).如果禁用ASLR功能,则加载地址大多数时间都相同.现代Linux通常启用了ASLR,因此要禁用它,请使用echo 0 | sudo tee /proc/sys/kernel/randomize_va_space.
您可以system在binutils中找到libc.so带有nm实用程序的函数偏移量.我想,你应该使用nm -D /lib/libc.soor objdump -T /lib/libc.so和grep输出.
使用的nm命令libc.so将显示system符号的位置libc.so.但是,如果启用了ASLR,libc.so则加载地址,因此system每次运行程序时,最终地址将随机变化.即使没有ASLR,您也需要确定libc.so加载的地址并将system该数量的地址抵消.
如果您只想要一个函数的地址而不是硬编码名称,那么您可以dlopen()使用主程序:
void *self = dlopen(NULL, RTLD_NOW);
dlsym(self, "system"); // returns the pointer to the system() function
Run Code Online (Sandbox Code Playgroud)
如果您只想在编译时知道名称的函数的地址,只需使用 void *addr = &system;