Depois de ler este artigo sobre como executar programas arbitrários alterando o PT_INTERP
para um interpretador personalizado, tentei experimentar isso localmente:
$ 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!
Este
PT_INTERP
cabeçalho do programa contém um caminho, que é o caminho do interpretador (arquivo executável) em que nosso ELF será executado
Desde os solution
pedidos ./flag
como seu interpretador, por que não ./flag
roda e imprime a mensagem "Hello World", quando solution
é executado? Em vez disso, ocorre uma falha de segmentação, que é diferente do comportamento no artigo.
Como posso registrar e executar com sucesso um interpretador personalizado em 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
Se você executar
dmesg
, deverá ver algo comoO motivo é que ambos
flag
esolution
têm um segmento em 0x400000.Uma maneira rápida de evitar isso é usar o
tinyelf
helloworld
binário comoflag
; não tem um segmento conflitante, e tudo funciona.Adaptando o exemplo do TinyELF, escreva isso para
flag.c
:Construa isso da seguinte forma:
Então o
solution
binário que você já tem funcionará.