티스토리 뷰




[pwnable.kr] Toddler's Bottle - fd(1 pt) write-up



폰케알에 제일 첫 번째로 있는 문제입니다.


자기 자신 혼자서 풀라고 하네요.



ssh로 접속을 해보면,

간단한 pwnable.kr의 설명과 함께 접속이 됩니다.


ls 명령어로 어떤 파일이 존재하는지 확인 해 보겠습니다.



fd 실행파일과, fd.c 코드 파일, flag 파일이 존재합니다.



C 코드를 해석하기 앞서 문제의 힌트인 문제제목 fd (파일 디스크립터)에 대해서 알아야 합니다.


파일 디스크립터란, 리눅스에서 시스템으로부터 할당받은 파일이나 소켓에 부여 된 정수 입니다.


윈도우의 핸들 개념과 비슷하다고 합니다. 하지만 차이점은 1씩 순서대로 추가가 된다고 합니다.

파일 디스크립터는 0,1,2를 제외하고 3부터 정수를 사용합니다. 왜냐하면



0은 표준입력(stdin)-키보드 사용을 의미하고

1은 표준출력(stdout)- 모니터 출력을 의미하고

2는 표준에러를 의미하고 있기 때문입니다.




따라서 파일 디스크립터는 표준 입력(stdin), 표준 출력(stdout)을 표현할 수 있습니다.


이 fd문제는 이 특성을 이용한 문제입니다.


이제 코드 해석을 해보겠습니다.



32바이트 크기인 buf라는 전역변수가 선언이 되어있네요.


그리고 argv 인자가 2개보다 작을 경우 프로그램은 종료가 됩니다.


그리고 fd의 값은 atoi(argv[1]) - 0x1234; 한 값이네요.


여기서 표준라이브러리에 있는 atoi라는 함수를 알아야 합니다.


atoi함수는 문자열을 정수로 변환해주는 함수입니다.


따라서 문자열에 정수가 존재할 경우 그 문자열에 있는 숫자를 정수로 바꿔준다는 의미이죠.


다만 문자열에 정수가 아닌 A, B, C, D 와 같은 문자들이 있을 경우 정수로 변환을 하지 못하고 0으로 변환 합니다.


예를 들어, 문자열에 1231231a 가 있다면 atoi함수를 이용하면 1231231이 됩니다.


문자열에 asdf234234가 있다면 atoi함수를 이용하면 0이 됩니다.


그리고 read() 함수 인데요,


첫 번째 인자 값인 fd는 파일디스크립터 입니다.

두 번째 인자 값인 buf는 파일디스크립터가 지시하는 파일의 값을 buf에다가 저장한다는 것이죠.

세 번째 인자 값인 32는 파일디스크립터가 지시하는 파일의 값중 32바이트만 가져오겠다는 뜻입니다.


그리고 buf의 값이 LETMEWIN\n이여야 하네요.


자 그럼, 어느 정도 공격 구상이 되는군요.


파일 디스크립터를 0으로 해주면 buf의 값을 표준입력으로 적을 수 있겠네요.


하지만 fd = atoi(argv[1]) - 0x1234이므로


fd가 0이 되게 하려면 argv는 0x1234여야 합니다.


0x1234는

4660 입니다.


공격해보겠습니다.



예상대로 입력을 받습니다.


입력에 LETMEWIN을 써 줍니다. 개행문자는 안 써줘도 됩니다.



플래그가 나옵니다.


Comments