War Game/pwnable.kr

[Toddler's] fd

ReTeu 2023. 3. 28. 21:55

처음 포너블이라는 개념을 접했던 때가 2018년 여름방학 즈음이었던 걸로 기억한다. 당시에는 리눅스를 거의 다룰 줄 모르는 걸음마 단계였으니 도움을 받지 않고서는 한 두 문제 건드리기도 어려웠지만 이제는 다르지 않을까 하는 생각을 하며.. (믈론 요즘은 다들 드림핵에서 논다고는 하지만) 당시에는 감히 건들기 어려웠던 문제들에 오랜만에 다시 도전해본다.

 

응애 1레벨

 

집에 초대를 받았으면 먼저 신발을 벗고 들어가야겠다.

마찬가지로 남의 서버에 집들이를 갔다면 일단 뭐가 있는지부터 확인해주는게 예의일 것이다.

ls -la

flag 파일을 cat 명령어를 통해 읽어내면 될 것 같은데 우리가 접속한 계정으로는 읽기권한이 업기 때문에 권한 상승 없이는 flag 파일에 접근할 수가 없다. fd 파일에 대하여 set_uid가 fd_pwn으로 설정되어 있으므로 해당 파일(fd)이 실행되는 동안에는 마치 fd_pwn의 계정으로 코드를 실행하는 것처럼 권한 상승이 일어나게 된다. 그렇다면 fd에서 특정 조건을 만족하면 flag 파일의 내용을 출력해주도록 짜여있을 가능성이 높아보인다. 이제 한 번 까보도록 하자.

 

  system("/bin/cat flag") 를 통해 홈 디렉토리에 있는 flag를 읽어 출력되는 결과를 뿌려주는 코드가 들어있는 것을 확인할 수 있었다.

코드의 내용은 다음과 같이 정리할 수 있다.

  함수 실행시에 파라미터로 넘겨준 문자열(argv)에 대하여 atoi() 함수를 취하여 int형으로 바꾼 다음, 0x1234를 감하여 fd에 저장한다.

read() 함수를 통해 파일 포인터 fd가 가르키는 파일의 첫 32byte만큼을 읽어들여 buf에 저장한다. 또한 해당 함수의 리턴값으로서, 읽어들인 파일의 크기는 변수 len에 담긴다.

  최종적으로 strcmp()를 통해 buf에 담겨있는 값이 "LETMEWIN\n"이라면 flag 값을 읽어 화면에 출력한다.

 

  여기에서 힌트로 제시되었던 File Descriptor가 등장하게 된다. 리눅스 또는 유닉스에서는 모든 것을 파일이라고 부르는 단위로 관리하게 되는데, 프로세스에서 사용하기 위하여 메모리에 파일을 탑재할 때에 이 개별 파일들에 라벨링을 해주는 개념이라고 이해하면 된다. 이때, stdin은 0, stdout은 1, stderr는 2가 기본적으로 우선 할당된다고 한다.

 

  따라서 우리의 경우에는 이 fd 값을 0으로 만들어 stdin을 불러온 다음, "LETMEWIN\n"을 입력해주면 되는 것이다.

0x1234를 십진수로 표현하면 4660이므로, 프로그램을 실핼항 때에 매개변수로 4660을 넘겨주면 되겠다.

 

다음 문제들은 눈으로 보면서 풀기엔 다소 귀찮아서 아이패드에 필기하면서 설명해야할 것 같아 나중에 풀도록 해야겠다.