最近我一直在为Nexus S手机逆向Android框架。99% 的源代码当然是开放的,但很少有专有共享库需要下载以编译操作系统。这些共享库从符号中剥离出来,突然间我开始明白我并不真正理解剥离的库是如何链接的。如果符号不存在,链接器如何匹配引用的库函数?
剥离的共享库是如何链接的?
逆向工程
linux
小精灵
图书馆
2021-06-12 04:07:37
1个回答
即使被剥离的库仍然必须保留动态链接所需的符号。这些通常放置在命名的部分中.dynsym
,并且也由动态部分中的条目指向。
例如,这是readelf
一个剥离的 Android 库的输出:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .hash HASH 000000b4 0000b4 000280 04 A 2 0 4
[ 2] .dynsym DYNSYM 00000334 000334 0005b0 10 A 3 6 4
[ 3] .dynstr STRTAB 000008e4 0008e4 00042f 00 A 0 0 1
[ 4] .rel.dyn REL 00000d14 000d14 000008 08 A 2 2 4
[ 5] .rel.plt REL 00000d1c 000d1c 000100 08 A 2 6 4
[ 6] .plt PROGBITS 00000e24 000e24 000214 04 AX 0 0 4
[ 7] .text PROGBITS 00001038 001038 00210c 00 AX 0 0 8
[ 8] .rodata PROGBITS 00003144 003144 000a70 00 A 0 0 4
[ 9] .ARM.extab PROGBITS 00003bb4 003bb4 000024 00 A 0 0 4
[10] .ARM.exidx ARM_EXIDX 00003bd8 003bd8 000170 00 AL 7 0 4
[11] .dynamic DYNAMIC 00004000 004000 0000c8 08 WA 3 0 4
[12] .got PROGBITS 000040c8 0040c8 000094 04 WA 0 0 4
[13] .data PROGBITS 0000415c 00415c 000004 00 WA 0 0 4
[14] .bss NOBITS 00004160 004160 000940 00 WA 0 0 4
[15] .ARM.attributes ARM_ATTRIBUTES 00000000 004160 000010 00 0 0 1
[16] .shstrtab STRTAB 00000000 004170 000080 00 0 0 1
您可以看到,即使它缺少该.symtab
部分,该.dynsym
部分仍然存在。事实上,节表也可以被删除(例如使用sstrip
),文件仍然可以工作。这是因为动态链接器只使用程序头(又名段表):
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
EXIDX 0x003bd8 0x00003bd8 0x00003bd8 0x00170 0x00170 R 0x4
LOAD 0x000000 0x00000000 0x00000000 0x03d48 0x03d48 R E 0x1000
LOAD 0x004000 0x00004000 0x00004000 0x00160 0x00aa0 RW 0x1000
DYNAMIC 0x004000 0x00004000 0x00004000 0x000c8 0x000c8 RW 0x4
该DYNAMIC
段对应于该.dynamic
部分并包含动态链接器的信息:
Dynamic section at offset 0x4000 contains 21 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [liblog.so]
0x00000001 (NEEDED) Shared library: [libcutils.so]
0x00000001 (NEEDED) Shared library: [libc.so]
0x00000001 (NEEDED) Shared library: [libstdc++.so]
0x00000001 (NEEDED) Shared library: [libm.so]
0x0000000e (SONAME) Library soname: [libnetutils.so]
0x00000010 (SYMBOLIC) 0x0
0x00000004 (HASH) 0xb4
0x00000005 (STRTAB) 0x8e4
0x00000006 (SYMTAB) 0x334
0x0000000a (STRSZ) 1071 (bytes)
0x0000000b (SYMENT) 16 (bytes)
0x00000003 (PLTGOT) 0x40c8
0x00000002 (PLTRELSZ) 256 (bytes)
0x00000014 (PLTREL) REL
0x00000017 (JMPREL) 0xd1c
0x00000011 (REL) 0xd14
0x00000012 (RELSZ) 8 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x6ffffffa (RELCOUNT) 1
0x00000000 (NULL) 0x0
符号解析所需的两个条目是STRTAB
和SYMTAB
。它们共同构成了动态符号表:
Symbol table '.dynsym' contains 91 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00001038 0 SECTION LOCAL DEFAULT 7
2: 00003144 0 SECTION LOCAL DEFAULT 8
3: 00003bb4 0 SECTION LOCAL DEFAULT 9
4: 0000415c 0 SECTION LOCAL DEFAULT 13
5: 00004160 0 SECTION LOCAL DEFAULT 14
6: 00000000 0 FUNC GLOBAL DEFAULT UND clock_gettime
7: 000026e1 88 FUNC GLOBAL DEFAULT 7 ifc_init
8: 00000001 20 FUNC GLOBAL DEFAULT UND strcpy
9: 00002d6d 140 FUNC GLOBAL DEFAULT 7 open_raw_socket
[...]
您可以看到它包含UND
(未定义的)符号 - 库所需并从其他 .so 导入的符号,以及库为其用户导出的“普通”全局符号。导出的符号在值列中列出的库中具有其地址。