Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Archives
Today
Total
관리 메뉴

binee::

[Plaid CTF 2016] butterfly write up 본문

CTF

[Plaid CTF 2016] butterfly write up

binee108 2016. 4. 21. 20:25

plaid CTF를 3년만에 다시하게 되었다.

3년전에는 pwnable 문제를 하나도 못 건드렸는데

이번 대회는 혼자서 pwnable 두 문제 푼 것에 만족한다.

fixed point 문제도 접근 방법은 맞았는데 끈기있게 하지 않은 게 잘 못이었던 것 같다.


butterfly 문제는 감탄하면서 풀었다.

보통 buffer oveflow를 할 경우 ebp나 esp를 변조하거나

OOB를 사용하는 것이 일반적이다.

그런데 butterfly는 코드영역의 값을 수정해서 esp를 조작하는 아이디어를 낼 줄은 몰랐다.

덕분에 6시간 동안 hex-ray코드만 보다가 어셈블리 코드에서 코드영역의 점프문 값을 수정하려고 하다가 add esp, 48을 수정하면 eip를 변조 할 수 있다는 것을 뒤 늦게 알아버려서 정말 늦게 풀었다. 심지어 RTL로 풀려고 해서 코드영역 여기저기를 수정했다.

다른 풀이를 보니까 쉘코드로 풀었는데 나는 왜 그걸 생각 못 했는지 멍청하다ㅋㅋ

암튼 이번 Plaid CTF로 그 동안 열심히 공부했던 보람을 느낄 수 있는 계기가 되어서

나름 만족스럽다.



Binary 분석



butterfly 바이너리를 확인 해보면


butterfly: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=daad8fa88bfeef757675864191b0b162f8977515, not stripped


64bit elf 파일이고 특이한 점은 없다.




Program Logic 분석

.


아래는 main함수의 hex-xay 결과다.



간단히 요약하면

fgets로 50바이트를 입력 받는데, strtol를 통해서 숫자값이 정수로 변환된다.

정수 변환된 값은 나누기 8을하고 헥스 아래 3자리를 000으로한 값(0x4001234이면 0x4001000으로 바꾼다는 말)

그리고 정수값에 나누기 8을 한 값의 주소에 xor 연산을 수행하고 저장한다.

저장되는 값은 정수로 변환된 값에서 최하위 비트3개에 따라서

(1, 2, 4, 8, 16, 32, 64, 128)값 중에 하나와 기존에 있던 값을 xor한 값을 저장한다.


저장을 하고 난뒤 읽기 쓰기 실행 권한을 준 영역을

mprotect로 다시 쓰기 권한을 제거한다.


알고리즘은 심플하다.

그리고 이문제가 말하는 요구조건도 간단하다.

xor로 1바이트를 수정 할 수 있는데 이를 이용해서 어떻게 exploit 할 것인지를 말하고 있다.





Exploit



처음에는 어떻게 exploit을 할지 막막했다.

그것도 1바이트를 내가 원하는 값도 아니고 xor로 기존의 있는 값과 내가 내가 컨트롤 할 수 있는 값의 범위는 (1, 2, 4, 8, 16, 32, 64, 128) 중에 하나이다.


이 문제를 풀려면 hex-ray를 보면 안되고

어셈블리코드를 봐서 거기서 수정 할 것을 찾아야한다.



여기서 add rsp, 48h에서 48값을 바꿔서 에필로그의 rsp 정리를 방해하면

rsp의 값이 fgets에서 저장하는 스택의 위치로 갈 수 있는 것을 알았다.

바로 0x48과 (1, 2, 4, 8, 16, 32, 64, 128) 중에 fgets의 주소에 닫을 수 있는 값은

64값이 나왔다. 72 ^ 64 = 8 로

스택의 위치가 fgets를 통해서 저장한 스택에 위치한다.

따라서 fget로 return address 주소를 지정 해 줄 수 있었다.

return address 주소를 main으로 지정했고,

추가적으로 RTL을 하기위해서 puts의 PLT를 사용해서 GOT값을 leak했다.

그 과정에서 RTL chaing을 하기에 입력값이 부족해서 fgets의 50입력값을 더 늘리고

또 그럼에 따라 canary값이 훼손되서 canary가 저장되는 주소도 수정해서 canary도 우회했다.


그리고 최종적으로 RTL를 통해서 쉘을 획득했다.


exploit 코드는 아래와 같다.

'CTF' 카테고리의 다른 글

[TU CTF 2016] WoO & WoO2 & woO2-fixed write up  (0) 2016.05.21
[Plaid CTF 2016] unix_time_formatter write up  (0) 2016.04.23
[sCTF 2016] pwn3 write up  (0) 2016.04.21
[sCTF 2016] pwn2 write up  (0) 2016.04.19
[sCTF 2016] pwn1 write up  (0) 2016.04.19