해킹/Write Up

RCTF 2017 RCalc WriteUp

NextLine 2017. 5. 23. 09:34

0. introduce

일단 rop가 좀 힘들었는데, 카나리를 덮을 수 있는걸 찾고 eip변조까지 하는데는 별로 시간이 안걸렸지만 익스짤때가 힘들었습니다. 익스에서 scanf와 printf를 잘 사용하지 않아서 어떻게할지 몰랐는데 대회끝나고 좀 더 생각을해보니 그 두개의 plt없이도 익스가 가능했습니다.  ret2dl_resolve를 삽질을 많이해서 rop chain에 그냥 puts_plt + 6을 넣어서 문제를 풀자고 생각했던것도 재미있었습니다.


1. binary

stack bufferoverflow문제이기 때문에 nx가 풀려있었으면 더 쉽게 풀 수 있었을꺼 같다.


- 가장 처음에 각각 한개의 chunk를 0x6020f0과 0x6020f8에 할당해서 넣어준다.


- 아래와 같은 방식의 카나리가 모든 함수에 적용되어있다. 

- 그래서 위 함수의 return값을 함수내 변수에 넣고 마지막에 bss영역의 카나리와 검사하여 값이 변조됬으면 "NO!"라는 메세지와 함께 종료된다.


- 처음에 scanf("%s")로 이름을 입력받는다.

- 두개의 정수를 입력받아 add, sub, mod, multi 연산을 해주고 결과값을 저장할것인지 물어본다.


- 값을 저장하는 루틴은 다음과 같다.


2. Vulnerability

첫번째 이름을 입력받는란에서 scanf("%s") 때문에 bof취약점이 발생한다.


3. Exploit

카나리값이 저장되는곳과 결과값을 저장하는 위치를 확인해보면 다음과같이 차이가 별로 안나는것을 확인할 수 있다.

그래서 계속해서 값을 저장하면 결국에는 카나리값을 덮어써서 카나리를 우회할 수 있게된다. 그리고 처음에 rop chain을 짜놓고 rop로 익스플로잇하면 된다.

익스할때 주의할점은 scanf("%s")로 입력을 받는것이기때문에 주소값을 쓸때 0x20을 쓸 수 없다. 그러므로 puts_plt 인 0x400820를 못쓰고, got영역에도 __libc_start_main : 0x601FF0 / __gmon_start :  0x601FF8 두개밖에 ropchain에 쓸 수 없다.

그래서 나는 익스를할때 puts_plt + 6을 통해 libc_start_main의 got를 leak하고 ebp를 조작한 후  맨 처음에 scanf("%s")로 돌아가 puts_got를 oneshot가젯으로 덮어씌워서 쉘을 얻었다.


Full Exploit Code

(https://github.com/LYoungJoo/CTF-Write-Up/blob/master/2017_Rctf%20Write%20Up/RCalc.py)


FLAG