20199124 2019-2020-2 《网络攻防实践》第10周作业

20199124 2019-2020-2 《网络攻防实践》第10周作业

本次作业属于哪个课程 《网络攻防实践》
这个作业要求在哪里 第十次作业 软件安全攻防——缓冲区溢出和Shellcode
我在这个课程的目标是 学习缓冲区溢出原理以及shellcode的编写
这个作业在哪个具体方面帮助我实现目标 分析shellcode
作业正文 见下文1、2、3、4部分
其他参考文献

一、实践内容

1.1 软件安全


​ 安全漏洞的定义为:在系统安全流程、设计、实现或内部控制中所存在的缺陷或弱点,能够被攻击者所利用并导致安全侵害或对系统安全策略的违反。软件安全漏洞的定义相似,只不过存在的范围是软件,软件安全漏洞是是目前最常见,也是影响范围最大的安全漏洞类型。

​ 软件安全漏洞对威胁:威胁信息安全、造成巨大经济损失、危害生命安全。

​ 软件安全的“困境三要素"(The Trinity of Trouble)是复杂性(Complexity)、可扩展性(Extensibility)和连通性(Connectivity), 软件的这三个要素共同作用,使得软件的安全风险管理成为了一个巨大的挑战,从而很难根除安全漏洞。

​ 软件安全漏洞从技术上主要包括内存安全迁规类漏洞、输入验证类安全漏洞、竞争条件类缺陷、权限混淆与提升类漏洞。其中著名的安全漏洞有缓冲区溢出漏洞、Web应用程序安全漏洞、目录遍历、信息泄露、由畸形输入导致的拒绝服务、符号链接问题、格式化字符串以及密码学缺陷(Crypt Errors)等。


1.2 缓冲区溢出


1.2.1 基本概念

​ 缓冲区溢出是指在计算机程序向特定缓冲区内填充数据时,数据长度超出了缓冲区本身的容量,导致外溢数据覆盖了相邻内存空间的合法数据,从而改变程序执行流程破坏系统运行完整性。所以一般情况下,应该对进入缓冲区的数据长度进行检查,防止溢出。

​ 缓冲区溢出攻击发生的根本原因:计算机程序的数据和指令都在同一内存中进行存储,而没有严格的分离。这一缺陷使得攻击者可以将输入的数据,通过利用缓冲区溢出漏洞,覆盖修改程序在内存空间中与数据区相邻存储的关键指令,从而达到使程序执行恶意注入指令的攻击目的。

1.2.2 背景知识

编译器与调试器的使用:类Unix平台的编译器GCC与调试器GDB, Windows 平台的集成开发环境Visual Studio、VS.Net。

汇编语言:重点关注IA32汇编语言。熟悉常用的寄存器(通用寄存器、段寄存器、控制寄存器和其他寄存器);熟悉一些常用汇编指令的含义类UNIX平台下,通常使用AT&T汇编格式,在DOS/Windows平台下,则主要使用Intel汇编格式。

进程内存管理

​ Linux操作系统中,程序在执行的过程如下:

系统创建虚拟的内存地址空间——将可执行程序加载到新创建的内存空间中——初始化“栈”(Stack)和“堆”——按照程序逻辑执行.text 中的指令——保存和读取“堆”和“栈”中的数据

​ Windows操作系统的进程内存空间布局如图所示

img

函数调用过程:栈溢出攻击就是针对函数调用过程中返回地址在栈中的存储位置,进行缓冲区溢出,从而改写返回地址,达到让处理器指令寄存器跳转至攻击者指定位置执行恶意代码的目的。程序进行函数调用的过程有三个步骤:调用、序言、返回。

1.2.3 缓冲区溢出攻击原理

​ 缓冲区溢出漏洞根据缓冲区在进程内存空间中的位置不同,又分为栈溢出、堆溢出和内核溢出,都是由于其上的缓冲区变量缺乏边界保护而遭受溢出攻击。

​ 缓冲区溢出攻击过程如下:

1.攻击者要定位缓冲区溢出要覆盖和修改的敏感位置,已经敏感位置修改为什么
2.攻击者确定漏洞利用点
3.编写shellcode
4.在攻击目标上执行程序,缓冲区溢出敏感位置数据被修改
5.程序跳到shellcode起始地址,执行shellcode
6.为攻击者开启一个命令行shell

1.3 Linux平台上的栈溢出与Shellcode


1.3.1栈溢出攻击技术

·NSR模式

​ NSR模式主要适用于被溢出的缓冲区变量比较大,足以容纳Shellcode的情况,其攻击数据从低地址到高地址的构造方式是一堆Nop指令(即空操作指令)之后填充Shellcodc, 再加上一些期望覆盖RET返回地址的跳转地址,从而构成f NSR攻击数据缓冲区。

·RNS模式

​ 一般用于被溢出的变量比较小,不足于容纳Shellcode的情况。攻击数据从低地址到高地址的构造方式是首先填充一些期望覆盖RET返回地址的跳转地址,然后是一堆Nop指令填充出“着陆区”,最后再是 Shellcodeo在溢出攻击之后,攻击数据将在RET区段即溢出了目标漏洞程序的小缓冲区, 并覆盖了栈中的返回地址,然后跳转令Nop指令所构成的“着陆区”,并最终执行Shellcode。

·RS模式

​ 在这种模式下能够精确地定位出Shellcode在目标漏洞程序进程空间中的起始地址, 无须Nop 空指令。这种模式是将Shellcode放置在目标漏洞程序执行时的环境变量中,由于环境变量是位于Linux进程空间的栈底位置,因而不会受到各种变星内存分配与对齐因素的影响,其位置是固定的。

前两种模式既适用于本地攻击也适用于远程攻击,第三种模式只适用于远程攻击。

1.3.2 Shellcode实现技术

Linux本地Shellcode实现机制

  • 先用高级编程语言,通常用C,来编写Shellcode程序;
  • 编译并反汇编调试这个Shellcode程序;
  • 从汇编语言代码级别分析程序执行流程;
  • 整理生成的汇编代码,尽量减小它的体积并使它可注入,并可通过嵌入C语言进 行运行测试和调试;
  • 提取汇编代码所对应的opcode二进制指令,创建Shellcode指令数组。

Linux远程Shellcode实现机制

​ 远程Shellcode的实现原理与本地Shellcode完全一致,但是需要让攻击目标程序创建socket监听指定的端口等待客户端连接,启动一个命令行Shell,并将命令行的输入输出与socket绑定,这样攻击者就可以通过socket 客户端连接目标程序所在主机的开放端口,与服务端socket建立起通信通道,并获得远程访问Shell。


1.4 Windows平台上的栈溢出与Shellcode


1.4.1栈溢出攻击技术

​ 由于Windows平台于Linux平台在废弃栈的处理方式、进程内存空间的布局、系统功能调用的实现方式上存在差异,所以实现栈溢出攻击的原理也大不相同。

​ 使用系统核心DLL中的“JMP ESP”指令来完成控制流程的跳转是很经典的方式。在函数调用结束装载返回地址的时刻,ESP指针恰好是指向了注入攻击缓冲区数据中的Nop指令和Shellcode,那么如果我们将返回地址改写为一个指向“JMPESP” 操作指令的高位地址,使得这个地址中不含空字节(也就不会被字符串操作函数所截断),那我们就可以构造出一段可以成功实施栈溢出的攻击数据,因为目标程序在函数调用完成执行RET指令时,就会将在返回地址位置改写的指令地址装载入EIP寄存器,并跳转至该地址继续执行,而这个地址指向的指令是“JMPESP”,同时ESP寄存器又恰恰指向的是栈上Nop和Shellcode的位置,因此这条指令会帮助我们将程序流程返回到栈上,转而执行所注入的Shellcode。

1.4.2 Shellcode实现技术

Windows本地Shellcode

​ Windows 32 的系统API 中提供了system()函数调用,可以用于启动指定程序或运行特定命令,在调用system (“command.com”)之后即可启动命令行程序。使用system()函数实现程序的跳转。

​ 目标程序进程空间中并不一定拥有system。为了使用这个函数,我们可以釆用了硬编码的system函数地址;而Kernel32.dll中的LoadLibrary和GetProcAddress()函数提供了运行时刻加载指定动态链接库,及查询指定函数加载地址的功能通常使用这两个API接口函数来加载并查询其他所需函数地址。

Windows 远程 Shellcode

  • 创建一个服务器端socket,并在指定的端口上监听;
  • 通过accept()接受客户端的网络连接;
  • 创建子进程,运行“cmd.exe”,启动命令行;
  • 创建两个管道,命令管道将服务器端socket接收(rccv)到的客户端通过网络输 入的执行命令,连接至cmd.exe的标准输入;然后输出管道将cmd.exe的标准输出连接至 服务器端socket的发送(send),通过网络将运行结果反馈给客户端。

1.5 堆溢出攻击


​ 堆中没有可以直接覆盖并修改指令寄存器指针的返回地址,相较于栈溢出攻击难度更大。因此,堆溢出往往需要利用在堆中一些会影响程序执行流程的关键变量,如函数指针、C++类对象中的虚函数表,或者挖掘出堆中进行数据操作时可能存在的向指定内存地址改写内容的漏洞机会。

函数指针改写:进行函数指针改写攻击需要被溢出的缓冲区临近全局函数指针存储地址,且在其低地址方向。攻击者只要能够将该函数指针指向恶意构造的Shellcode入口地址

Linux下堆管理glibc库free()函数本身漏洞:free()函数在处理内存块回收时,需要将已被释放的空闲块和与之相邻的空闲块进行合并,因此将会把符合条件的空闲块从Bin 链表中unlink摘出来,合并之后再将新的空闲块插回链表中。


1.6 缓冲区溢出攻击的防御技术


  1. 解决缓冲区溢出攻击最根本的办法是编写正确的、不存在缓冲区溢出安全漏洞的软件代码。但这是很难的,码农常常会使用一些漏洞挖掘工具,自行测试软件,十软件变得更安全;其次在编译器上引入针对缓冲区的边界保护检查机制。
  2. 允许溢出发生,但对可能影响到程序流程的关键数据结构实施严密的安全保护,不让程序改变其执行流程,从而阻断溢出攻击
  3. 通过堆栈不可执行限制来防御缓冲区溢出攻击
原文地址:https://www.cnblogs.com/2499mly/p/12833639.html