在阅读了这篇关于通过更改为自定义解释器来执行任意程序的文章后PT_INTERP
,我尝试在本地进行实验:
$ cat flag.c
#include <stdio.h>
int main(int argc, char **argv) {
printf("Hello World!\n");
return 0;
}
$ gcc -static flag.c -o flag
$ cat solution.c
const char interp_section[] __attribute__((section(".interp"))) = "./flag";
$ gcc -s -fno-ident -Wl,--build-id=none -Wl,-e,0 -static -nostdlib solution.c -o solution
$ ./solution
Segmentation fault
$ ./flag
Hello World!
这个
PT_INTERP
程序头包含一个路径,也就是我们的ELF将在其下运行的解释器(可执行文件)的路径
既然solution
requests./flag
作为它的解释器,为什么不./flag
运行并打印消息“Hello World”,什么时候solution
执行?而是发生了分段错误,这与文章中的行为不同。
如何在 中成功注册和执行自定义解释器PT_INTERP
?
$ readelf -l solution
Elf file type is EXEC (Executable file)
Entry point 0x0
There are 4 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000000e0 0x00000000000000e0 R 0x8
INTERP 0x0000000000000120 0x0000000000400120 0x0000000000400120
0x0000000000000007 0x0000000000000007 R 0x1
[Requesting program interpreter: ./flag]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x0000000000000127 0x0000000000000127 R 0x1000
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x10
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp
03
如果你运行
dmesg
,你应该看到类似原因是两者都在 0x400000 处有一个段
flag
。solution
避免这种情况的一种快速方法是将
tinyelf
helloworld
二进制文件用作flag
; 它没有冲突的部分,一切正常。改编 TinyELF 示例,将其写入
flag.c
:如下构建:
然后
solution
你已经拥有的二进制文件将起作用。