[FTZ] level 16 풀이 <BOF-함수 덮기>
ID : level16
PW : about to cause mass
1.
새로운 파일인 attackme.c가 있다. 읽기 권한이 없어서 읽을 수가 없다.
그냥 attackme의 소스코드인 것 같으므로 hint파일을 읽어주자.
main함수 부분만 분석해 보도록 하겠다.
main(){
int crap;
void(*call)()=printit; //call 포인터 함수에 printit 함수를 저장 (call 선언, printit로 초기화)
chat buf[20];
fgets(buf,48,stdin); //48바이트 만큼의 입력을 buf변수에 받음
call(); //call 함수 호출 = printit 함수 호출
}
지금까지와는 새로운 유형의 오버플로우 문제인 것 같다. 문제 해결은 다음과 같다.
- buf[20] 에서 부터 *call 까지의 거리 알아보기
- shell 함수의 주소 가져오기
- *call 위치에 shell 함수의 주소를 덮어 씌우는 페이로드 제작하기
(call 실행되면 printit 실행되는건데 shell로 덮어버려. 물론 call이 포인터변수니까 shell함수의 주소를 넣어줘야겠지)
먼저 buf[20] 에서 부터 *call 까지의 거리를 확인해보자!
2.
attackme 파일을 디버깅 했다.
????main+6은 뭐지?
<main+24>부분을 보면, buf 에서부터 ebp까지의 거리가 56임을 알 수 있다.
<main+36>부분을 보면, call 에서부터 ebp까지의 거리가 16임을 알 수 있다.
따라서 buf에서 call까지의 거리 = 40.
이건 어떻게 구하는 건지 모르겠는데 몰라도 풀어지긴 한다.
예상되는 메모리 구조:
buf(20) + dummy(20) + *call(4) + dummy(4) + crap(4) + dummy(4) + SFP(4) + RET(4) = 64 (0x38+8)
메모리 구조를 파악했으니 shell 함수의 주소를 구하자.
gdb에는 프로그램에 저장된 함수나 새롭게 선언된 함수의 이름으로 그의 주소를 출력해주는 기능이 있다.
- p [함수이름] : 해당 함수의 주소 출력
shell 함수의 주소를 구했다.
이제 페이로드를 짤 수 있겠다.
페이로드
(python -c 'print "\x90"40+"\xd0\x84\x04\x08"';cat)|./attackme
앞의 버퍼(20)와 더미(20)을 NOP 40개로 채워주고, 바로 그 다음에 위치하는 call포인터 변수에 쉘 함수의 주소값을 넣어줬다.
이로써 레벨 16을 클리어했다.
(2020.02에 작성한 글을 가져왔습니다.)