Lord of BOF_11_Golem


핵심 알고리즘
argv[1]을 받고, 이를 함수 인자로 넣는다.problem_child함수에서 인자로 받은argv[1]의 내용을 41바이트 복사한다.
주석의 힌트에서 알 수 있듯이, FPO를 이용하여 풀 수 있다. FPO는 Frame Pointer Overflow로, EBP 백업을 이용한 방법이다.

EBP 백업의 하위 1바이트를 조작하면(리틀 엔디안에서) EBP가 떠내려 간다. 이후 main 함수에서 return 하기 위해 leave 명령어를 실행하면 ESP는 (조작된)EBP가 가리키고 있던 위치를 가리키게 된다. 그리고 한 번 pop을 한 뒤, ret하게 된다.
따라서 조작한 EBP backup-4 위치에 원하는 return address를 넣으면 EIP를 조작할 수 있다.
실제로 problem_child 함수에서 어디까지 덮어 쓸 수 있는지 확인하였다. EBP 백업의 1바이트를 덮어쓴다는 것을 확인할 수 있다. EBP backup의 하위 1바이트를 조작하므로, 0xxxxxxYY 형태의 주소가 된다. YY부분에 조작된 값이 들어간다.(리틀 엔디안) 상위 3바이트는 조작되지 않으므로 기존 EBP backup인 스택 영역의 주소가 있다. 즉, 셸코드는 스택 영역을 이용해야 한다.
환경변수나 프로그램 이름 또는 인자 등을 이용해보려 했지만, 실험해보니 환경변수 위치는 주소의 앞자리가 달라 쓸 수 없었다. 지역변수와 가까운 쪽의 스택 주소를 이용해야 한다는 것을 알게 되었다.

따라서 strncpy가 일어나는, problem_child 함수에서 이용하는 버퍼를 이용하기로 하였다. 즉, main 함수 인자에 직접 넣기로 하였다. (주소와 셸 코드)
만들어둔 셸코드는 스택을 이용하기에 셸 코드 주소로는 main함수 인자 주소를 이용하였고, return address는 problem_child 함수에서 사용하는 버퍼를 이용하였다.
strncpy로 복사된 스택의 주소를 core파일을 이용하여 알아냈다. 값은 0xbffffaa4부터 시작된다. 첫 4바이트에는 새로운 ebp backup을, 두번째 4바이트에는 셸 코드의 주소를 넣어야 한다.
그리고 0xbffffacc위치에는 1바이트 오버플로우를 통해 이번 테스트에서 0x41414141를 입력한 위치(새로운 ebp backup 주소가 있는 위치)를 적어야 한다.

셸 코드의 위치를 알아보았다. main 함수 인자가 있는 쪽을 메모리에서 찾았다.

0xbffffc32부터 argv[1]이 있다는 것을 알 수 있다. 앞의 8바이트는 셸 코드가 아니므로, 8바이트 뒤인 0xbffffc3a를 이용한다.

페이로드를 완성하였다.

심볼릭 링크 파일을 이용하여 익스플로잇에 성공하였다. darkknight의 비밀번호는 new attacker 이다.
tags: writeup, pwnable, buffer overflow, stack overflow, memory corruption, elf file, linux, frame pointer overflow, c lang, x86asm