[Pwnable.kr] fd write up
포너블.kr을 풀어야지 생각만 하다가 이제서야 푸네요
문제는 이렇습니다.
파일 디스크립터가 무엇인지 묻는걸로 봐선 이문제는 파일디스크립터로 뭔가 하는문제인거 같습니다.
그러고보니 문제 제목도 fd 였네요.
fd@pwnable.kr -p 2222 로 접속을하면 위와같이 나옵니다.
접속을 했으면 가장먼저 해야되는게 있죠?
ls 로 파일이 뭐가있는지 봤더니 fd, fd.c, flag 이렇게 있네요.
cat flag 하니까 Permission denied 가 떠서 chmod로 권한을 줘볼려고 했지만 그렇게 하는건 아닌것 같습니다.
결국엔 fd.c를 열어보기로 했습니다.
코드를 해석해보자면
// argc 는 파일에 인자로 전달된 파라미터의 갯수를 저장하고 있습니다. //
if(argc<2){ // 즉, 해당파일에 전달된 인자 갯수가 2개 미만일때
printf("pass argv[1] a number\n"); // 인자값을 전달하라는 메시지를 출력하고있네요
return 0;
}
main 에서 선언된 argc는 주석에 달린 내용처럼 해당 파일에 전달된 인자값의 갯수를 저장하고있습니다.
~$ ./fd hi i am yoowOn
이런식으로 쉘에 입력을 하면
argc = 5 ('./fd', 'hi', 'i', 'am', 'yoowOn')
argv[0] = ./fd
argv[1] = hi
argv[2] = i
argv[3] = am
argv[4] = yoowOn
으로 인자값이 들어가게 됩니다.
argv에는 공백을 기준으로 인자가 들어갑니다.
즉, 실제로 프로그램에 넘겨주는 인자값은 argv[1]에 들어있다는 뜻이죠.
int fd = atoi( argv[1] ) - 0x1234;
atoi 함수는 문자열을 정수로 변환해주는 함수인데요, argv[1]에 있는값을 정수로 변환하라는 의미입니다.
0x1234 는 헥스값인데요, 10진수로 변환을 하면 4660 이라는 정수가 나오게 됩니다.
len = read(fd, buf, 32);
여기서 read 함수는 파일을 읽는 함수입니다.
fd = 파일 디스크립터
buf = 읽어들인 파일을 저장할 공간
32 = 해당 크기(여기선 32바이트) 만큼 읽어옴.
반환값은 읽어들인 파일의 길이입니다.
그래서 len 에는 read에서 읽은 파일의 길이가 저장됩니다.
if(!strcmp("LETMEWIN\n", buf))
그리고나서 buf (32바이트 만큼 읽어들인 파일) 이랑 "LETMEWIN" 이랑 비교해서 TRUE 라면 Flag 를 출력해주네요.
여기서 볼것은 read 함수입니다.
read 함수에 나오는 fd가 파일의 디스크립터인데요
Unix OS 에서 네트워크 소켓과 같은 파일이나 기타 입력 및 출력 리소스에 엑세스하는 데 사용되는 추상적 표현입니다.
0, 1, 2가 고정되어있음
쉽게 설명해서
0 = input
1 = output
2 = error
입니다.
그럼 다시 문제로 돌아와서....
파일에서 특정 값을 읽어와서 buf에 저장해야되니 해당 파일에 참조를 해야합니다.
그럼 fd 값은 0이 되어야하구요,
int fd = atoi( argv[1] ) - 0x1234;
다시 여기로 돌아와서 fd 값이 0이 되어야 한다고 했고, 0x1234 는 10진수로 4660 이니까
저희는 argv[1] 에 4660의 값을 넣어줘야 합니다.
$ ./fd 4660
이런식으로 인자값을 주면 입력창이 나오는데 여기서 LETMEWIN 을 입력하면 Flag가 출력이 됩니다.