通過讀取maps資訊獲取可執行檔案頭裝載的地址
阿新 • • 發佈:2021-06-19
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
許可權的段,並將其與實際的程式碼段分開