리눅스 파일 디스크립터에 관련된 문제임을 알 수 있습니다. fd 가 뭔지 알아야 문제가 풀릴 것이므로 리눅스 파일 디스크립터에 대해 간단히 짚어보고 가도록 하겠습니다.
File Descriptor
리눅스는 모든 것을 파일로 관리하는데, 장치도 예외가 아닙니다. 일반 파일과 내/외부 모든 장치를 파일로 취급한다는 것입니다. 이 파일에 접근하기 위한 추상적인 키가 파일 디스크립터인것입니다.
Value
Name
0
Standard input
1
Standard output
2
Standard error
위는 모든 프로세스가 갖추어야 하는 POSIX 파일 디스크립터입니다. 간단하게 짚어봤으니, 다시 문제로 돌아가보도록 합시다.
fd@ubuntu:~$ ls -al total 40 drwxr-x--- 5 root fd 4096 Oct 26 2016 . drwxr-xr-x 80 root root 4096 Jan 11 2017 .. d--------- 2 root root 4096 Jun 12 2014 .bash_history -rw------- 1 root root 128 Oct 26 2016 .gdb_history dr-xr-xr-x 2 root root 4096 Dec 19 2016 .irssi drwxr-xr-x 2 root root 4096 Oct 23 2016 .pwntools-cache -r-sr-x--- 1 fd_pwn fd 7322 Jun 11 2014 fd -rw-r--r-- 1 root root 418 Jun 11 2014 fd.c -r--r----- 1 fd_pwn root 50 Jun 11 2014 flag fd@ubuntu:~$
fd.c 를 까보면,
#include<stdio.h> #include<stdlib.h> #include<string.h> char buf[32]; intmain(int argc, char* argv[], char* envp[]){ if(argc<2){ printf("pass argv[1] a number\n"); return0; } int fd = atoi( argv[1] ) - 0x1234; int len = 0; len = read(fd, buf, 32); if(!strcmp("LETMEWIN\n", buf)){ printf("good job :)\n"); system("/bin/cat flag"); exit(0); } printf("learn about Linux file IO\n"); return0;
}
위와 같은 코드를 볼 수 있습니다.
우선 argc 가 2 미만일 때 “pass argv[1] a number”을 출력하고 종료하게 됩니다. 즉, fd 실행할 때 인자를 넘기라는 뜻입니다.
그 밑으로 main 함수의 인자로 받은 문자열을 숫자로 변환하여 (atoi 함수) 0x1234 를 빼, 그 값을 파일 디스크립터로 하여 buf 에 입력을 받아, 그 값을 문자열 “LETMEWIN”과 비교하여 buf 와 같을 때, “good job :)” 이라는 문장과 함께 flag 를 출력하는 코드라는 것을 알 수 있습니다.
표준입력으로 LETMEWIN 이라는 값을 buf 에 입력하기 위해선, 파일 디스크립터가 0 이 되어야 할 것임이 자명합니다.
문제를 풀기위한 모든것을 알게 되었습니다.
fd 를 실행할 때, 4660 을 인자로 넘기게 되면, 표준입력으로 buf 에 입력을 할 수 있게 될것이고, “LETMEWIN”을 buf 에 입력하게 되면 플래그를 출력할 것입니다.
Solve
fd@ubuntu:~$ ./fd 4660 LETMEWIN good job :) mommy! I think I know what a file descriptor is!! fd@ubuntu:~$