通过读取maps信息获取可执行文件头装载的地址
1. 通过maps文件获取进程的文件头和段表
想要实现这一功能,根据书上所写,首先要找到代码段的首地址BaseVaddr
,然后文件头就从这个地址开始,用ptrace
从这个地址读一个sizeof(Elf64_Ehdr)
大小的数据出来就可以了
但是,我在实现的时候遇到的一个问题,读出来的结果压根不对,其结果如下所示
$ sudo ./reconstruct 12127
BaseVaddr: 0x401000
ELF header:
magic: f3 f 1e fa ff ff ff ff 48 8b 5 e9 ff ff ff ff
Type: c085
Machine: 274
Version: 0
Entry point address: c308c4
Start of Program header: 2fe235ff
Size of program header: 65535 (bytes)
Number of Program headers: 61952
Size of section header: 57833 (bytes)
Number of Section headers: 65535
Section header string table index: 65535
正常64为ELF文件的前四个字节应该为\0x7fELF
,而这里是个啥???
2. 手动查看maps文件
从上图可以发现,它跟网上很多博客给出来的并不是完全一样,在权限为r-xp
的代码段上面还有一个权限为r--p
的段,且其映像文件也是test
3. 尝试BaseVaddr
值
因此我去尝试着将BaseVaddr
设置为固定值0x400000
,继续运行代码得出如下结果:
$ sudo ./reconstruct 12127
BaseVaddr: 0x400000
correct!
ELF header:
magic: 7f 45 4c 46 0 0 0 0 0 0 0 0 0 0 0 0
Type: 2
Machine: 3e
Version: 0
Entry point address: 0x401070
Start of Program header: 64 (bytes into file)
Flags: 0x0
Size of this header: 0 (bytes)
Size of program header: 0 (bytes)
Number of Program headers: 13
Size of section header: 64 (bytes)
Number of Section headers: 0
Section header string table index: 0
对比一下用readelf
读出来的文件头
$ readelf -h ./test
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x401070
Start of program headers: 64 (bytes into file)
Start of section headers: 14728 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 13
Size of section headers: 64 (bytes)
Number of section headers: 31
Section header string table index: 30
可以发现其大部分是对上了,但是有一些数据是对不上的,比如Data
,Version
,OS/ABI
,Size of this header
,Size of program header
都是对不上的,段的数量却是正确的
4. 结论
虽然上面还是有一些数据对不上,但是有一个结论,那就是在这种情况下,系统实际装载可执行文件的时候,是将文件头和段表等信息作为r--p
权限的段,并将其与实际的代码段分开
5. 修正
出现上面有些许不对的,是我自己的代码问题,在64位平台中的gcc环境下,unsigned long是8个字节,ptrace每次读取的是4个字节,而我用8个字节去存4个字节的数据就出现上面的错误了。现在数据是对的了
$ sudo ./reconstruct 13483
BaseVaddr: 0x400000
correct!
ELF header:
magic: 7f 45 4c 46 2 1 1 0 0 0 0 0 0 0 0 0
Type: 2
Machine: 3e
Version: 1
Entry point address: 401070
Start of Program header: 64 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program header: 56 (bytes)
Number of Program headers: 13
Size of section header: 64 (bytes)
Number of Section headers: 31
Section header string table index: 30
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!