Pwnable.kr의 첫 번째 문제부터 차근차근 풀어보려 한다.. 가보자공 ~
첫 번째 문제답게 쉬운 편이다.
첫 번째 문제명은 fd로 File Descriptor와 관련된 문제임을 예상할 수 있었다 !
File Descriptor는 프로세스에서 실행되는 파일들의 목록을 관리하기 위해 사용되는 추상적인 값이다.
기본적으로 할당된 파일 디스크립터가 있는데, 아래와 같다.
fd | Described |
---|---|
0 | stdin(표준입력) |
1 | stdout(표준출력) |
2 | stderr(표준에러) |
이제 주어진 호스트와 포트로 서버에 접속해보면 아래와 같은 화면이 뜬다.
ls 명령어를 통해 파일의 목록을 확인해보면 fd와 fd의 소스코드, flag 파일 총 3개의 파일이 보인다...!
우선 fd를 실행시키면 argv[1]의 인자가 필요함을 알 수 있다.. 이제 fd.c의 코드를 살펴보자.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char buf[32];
int main(int argc, char* argv[], char* envp[]){
if(argc<2){
printf("pass argv[1] a number\n");
return 0;
}
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");
return 0;
}
코드는 간단하다. 우선 프로그램 실행 시 입력값을 같이 주면 입력값을 atoi 함수를 통해 정수로 바꾸고 해당 값에서 0x1234를 뺀 값을 fd에 저장한다.
read 함수의 첫 번째 인자로 0x1234를 뺀 fd를 저장하는데, read 함수의 첫 번째 인자는 int fd로 읽을 파일의 파일 디스크립터를 넣어준다.
보통 사용자로부터 입력을 받는 경우, read(0, buffer, bytes)의 형태로 사용된다.
즉, 사용자의 입력값에서 0x1234를 뺀 값이 0이 되어야 사용자의 입력값을 buffer에 저장하므로, fd 실행 시, 4660(0x1234)을 argv[1]에 넘겨주어 실행시키면, 아래의 read 함수를 통해 buf에 사용자가 입력한 값을 저장할 수 있다!
그 후는 더 간단하다. strcmp 함수의 경우, 첫 번째 인자와 두 번째 인자가 같을 경우 0을 리턴하고, 다를 경우 1을 리턴하는데 0을 만들어주면 밖의 !0 => 1이 되어 플래그를 획득할 수 있다!!
Flag 획득! "mommy! I think I know what a file descriptor is!!"