RCTF 2017 RCalc WriteUp
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