64位Ubuntu系统下ROP攻击
64位Ubuntu系统下ROP攻击
基础知识
ROP攻击
- ROP全称为Retrun-oriented Programmming(面向返回的编程)是一种新型的基于代码复用技术的攻击,攻击者从已有的库或可执行文件中提取指令片段,构建恶意代码。
- ROP攻击同缓冲区溢出攻击,格式化字符串漏洞攻击不同,是一种全新的攻击方式,它利用代码复用技术。
- ROP的核心思想:攻击者扫描已有的动态链接库和可执行文件,提取出可以利用的指令片段(gadget),这些指令片段均以ret指令结尾,即用ret指令实现指令片段执行流的衔接。操作系统通过栈来进行函数的调用和返回。函数的调用和返回就是通过压栈和出栈来实现的。每个程序都会维护一个程序运行栈,栈为所有函数共享,每次函数调用,系统会分配一个栈桢给当前被调用函数,用于参数的传递、局部变量的维护、返回地址的填入等。栈帧是程序运行栈的一部分 ,在Linux中 ,通过%esp和 %ebp寄存器维护栈顶指针和栈帧的起始地址 ,%eip是程序计数器寄存器。而ROP攻击则是利用以ret结尾的程序片段 ,操作这些栈相关寄存器,控制程的流程,执行相应的gadget,实施攻击者预设目标 。ROP不同于retum-to-libc攻击之处在于,R0P攻击以ret指令结尾的函数代码片段 ,而不是整个函数本身去完成预定的操作。从广义角度讲 ,return-to-libc攻击是ROP攻的特例。最初ROP攻击实现在x86体系结构下,随后扩展到各种体系结构.。与以往攻击技术不同的是,ROP恶意代码不包含任何指令,将自己的恶意代码隐藏在正常代码中。因而,它可以绕过W⊕X的防御技术。
实验环境
- 虚拟机系统:Ubuntu 12.04(64位)

前期准备
- 根据X86_64 ABI的调用约定,函数间传递参数不再以压栈的方式,而是以寄存器方式传递参数,前面6个参数依次以rdi, rsi, rdx, rcx, r8和r9寄存来传递。在Linux系统,64位架构只使用48位的虚拟地址空间,也即每个地址高16位全部为0,因此在64位系统上,地址已天然零化,ret2libc攻击似乎没有了用武之地,在ret2libc的基础上我们采用ROP攻击方法。
- 我们现在先假设栈没有可执行属性,那么需要自己编写一个shell来执行,考虑通过execve系统调用来实现。我们直接将汇编代码放在shell.c文件中:
int main() {
asm("\
needle0: jmp there\n\
here: pop %rdi\n\
xor %rax, %rax\n\
movb $0x3b, %al\n\
xor %rsi, %rsi\n\
xor %rdx, %rdx\n\
syscall\n\
there: call here\n\
.string \"/bin/sh\"\n\
needle1: .octa 0xdeadbeef\n\
");
}
- 无论我们的代码在内存中的哪个地方结束,call-pop指令都将使用“/bin/sh\”字符串的地址加载rdi寄存器,接下来编译运行shell.c文件,成功获得了一个shell:

实践过程
我们先提取要注入的payload,查看机器代码:

在64位系统上,代码段通常位于0x400000,在该二进制文件中,我们的代码位于0x4b8的偏移量处,并在偏移量0x4d5之前完成,共有29个字节:

查看我们的shellcode:

接着,我们看一个被攻击的简单代码victim.c:
#include <stdio.h>
int main() {
char name[64];
puts("What's your name?");
gets(name);
printf("Hello, %s!\n", name);
return 0;
}
- 在Ubuntu系统上,有三种对策来保护堆栈,第一种是SSP,又名ProPolice,编译器重新排列堆栈布局,使缓冲区溢出不太危险,并插入运行时堆栈完整性检查;第二种是可执行空间保护(NX),当尝试在堆栈中执行代码时会导致分段错误;第三种地址空间布局随机化(ASLR),堆栈的位置每次运行都是随机的,所以即使我们可以覆盖返回地址,也不知道该放在哪里。
三种攻击尝试
第一种尝试
我们可以想办法绕过这些方法,使用gcc的-fno-stack-protector选项禁用堆栈保护,编译victim,然后使用execstack -s指令禁用可执行文件空间保护,发现提示没有安装:

安装完成之后,禁用可执行文件空间保护,然后在运行文件时禁用ASLR:

我们再在原victim.c代码的基础上加上一句
printf("%p\n", name);,打印缓冲区的位置,然后再编译运行:

后面的过程中应该也会出现该缓冲区的地址,我们让它以小端法显示:

这个时候我们攻击我们的victim.c程序,可以看到攻击成功:

第二种尝试
接着,我们再通过一个例子来看看打补丁的重要性,在以前,我们可以通过查看/proc/pid/stat来读取任何进程的ESP注册表,但是这种漏洞很早就被修复了,我们假装目前在没有打补丁的系统上,先查看所有进程的esp:

我们先运行禁用了ASLR的victim程序:

再在另一个终端窗口查看victim程序的esp:

因此,当程序正在等待用户输入时,它的堆栈指针0x7fffffece8,我们计算从这个指针到名称缓冲区的距离:

现在重新运行启用了ASLR的victim程序:

我们查找victim进程的esp指针,然后添加上偏移量,就是上一步中运行victim程序的缓冲区地址:

接着用管道命令来进行演示:

在另一个终端中输入如下命令:

可以看到攻击成功,获取到了shell:

第三种尝试
先通过运行execstack -c指令重新启动可执行空间保护,此外,在ROP攻击中代码片段从可执行内存中挑选出来,例如,它们可能是libc的片段,所以我们还要通过locate指令找到libc的位置,如图所示,我们选择第一个:

我们希望执行
pop %rdi retq,而指向“/bin/sh”的指针位于堆栈的顶部。这将在推进堆栈指针之前将指针分配给rdi,相应的机器代码是两个字节的序列0x5f 0xc3,它应该在libc的某处发生。但是没有Linux工具能够直接在文件中搜索给定的字节序列,所以我们可以用下面的grep指令来实现检索:

在ROP中,以RET结尾的一系列指令称为gadget,如果我们用以下顺序覆盖返回地址:libc的地址+ 0x22a12;“/bin/sh”的地址;libc的system()函数的地址,然后在执行下一个ret指令时,程序将弹出“/bin/sh”的地址到rdi,然后跳转到系统函数,我们就可以达到我们的目的。先输入如下指令运行禁用了ASLR的victim程序:

再在另一个终端中输入如下指令:

我们可以看到,libc被加载到从0x7ffff7a1a000开始的内存中,因此gadget地址是0x7ffff7a1a000 + 0x22a12,“/bin/sh”的地址我们之前已经找到了,是0x7fffffffed40,最后我们通过下面的指令来找libc的system()函数的地址:

我们可以得到libc的system()函数的地址是0x7ffff7a1a000 + 0x45730,最后将它们放到一起,成功得到了shell:

64位Ubuntu系统下ROP攻击的更多相关文章
- premake 在64位Ubuntu系统下编译32位GCC程序
首先,要安装GCC 4.8, 参考前文:Ubuntu 12.04 & 13.04 安装 GCC4.8.1 其中,重点是安装multilib apt-get install gcc-4.8-mu ...
- 64位Win8系统下安装Oracle12c
经过3个小时的折腾,终于在64位win8系统下成功安装了Oracle 12c.这篇文章主要把安装过程中遇到的一些问题总结一下,以便帮助后来人参考. 首先我把我的机器的主要配制情况列举出来: 1. 系统 ...
- 在64位Ubuntu系统上安装32位程序包
在64位Ubuntu系统上安装32位的程序包 $sudo apt-get install package_name:i386 例如: $sudo apt-get install openjdk-7-j ...
- 64位Windows系统下32位应用程序连接MySql
1.首先得安装“Connector/ODBC”,就是Mysql的ODBC驱动,这个是与应用程序相关的,而不是与操作系统相关的,也就是说,不管你的系统是x64还是x86,只要你的应用程序是x86的那么, ...
- 64位Win7系统下vs2010调试无法连接oracle
64位win7系统的Program Files (x86)路径中有括号,oracle不认识这样的路径,所以就出现不能连接数据库的问题.所以我们可以将vs2010的内部调试web服务器WebDev.We ...
- 64位Win7系统下vs2010调试无法连接oracle解决办法
具体的解决办法如下: 1.先将WebDev.WebServer20.EXE和WebDev.WebServer40.EXE文件从Program Files (x86)目录中拷贝出来放到c:\dev目录中 ...
- 64位debian系统下安装inodeClient
linux下的inodeClient下载: 链接:http://pan.baidu.com/s/1jIoX6Zk 密码:vnws 里面包括一份说明书,一个32位的,一个64位的文件: 对于64位的客户 ...
- centos 64位linux系统下安装appt命令
首先,安装apktool包 1. wget http://android-apktool.googlecode.com/files/apktool-install-linux-r04-brut1.ta ...
- 关于64位Windows7系统下INF的安装问题
原文 http://bbs.csdn.net/topics/360262492 我的电脑 ——>属性 ——>设备管理器 ——>操作 ——>添加过时硬件 但是,64位系统上报“指 ...
随机推荐
- 百度之星-day2-1004-二分答案
由于序列有序,求其中一个最优解,二分答案即可,注意二分时上边界满足才保存 #include<iostream> #include<stdio.h> #include<st ...
- 终于做完了这个pj
首先要说这个博客网站实在是功能太弱!不知道为什么还要每次写博客.直接交作业不好吗- -b 1.估计时间: 看见这个任务就觉得很难啊,估计装vs2012就得半天,然后上学期选修的c++基本上都忘光了,本 ...
- M1阶段个人总结
经过4周的开发,我们团队的第一阶段已经结束了. 这一个月来我由于其他事情较多,所以开发的工作主要交给了另外的三名同学. 我主要负责制定代码规范和工程结构,通过github来跟进项目进度,提供一些技术支 ...
- 20135316Linux内核学习笔记第六周
20135316王剑桥<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC 1000029000 一.进程控制块PCB--task_ ...
- Tor源码阅读与改造(一)
0x00 前言 由于公司需求,需要掌握洋葱网络的整体架构和部分详细实现细节,并对Tor进行针对性的改造.在查询Tor官方相关文档和google各种网站后,得到的信息仍无法达到目的,所以便开始了阅读To ...
- [IOI2018]狼人——kruskal重构树+可持久化线段树
题目链接: IOI2018werewolf 题目大意:给出一张$n$个点$m$条边的无向图,点和边可重复经过,一个狼人初始为人形,有$q$次询问,每次询问要求人形态只能处于编号不小于$L$的点,狼形态 ...
- BZOJ1131[POI2008]Sta——树形DP
题目描述 给出一个N个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大 输入 给出一个数字N,代表有N个点.N<=1000000 下面N-1条边. 输出 输出你所找到的点,如果具有 ...
- BZOJ2795&2890&3647[Poi2012]A Horrible Poem——hash
题目描述 给出一个由小写英文字母组成的字符串S,再给出q个询问,要求回答S某个子串的最短循环节.如果字符串B是字符串A的循环节,那么A可以由B重复若干次得到. 输入 第一行一个正整数n (n<= ...
- HDU1711-KMP-水题
纯KMP,入门题,不知道读入挂加朴素匹配能不能过 #include <cstdio> #include <algorithm> #include <cstring> ...
- Pairs Forming LCM LightOJ - 1236 (算术基本定理)
题意: 就是求1-n中有多少对i 和 j 的最小公倍数为n (i <= j) 解析: 而这题,我们假设( a , b ) = n ,那么: n=pk11pk22⋯pkss, a=pd11pd2 ...