ssh 주소를 따라 접속 후 ls 명령어를 통해 보면 fd, fd.c flag 총 세 가지의 파일이 있다.
fd.c 파일의 소스코드를 보자.
argc가 2 이상이 되어야 하고 buf라는 배열에 들어간 문자열이 LETMEWIN 과 같아야 flag가 실행되도록 되어 있다.
첫 번째로 걸려있는 조건, if문 안의 argc<2 라는 조건은 무엇일까?
main 함수의 파라미터를 보자. argc와 argv, envp가 존재한다. envp의 경우 이 문제를 푸는 데에는 필요하지 않다.(환경변수)
argc와 argv는 무엇일까? argc는 바로 main함수 즉 프로그램이 입력받는 인자의 개수이다. argv의 경우 입력된 인자들의 배열이라고 생각하면 된다.
만약 ./fd 1 2 3 4 이렇게 인자를 4개를 주어 fd라는 프로그램을 실행시켰다고 해 보자.
그렇다면 argc는 4 이고 argv[0]~argv[3]은 1 2 3 4 가 되어야 할까? 정답은 아니다.
argc와 argv에서 인식하는 파라미터는 파일 이름도 포함된다. 즉 프로그램 이름까지 인자는 총 5개가 되고 argv[0]는 프로그램 이름이 된다.
따라서 첫 번째 부터 준 인자는 argv[1] 부터 들어가게 된다.
결국 첫 번째 조건인 argc<2는 인자를 1개 이상 넣어주어야 한다는 것이다.
그리고 print문을 보면 숫자를 넣으라고 힌트도 제시하고 있다.
이후의 코드를 보자. fd라는 변수에 첫 번째로 들어온 인자를 atoi 함수로 정수로 변환한 뒤 0x1234를 빼 저장한다.
그 뒤 read 함수를 실행한다. 이 때 read 함수의 첫 번째 인자로 fd 변수가 들어가도록 되어 있다.
이것은 무엇을 의미할까? read 함수의 파라미터가 무엇인지 보자.
read 함수의 첫 번째 인자는 파일 디스크립터이다.
두 번째는 파일을 읽을 버퍼 주소, 마지막은 버퍼 크기를 의미한다.
즉 우리가 첫 번째로 입력하는 argv[1]은 0x1234와 연산되어 read 함수의 파일 디스크립터를 결정하게 된다.
파일 디스크립터에는 여러 가지가 있지만 우리는 표준 입력 파일 디스크립터를 read 함수의 인자로 넣어줄 것이다.
표준 입력을 의미하는 파일 디스크립터는 0이다.
파일 디스크립터로 들어갈 fd 변수를 0으로 만들어줘야 하기 때문에 argv[1] 즉 첫 번째 인자로 들어가야 할 값을 알 수 있다.
0x1234는 10진수로 변환하면 4660 이므로 ./fd 4660을 실행하면 read 함수가 실행되어 입력을 기다린다.
이후 buf에 입력된 값과 LETMEWIN 이라는 문자열을 비교하므로 LETMEWIN을 read 함수로 입력해주면 flag를 알 수 있다.