漏洞渗透模块
接下来你将会学习到渗透模块的开发,在这个过程还将涉及如何利用Metasploit的内置功能来加快开发的过程。我们将会介绍各种漏洞,并会尝试使用各种方法和途径去对这些漏洞进行渗透。除此之外,重点将放在渗透模块的开发上。我们还会涵盖各种用来辅助Metasploit编写渗透模块的工具。不过,掌握计算机架构是编写渗透模块的一个重要前提条件。如果对计算机的架构一窍不通,将无法理解这一切到底是如何运作的。因此,我们首先学习计算机的架构和开发渗透模块的基本要素。
一、渗透的基础部分
首先了解一下编写渗透模块所必需的基础部分。
下列术语都是基于硬件特性、软件特性以及渗透的角度。
寄存器(register):这是处理器上用来存储信息的一块区域。此外,处理器利用寄存器来处理进程执行、内存操作、API调用等。
x86:这是一个主要应用在Intel平台上的系统架构,通常是32位操作系统,而x64是指64位操作系统。
汇编语言(assembly language):这是一种低级编程语言。汇编语言操作起来十分简单。但是对汇编语言的阅读或者维护工作则是一块难啃的骨头。
缓冲区(buffer):缓冲区指的是程序中用来存储数据的一段固定的内存空间。通常它会以栈或者堆的形式保存数据,这取决于其所使用的存储空间类型。
调试器(debugger):调试器允许对可执行文件进行逐步分析,包括对存储器、寄存器、栈等设备的停止、重启、中断以及控制等操作。目前使用比较广泛的调试器主要有immunity调试器、GDB和OllyDbg。
ShellCode:这是一段用于在目标系统上执行的机器语言。过去,它总是被用来执行一个可以赋予攻击者访问目标系统权限的shell进程。所以,ShellCode就是一组可以被处理器理解的指令。
栈(stack):栈充当着数据占位符的角色,通常使用后进先出(Last in First out,LIFO)的存储方法,也就是说最后进入的会最先被移除。
堆(Heap): 堆是用于动态分配的内存区域。与栈不同,我们可以在任何时间对其进行分配、释放和阻塞。
缓冲区溢出(buffer overfow):这个概念通常是指向缓冲区中存放了太多的数据,超出了缓冲区的范围。
格式字符串错误(format string bug):这是一些在使用print系列语句对文件或者命令行中的文本进行处理时出现的错误。在输入一组特定数据的时候,该错误的存在会导致程序中重要信息的泄露。
系统调用(system call):程序在执行的时候调用了操作系统提供的方法。
二、缓冲区溢出
缓冲区溢出是一个程序执行中的异常,即向缓冲区中写入数据时,这些数据超出了缓冲区的大小并且覆盖了内存地址。下图给出了一个非常简单的缓冲区溢出漏洞。
使一个有漏洞的程序崩溃
三、构建渗透测试模块的基础
偏移量(offset) | 我们在上一节中让应用程序崩溃了。为了渗透这个应用程序,需要确定填满缓冲区和EBP寄存器所需字节的准确长度,在这个长度后面的内容就会被保存到EIP寄存器中。我们将未填充进EIP寄存器的数据长度称之为偏移量 |
跳转地址(jump address/ret) | 用来重写EIP寄存器的一个地址,通常是一个DLL文件的JMP ESP指令,可以让程序跳转到攻击载荷所在的地址 |
坏字符(bad character) | 坏字符指的是那些可能导致攻击载荷终止的字符。假设一个ShellCode中存在null字节(0x00),那么它在网络传输的过程中就可能导致缓冲过早的结束,从而出现意想不到的结果。应尽量避免坏字符 |
1、查找偏移量
开发渗透模块的第一个步骤就是找出偏移量。在这个过程中将使用Metasploit的两款工具,分别是pattern_create和pattern_offset。
2、查找跳转地址
我们之所以需要这个JMP ESP指令的地址,是因为我们通过ESP寄存器来载入攻击载荷,而不是在填充满缓冲区之后简单地找到攻击载荷。因此,需要从一个外部的DLL文件得到JMP ESP指令的地址,这个DLL文件将会使程序跳转到ESP中的地址,而这正是攻击载荷的起始地址。
为了找到这个跳转地址,需要一个调试器,这样才能知道这个有漏洞的应用程序载入了哪些DLL文件。
3、填充空间
现在已经成功完成了第二个步骤。不过这里必须指出一点,ShellCode有时可能不在ESP所指向的内存地址,往往在EIP和ESP之间会隔着一段区域,这就会导致ShellCode无法执行。在这种情况下,我们需要使用随机数据或者NOP来填充这个区域。
4、坏字符
有时即便所有渗透工作都已正确完成,却不能成功渗透到目标系统中。或者渗透工作完成了,但是攻击载荷却没有执行。当渗透模块中提供的数据被目标系统进行了截断或者不当解析时,就会出现以上现象。这将导致整个渗透模块不能工作,我们也将无法获得控制系统的shell或者Meterpreter。在这种情况下,需要找到那些导致不能运行的坏字符。处理这种情况的最好办法就是找到匹配的渗透模块,将坏字符从渗透模块中移除。
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = NormalRanking
def initialize(info={})
super(update_info(info,
'Name' => "[Vendor] [Software] [Root Cause] [Vulnerability type]",
'Description' => %q{
Say something that the user might need to know
},
'License' => MSF_LICENSE,
'Author' => [ 'Name' ],
'References' =>
[
[ 'URL', '' ]
],
'Platform' => 'win',
'Targets' =>
[
[ 'System or software version',
{
'Ret' => 0x41414141 # This will be available in `target.ret`
}
]
],
'Payload' => {
'BadChars' => "\x00"
},
'Privileged' => false,
'DisclosureDate' => "",
'DefaultTarget' => 0))
end
def check
# For the check command
end
def exploit
# Main function
end
end
总结:
在本章中,我们针对一个特定漏洞进行渗透模块编写,这个漏洞是一个存在于FreeFloat FTP Server 软件上的溢出漏洞。这种漏洞极为普遍,因而对这种漏洞的研究可以提高我们渗透测试方面的能力。在本章中,先介绍了如何引起一个程序的崩溃,利用崩溃信息可以找出该程序的偏移地址。然后就是如何利用这个地址来编写一个漏洞渗透模块,这里面涉及如何查找 JMP ESP 指令,如何编写漏洞渗透程序,如何找到引起程序终止的坏字符。最后使用 Metasploit 生成了 Shellcode,并将这个 Shellcode 加入漏洞渗透模块。