sint

oogu ㅣ 2023. 2. 3. 10:48

#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(30);
}

void get_shell()
{
    system("/bin/sh");
}

int main()
{
    char buf[256];
    int size;

    initialize();

    signal(SIGSEGV, get_shell);

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

    if (size > 256 || size < 0)
    {
        printf("Buffer Overflow!\n");
        exit(0);
    }

    printf("Data: ");
    read(0, buf, size - 1);

    return 0;
}

[그림 1-1]

오랜만에 32bit고 거의 모든 보호기법이 없다.

bof을 통해 ret 값을 get_shell로 덮어보자!

코드에서  Size 변수의 크기를 검사하는데 0<= Size <= 255 안에 있으면 된다.

만약 0을 입력하면 read 함수의 세 번째 인자에서 0-1 이 되는데 read 함수 세 번째 인자는 부호가 없는 size_t 형이므로 음수가 전달되면 매우 큰 수로 해석됩니다. 이를 통해 bof가 발생됩니다.

[그림 1-2]

main+128을 참조하면 buf의 위치는 ebp-0x100(256)에 있다.

[그림 1-3]

따라서 260 + get_shell 주소를 채우면 쉘이 실행 될 것이다.

[그림 1-4]
[그림 1-5]

성공!

 

다른 방법으로 main 코드에 signal(SIGSEGV,get_shell) 코드가 존재하는데, 이 코드는 SIGSEGV(Segmentation Fault)가 일어나면 get_shell 함수가 실행된다는 뜻입니다. 따라서 ret 값으로 get_shell 주소가 아니라 "AAAAA.."와 같은 dummy data를 overwrite하면 Segmentation Faultrk 발생해 get_shell이 실행됩니다.

 

이 문제를 풀면서 어떤 변수를 정의할 때, 변수를 활용하는 모든 과정에서 변수에 어떤 값이 저장될 수 있는지 이해하고, 자료형을 지정해야된다고 알았다.

'Dreamhack - pwnable' 카테고리의 다른 글

seccomp  (0) 2023.02.13
cmd_center  (0) 2023.02.03
tcache_dup2  (0) 2023.02.01
tcache_dup  (0) 2023.02.01
tcache_poison  (0) 2023.01.30