読んだ後これカスタムインタプリタに変更してランダムプログラムを実行する方法についての記事に関連して、ローカルで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
リクエストがソルバーとして機能するために実行されたときに「Hello World」メッセージを発行して印刷しないの./flag
はなぜですか?代わりに、この資料の動作と異なる分割エラーが発生します。./flag
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
ベストアンサー1
実行すると、dmesg
次の内容が表示されます。
(solution): Uhuuh, elf segment at 0000000000400000 requested but the memory is mapped already
flag
その理由は、両方ともsolution
0x400000に位置するセグメントがあるためです。
これを避けるための簡単な方法は、次を使用することです。tinyelf
helloworld
バイナリ;衝突する部分がなく、flag
すべてがうまく機能します。
TinyELFの例を修正して以下を作成してくださいflag.c
。
#include <asm/unistd.h>
long syscall(long n,
long a1, long a2, long a3, long a4, long a5, long a6);
void _start() {
syscall(__NR_write, 1, (long) "Hello World!\n", 13, 0, 0, 0);
syscall(__NR_exit, 0, 0, 0, 0, 0, 0);
}
long syscall(long n, long a1, long a2, long a3, long a4, long a5, long a6) {
asm volatile ("movq %4, %%r10;"
"movq %5, %%r8;"
"movq %6, %%r9;"
"syscall;"
: "=a"(n)
: "a"(n), "D"(a1), "S"(a2), "d"(a3),
"r"(a4), "r"(a5), "r"(a6)
: "%r10", "%r8", "%r9");
return n;
}
ビルドは次のとおりです。
gcc -nostartfiles -nostdlib flag.c -o flag
これにより、solution
既存のバイナリが機能します。