Pwnablekr_Toddlers Bottle_bof

링크에 접속하면 코드와 ELF 실행 파일을 얻을 수 있다. 문제에서 nc를 이용하여 접속하기를 요구하고 있다.

C언어 코드다. 핵심 알고리즘은 다음과 같다.
func에 인자로 0xdeadbeef를 넣고 호출func에서,gets로 버퍼에 입력값을 받음func에서,func의 인자가 0xcafebabe인지 확인
함수 인자로 0xdeadbeef를 넣는데, 문제의 조건은 인자가 0xcafebabe이기를 요구한다. 이는 어떻게든 스택에 있는 함수 인자 값을 변형해야 한다는 의미이다.
주목할 점은 gets 함수를 사용한다는 점이다. 이 함수는 버퍼의 크기에 대한 정보를 받지 않기 때문에 오버플로우를 일으킬 수 있다. 인자로 스택의 주소를 넣어주었기 때문에 스택 오버플로우를 일으켜 인자가 있는 부분의 값을 바꿔줄 수 있다.
하지만 코드만으로는 정확한 스택 구조를 알 수 없다. ELF 실행 파일에서 직접 디스어셈블리 코드를 보아야 한다. IDA를 이용해 실행 파일을 디스어셈블 했다. 그 중 func 코드만 떼어냈다.

먼저 push ebp 코드로 스택에 ebp를 백업한 값이 들어간다는 것을 알 수 있다. sub 48h를 보아 지역변수를 위한 스택을 0x48만큼 확보했다는 것을 알 수 있다. 그리고 gets를 호출하기 전 ebp-0x2c 주소를 인자로 준다는 것을 알 수 있다. 마지막으로, ebp+8과 0xcafebabe를 비교하는 코드를 통해 ebp+8의 위치에 인자가 있다는 것을 알 수 있다.
오른쪽은 스택을 그림으로 나타낸 것이다.

함수 인자를 바꾸고 싶으므로, 함수 인자 위치까지 가기 위한 더미값을 넣는다. 그리고 함수 인자가 있는 위치에 0xcafebabe 를 넣어준다. 이 때, 리틀엔디안에 주의한다.
계산해 보면 더미값은 52바이트를 입력하고, 그 후 0xbe 0xba 0xfe 0xca를 넣어주어야 한다.

파이썬과 netcat을 이용하여 입력값을 주었다. 셸이 실행되면 ls 명령어로 flag 파일을 찾고, cat 명령어를 이용하여 읽는다. nc는 cat 명령어의 네트워크 버전이다. cat 명령어는 인자로 준 파일의 내용을 간단히 읽거나 쓸 수 있는 명령어이다. stdin을 읽고, stdout으로 쓴다.
flag는 daddy, I just pwned a buFFer :) 이다.
tags: writeup, pwnable, elf file, linux, c lang, memory corruption, stack overflow, x86asm