为什么so里面有两个PT_LOAD段, 在maps文件里面却有三段映射
最新在做https://bbs.pediy.com/thread-270030.htm的分析研究, 主要目的是避免监守自盗, 同时也希望在实战中学习,在分析的过程中就遇到了一些疑惑
1 | 其中一个疑惑便是为什么elf文件里面只有 2 个段, 但是到内存后却有 3 段映射.
|
这里尝试做一些解答.
对应现象
- 通过ida观察elf具有两个PT_LOAD段
- 通过maps文件观察, 具有3个映射段
- 通过源码观察, 确实只加载2个段
内核层mmap观察分配情况
1 2 3 4 5 6 7 | 130 |OnePlus7T: / data / local / tmp
[ 3142.307841 ] [info]kr_mmap mmap file libsotest.so. vaddr = 0x7b51953000 , len = 0x1d0 prot = 1 , off = 0x0 (ReadProgramHeaders)
[ 3142.307861 ] [info]kr_mmap mmap file libsotest.so. vaddr = 0x7b51952000 , len = 0xae0 prot = 1 , off = 0x35000 (ReadSectionHeaders)
[ 3142.307891 ] [info]kr_mmap mmap file libsotest.so. vaddr = 0x7b51950000 , len = 0x1ca0 prot = 1 , off = 0x34000 (ReadDynamicSection)
[ 3142.307906 ] [info]kr_mmap mmap file libsotest.so. vaddr = 0x7b5194f000 , len = 0xaeb prot = 1 , off = 0x0 (ReadDynamicSection)
[ 3142.308172 ] [info]kr_mmap mmap file libsotest.so. vaddr = 0x7abcd88000 , len = 0x34988 prot = 5 , off = 0x0 (LoadSegments)
[ 3142.308199 ] [info]kr_mmap mmap file libsotest.so. vaddr = 0x7abcdcc000 , len = 0x11f8 prot = 3 , off = 0x34000 (LoadSegments)
|
通过上面的日志信息可以了解到, linker在Android10上面总计进行了6次mmap, 分别为
(1) ReadProgramHeaders
(2) ReadSectionHeaders
(3) ReadDynamicSection
(4) ReadDynamicSection
(5) LoadSegments(通过文件偏移, 可以知晓这里对应elf的第一个段)
(6) LoadSegments(通过文件偏移, 可以知道这里对应elf的第二个段)
其中最后2次映射由LoadSegments引发,也就是我们真正要关注的问题点. 通过mmap观察走两次mmap为正常行为,为什么maps有3段呢? 我们还需要进一步分析, 因此我又hook了mprotect的方法
(tips: 如果大家仔细观察, 这里又会有另外一个小疑问, 为什么mmap的偏移是0x34000, 但是elf的fileoffset是0x34D18. 这里后面再做详细解答)
详细堆栈信息如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
kr_openat tgid = 7635 path = / proc / 7635 / maps
kr_openat vaddr = 0x7b51953000
pc = 0x7b52dace58 sp = 0x7fe046bc00 c - >sp = 0x7fe046bc00 c - >pc = 0x7b52dace58 regs_len = 320 stack_len = 1024 path_len = 1024
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
kr_openat tgid = 7635 path = / proc / 7635 / maps
kr_openat vaddr = 0x7b51952000
pc = 0x7b52dace58 sp = 0x7fe046bc00 c - >sp = 0x7fe046bc00 c - >pc = 0x7b52dace58 regs_len = 320 stack_len = 1024 path_len = 1024
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
kr_openat tgid = 7635 path = / proc / 7635 / maps
kr_openat vaddr = 0x7b51950000
pc = 0x7b52dace58 sp = 0x7fe046bbf0 c - >sp = 0x7fe046bbf0 c - >pc = 0x7b52dace58 regs_len = 320 stack_len = 1040 path_len = 1024
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
kr_openat tgid = 7635 path = / proc / 7635 / maps
kr_openat vaddr = 0x7b5194f000
pc = 0x7b52dace58 sp = 0x7fe046bbf0 c - >sp = 0x7fe046bbf0 c - >pc = 0x7b52dace58 regs_len = 320 stack_len = 1040 path_len = 1024
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
kr_openat tgid = 7635 path = / proc / 7635 / maps
kr_openat vaddr = 0x7abcd88000
pc = 0x7b52dace58 sp = 0x7fe046c050 c - >sp = 0x7fe046c050 c - >pc = 0x7b52dace58 regs_len = 320 stack_len = 16304 path_len = 1024
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
kr_openat tgid = 7635 path = / proc / 7635 / maps
kr_openat vaddr = 0x7abcdcc000
pc = 0x7b52dace58 sp = 0x7fe046c050 c - >sp = 0x7fe046c050 c - >pc = 0x7b52dace58 regs_len = 320 stack_len = 16304 path_len = 1024
|
补全hook信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | [ 18391.525011 ] [info]kr_mmap mmap file libsotest.so. vaddr = 0x7b5195a000 , len = 0x1d0 prot = 1 , off = 0x0
[ 18391.525027 ] [info]kr_mmap mmap file libsotest.so. vaddr = 0x7b51959000 , len = 0xae0 prot = 1 , off = 0x35000
[ 18391.525055 ] [info]kr_mmap mmap file libsotest.so. vaddr = 0x7b51957000 , len = 0x1ca0 prot = 1 , off = 0x34000
[ 18391.525069 ] [info]kr_mmap mmap file libsotest.so. vaddr = 0x7b51956000 , len = 0xaeb prot = 1 , off = 0x0
[ 18391.525315 ] [info]kr_mmap mmap file libsotest.so. vaddr = 0x7abcd16000 , len = 0x34988 prot = 5 , off = 0x0
[ 18391.525343 ] [info]kr_mmap mmap file libsotest.so. vaddr = 0x7abcd5a000 , len = 0x11f8 prot = 3 , off = 0x34000
[ 18391.525629 ] [ 20211115_17 : 03 : 46.098714 ]@ 6 [info]kr_mprotect start = 0x7abcd5a000 len = 0x1000 prot = 1 (关键信息)
[ 18391.525670 ] [ 20211115_17 : 03 : 46.098754 ]@ 6 [info]kr_mprotect start = 0x7b51955000 len = 0x1000 prot = 1
[ 18391.525769 ] [ 20211115_17 : 03 : 46.098853 ]@ 6 [info]kr_mprotect start = 0x7b51b82000 len = 0x64000 prot = 1
[ 18391.525851 ] [ 20211115_17 : 03 : 46.098936 ]@ 6 [info]kr_mprotect start = 0x7b51c3a000 len = 0x64000 prot = 1
[ 18391.525933 ] [ 20211115_17 : 03 : 46.099017 ]@ 6 [info]kr_mprotect start = 0x7b51aeb000 len = 0x64000 prot = 1
[ 18391.526019 ] [ 20211115_17 : 03 : 46.099104 ]@ 6 [info]kr_mprotect start = 0x7b51a87000 len = 0x64000 prot = 1
[ 18391.533599 ] [ 20211115_17 : 03 : 46.106682 ]@ 6 [info]kr_mprotect start = 0x7a63101000 len = 0x2c000 prot = 3
[ 18391.533950 ] [ 20211115_17 : 03 : 46.107034 ]@ 6 [info]kr_mprotect start = 0x7a63101000 len = 0x1a2b8 prot = 5
[ 18391.534488 ] [ 20211115_17 : 03 : 46.107573 ]@ 6 [info]kr_mprotect start = 0x7a63132000 len = 0x12000 prot = 3
[ 18391.534601 ] [ 20211115_17 : 03 : 46.107685 ]@ 6 [info]kr_mprotect start = 0x7a63132000 len = 0xa78 prot = 5
[ 18391.534683 ] [ 20211115_17 : 03 : 46.107768 ]@ 6 [info]kr_mprotect start = 0x7a63101000 len = 0x2c000 prot = 3
|
第二次采集的时候通过hook补全了mprotect权限, 发现为了一行关键信息. linker使用mprotect进行了权限修改, 因此内核层便进行了maps分割
这里简单画了下对应信息, 方便能够理解背后的行为.
通过上面的分析的,便解答了心中的疑惑. 那么我们进一步思考linker为什么需要进行上面的行为呢? 这个问题我们就需要去linker源码里面寻找答案了,
堆栈信息已经给我们提供了阅读代码的线索, 我们也就可以去大海里遨游不怕迷路了.
linker LoadSegments详细分析
ElfReader::ReadProgramHeaders 进行mmap, 在析构函数进行 munmap
ElfReader::ReadSectionHeaders 后续再分析
ElfReader::ReadDynamicSection 后续再分析
ElfReader::ReadDynamicSection 后续再分析
ElfReader::LoadSegments 这里进行一下详细阐述, linker其实是操作系统和elf的连接器, 既要满足elf的要求, 又要满足mmap的一些限制.
比如:
mmap需要按页分配, elf需要对齐
下图详细描述了虚拟地址空间映射和so文件之间的关系
因为mmap时使用但是PAGE_START(phdr->p_offset), elf的fileoffset是0x34D18, 向上页对齐便是0x34000. 心里的疑惑也就解开了.
.bss 也叫做全局变量段
待解答疑问
- mprotect由谁调用的,目的是什么?
其他比较好的讲解
liner底层原理
欢迎同行一起交流
https://github.com/yhnu/op7t
[培训]《安卓高级研修班(网课)》月薪三万计划
最后于 2021-11-17 09:48
被github_yhnu编辑
,原因: