// 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;
}

위는 문제의 소스코드다.

바이너리 분석

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

free(ptr)
free(ptr)

같은 메모리 영역을 두번 해제 하므로 Double_Free_Bug가 일어난다.

⇒ 이후 해당 glibc버전이 높아 해당 취약점을 인지하여 프로세스를 끈다.

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

결국 프로세스가 종료되어 이후 system 함수는 호출되지 않는다.

초반에 입력 받은 데이터를 바탕으로 *(long *)*ptr = *(ptr+1); 을 통해 ptr+1에 있는 값을 ptr에 쓴다.

이를 활용하여 hook_overwrite을 을 발생시켜 쉘을 탈취하면 될것이다.

익스플로잇 시나리오

  1. 주어진 libc와 출력되는 stdout 값을 통해 libc_base를 구한다.
  2. malloc_hook을 main함수에서 실행되는 쉘을 실행하는 곳으로 이동하는 주소로 덮는다.