linux .so有什么借口,为什么有些程序需要连接ld-linux.so.x这个库

环境:目标系统为armeabi,32bit,linux,gcc4.9,glibc2.20,宿主机器为ubuntu12.04

执行readelf -d xxx.so,发现有些是需要连接ld-linux.so.x的,比如libffi.so:

$ /disk7/shuyin.wsy/tv/prebuilts/gcc/linux-x86/arm/arm-linux-gnueabi-4.9-glibc-2.20/bin/arm-linux-gnueabi-readelf -d libffi.so.6.0.2

Dynamic section at offset 0x5060 contains 28 entries:

Tag Type Name/Value

0x00000001 (NEEDED) Shared library: [libgcc_s.so.1]

0x00000001 (NEEDED) Shared library: [libc.so.6]

0x00000001 (NEEDED) Shared library: [ld-linux.so.3]

0x0000000e (SONAME) Library soname: [libffi.so.6]

里面有条NEEDED ld-linux.so.3。

有些库,比如eglplatform_null.so就没有这一行。

即使我添加了-nodefaultlib -nostdlib -lc -lgcc_s也没办法搞掉NEEDED ld-linux.so.3。

首先,可执行程序由arm-linux-gnueabi-ld去连接的,连接过程中需要找到所有的符号,如果用到了ld-linux.so.3里面的符号,那么就应当去连接它;如果没用到,就可以不连接。

arm-linux-gnueabi-nm  --dynamic ld-linux.so.3可以查看到ld-linux.so.3的符号,加dynamic的话,只看动态的符号,不加的话会有很多无关的符号输出来:

00017ae0 W free

00000000 A GLIBC_2.0

00000000 A GLIBC_2.1

00000000 A GLIBC_2.3

00000000 A GLIBC_2.4

00000000 A GLIBC_PRIVATE

0002ff40 D __libc_enable_secure

0001793c W __libc_memalign

0002ff38 D __libc_stack_end

00017a84 W malloc

0002fc8c D __pointer_chk_guard

00030940 B _r_debug

00017b84 W realloc

00030050 D _rtld_global

0002fce8 D _rtld_global_ro

0002fce0 D __stack_chk_guard

00013870 T __tls_get_addr

去掉明显不靠谱的GLIBC_2.0,__libcxxx,malloc(你不会以为malloc是ld-linux.so里面实现的函数吧)之类的,还剩5个:

0002fce0 D __stack_chk_guard

0002fc8c D __pointer_chk_guard

00013870 T __tls_get_addr

00030050 D _rtld_global

0002fce8 D _rtld_global_ro四个数据,一个函数。

使用arm-linux-gnueabi-objdump -R xxx可以找到动态链接的xxx所缺的符号(函数,变量什么的):

find . -name "*.so*" | while read line #搜索连接到ld-linux.so的所有的库文件,保存到need_list.log

do

ret=`readelf -d $line | grep ld-linux`

if [ "$ret" != "" ] ;then

echo $line

fi

done | tee need_list.log

cat need_list.log | while read line #在这些库文件里面,搜索5个符号,如果搜索不到,报错

do

echo "filename: $line"

ret=`/disk7/shuyin.wsy/tv/prebuilts/gcc/linux-x86/arm/arm-linux-gnueabi-4.9-glibc-2.20/bin/arm-linux-gnueabi-objdump -R $line | grep -e __stack_chk -e __pointer_chk -e __tls_get_addr -e _rtld_global`

if [ "$ret" == "" ] ; then

echo "error"

fi

done | tee need_error.log

##################################################################################

find . -name "*.so*" | while read line #搜索不连接ld-linux.so的所有的库文件,保存到not_need_list.log

do

ret=`readelf -d $line | grep ld-linux`

if [ "$ret" == "" ] ;then

echo $line

fi

done | tee not_need_list.log

cat not_need_list.log | while read line #在这些库文件里面,搜索5个符号,如果搜索到,报错

do

echo "filename: $line"

ret=`/disk7/shuyin.wsy/tv/prebuilts/gcc/linux-x86/arm/arm-linux-gnueabi-4.9-glibc-2.20/bin/arm-linux-gnueabi-objdump -R $line | grep -e __stack_chk -e __pointer_chk -e __tls_get_addr -e _rtld_global`

if [ "$ret" != "" ] ; then

echo "error"

fi

done | tee not_need_error.log

注意需要排出glibc自带的一些库的干扰(libssp, libasan)。上述shell脚本的结果验证了我们的猜想,需要使用那5个符号的,就需要连接ld-linux.so。(实际上除了glibc里面的一些库,也没人依赖_rtld_global,_rtld_global_ro)

那么为什么会使用到了这几个符号呢:

0002fce0 D __stack_chk_guard

0002fc8c D __pointer_chk_guard

00013870 T __tls_get_addr

man gcc可以看到

-fstack-protector

Emit extra code to check for buffer overflows, such as stack

smashing attacks. This is done by adding a guard variable to

functions with vulnerable objects. This includes functions that

call "alloca", and functions with buffers larger than 8 bytes.

The guards are initialized when a function is entered and then

checked when the function exits. If a guard check fails, an

error message is printed and the program exits.

-fstack-protector-all

Like -fstack-protector except that all functions are protected.

-mstack-protector-guard=guard

Generate stack protection code using canary at guard. Supported

locations are global for global canary or tls for per-thread

canary in the TLS block (the default). This option has effect

only when -fstack-protector or -fstack-protector-all is

specified.

如果我们不加-fstack-protector和-fstack-protector-all,再次编译程序,发现不依赖于ld-linux.so.3了。

但是加了-fstack-protector-all,-mstack-protector-guard=guard也不一定会依赖ld-linux.so.3,因为一个极其简单的函数,有必要堆栈保护吗?

注意:needed里面的ld-linux.so.3和.interp里面的/lib/ld-linux.so.3都是同一个文件,程序运行前会先执行.interp里面的/lib/ld-linux.so.3,将依赖的库载入内存,处理好GOT,然后将控制权交给程序的_start函数。即使needed里面没有ld-linux.so.3也不影响程序的执行,因为需要的符号已经存在了,/lib/ld-linux.so.3的符号。而且/lib/ld-linux.so.3里面有不少代码,防止重复载入ld-linux.so。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值