资讯专栏INFORMATION COLUMN

僵尸网络之如何防护DDoS攻击,愿这个世界再无黑产

NeverSayNever / 1590人阅读

摘要:我写这篇文章的目的是为了让大家更多的去了解如何防护攻击,所以请勿用作违法行为愿这个世界再无黑产。僵尸网络执行某些任务的方式存在很大差异。这种结构是所谓的命令与控制僵尸网络的特征。与僵尸网络无关。该消息将从格式化为僵尸网络的名称要执行的命令。

*严正声明:本文仅限于技术讨论与分享,严禁用于非法途径。

大家好,最近看到国外有一篇和僵尸网络有关的文章,今天分享给各位。

当然,我们面对DDoS当然是可以防御的,就比如云清洗。我写这篇文章的目的是为了让大家更多的去了解如何防护DDoS攻击,所以请勿用作违法行为!愿这个世界再无黑产。

学习网络安全的朋友可以点击【网络安全学习资料·攻略】查看学习思路,也可以私信我获取网络安全相关书籍、工具、教程

简单的 C&C 僵尸网络

这个 hackpack 将引导您完成一个基本框架,该框架从根本上表征了僵尸网络。 如果您以前使用过 C,它可能会有所帮助。 如果你喜欢这个教程,一定要给这个 repo 加星标!

注意:请勿将您在此处学到的任何内容用于恶意目的。 这个 hackpack 只是一个用于教育目的的僵尸网络案例研究。 在这个 hackpack 中学到的概念具有深远的用例(基本上与网络有关的任何事情)。 最重要的是,此 hackpack 旨在在本地进行测试和部署(因此请不要与其他黑客共享您构建的与此 hackpack 相关的任何内容)。 隐私很重要,所以请尊重它。

什么是僵尸网络?

在构建僵尸网络之前,了解什么是僵尸网络很重要。僵尸网络是能够远程接收命令并在本地部署它们的计算机网络。 或者,他们可以选择将信息中继回网络中的其他节点。 它们已被用于从分布式拒绝服务攻击到广泛部署的间谍软件的所有领域。

您过去可能听说过许多僵尸网络。 最突出的可能是 Mirai 和 Gameover Zeus,它们分别控制了 380 和 360 万台物联网设备。 僵尸网络执行某些任务的方式存在很大差异。 但是为了成功构建我们的僵尸网络,我们需要在我们的工作网络中确保以下功能。

我们的僵尸网络应该:

包括一个控制网络上所有其他节点的主节点;

在主机上部署伪装的恶意软件/从节点;

将命令从主节点传输到从节点,执行并将输出返回给主节点。

这种结构是所谓的命令与控制僵尸网络的特征。 这些僵尸网络有一台主服务器和多台从服务器。 然而,这种僵尸网络风格已经过时,可以通过切断对主域的访问来轻松取缔。 更新和复杂的僵尸网络遵循点对点架构,其中管理员权限分布在网络中的所有节点或节点子集。

这些僵尸网络让安全专家非常头疼,因为没有中央控制点,并且可以增长到数百万个节点。 消灭此类僵尸网络本身就是一个有趣的读物。 然而,为了这个 hackpack 的目的,让我们保持简单。 我们将为 C&C 僵尸网络实现一个简单的从节点。
执行
这个 hackpack 将主要处理实现客户端恶意软件。 对于主服务器,我们可以使用开源 TCP 服务器调用 Netcat。 Netcat 与僵尸网络无关。 它只是一个方便的、既定的工具,我们可以重新使用它来向来自客户端的发送文本数据包(这才是真正的主人)。 我稍微调整了 netcat 服务器并将其编译为名为“master”的二进制文件。 这里不再需要工作了! 我们的主人已经准备好使用了。

奴隶
让我们继续讨论更有趣的部分:接收和执行远程命令(我们稍后会担心伪装我们的恶意软件)。 这里的目标是使我们的从节点尽可能简单并遵守上面详述的要求。 请注意,在 lib/macros.h 中定义了许多常量,因此可以随意使用它们。 所有实现的函数签名都可以在 lib/connect.h 或 lib/utils.h 中找到。

  1. 启动
    打开 bot.c 文件。 在我们的服务器中启动一个新节点时,我们可能应该命名它,以便 master 知道将命令部署到哪些客户端。 可以使用许多命名约定。 使用 IP 地址可能是最好的,因为它是每个客户端的唯一标识符。

然而,为了让普通人更容易阅读,让我们使用计算机的用户名。 使用 C 函数getenv()有论据"USER"返回计算机存储在 USER 环境变量中的任何内容。 这是存储用户用户名的一个地方,所以让我们使用它。 另外,既然你的奴隶正在运行,让我们找到主人。 为此,我们必须知道主人的 IP 地址。 每个网络设备都有一个 IP 地址。 它负责识别其他节点和位置寻址。

此外,master 可以有许多服务器在不同的端口上运行。 所以,我们不仅要连接到master,还要指定正确的端口。 此端口由主设备选择,但可以更改。 在这个 hackpack 中,我们想在本地进行测试。 因此,我们将使用您的计算机作为我们的网络。

每台计算机的本地 IP 地址(“localhost”也解析为)是"127.0.0.1". 在 master 中,我指定它在端口上运行9999. 有了这三样东西(主 IP 地址、主端口和从名称),我们就可以在服务器和客户端之间启动一个称为套接字的通信管道。 将这三个参数传递给函数init_socket()创建一个套接字。

init_function()不是内置的 C 命令。 相反,我们需要实施它。 然后,我们需要在堆栈上分配一些空间来保存传入的消息。 我们使用大约 10KB 的堆栈空间调用这个堆栈指针msg. 最后,有一个printf声明表示一切进展顺利。

char* name = //Get the client"s username and store it in nameint channel = //initiate a channel given SERVER, PORT, and name;//Allocate stack space of size CMD_LENGTH to hold data of type char. Call the stack pointer msgprintf("%s joining the botnet/n", name);

现在切换到 lib/connect.c。 让我们实施init_channel(). 首先,我定义了一个名为的堆栈字符缓冲区msg长度CMD_LENGTH和一个特殊的 C 网络结构称为server保存有关我们与 master 连接的信息。

首先将传入的 ip 地址从人类可读的格式(带有数字和点)转换为网络字节顺序的二进制格式。 这是使用一个名为的特殊 C 函数完成的inet_addr()来自套接字库。 它只是接收一个 ip 地址并将其以网络可用的二进制文件形式输出。

在 C 中,我们可以通过填写一个名为的结构体的字段来轻松地指定一个网络sockaddr_in.我们那个结构体的实例被称为server. 我们需要填写该结构体的 3 个字段:server.sin_addr.s_addr(主 IP 地址)、server.sin_family(指定通信域的 1 字节值)和 server.sin_port(我们将在主服务器上连接的端口) )。 sin_family 可以给出套接字库提供的 C 宏。

通常,在这种情况下,我们将此字段设置为AF_INET. 这意味着我们的连接通过 IP 地址识别网络节点,这正是我们想要的。 但是,也可以使用PF_INET这类似于AF_INET但指定网络可以使用协议中的任何内容来识别特定节点。 两者存在的原因还有很多假设的历史原因,但这是我真正不知道或真正关心的事情。 只需使用AF_INET.

最后,在设置服务器端口时,我们必须通过port通过一个特殊的函数调用htons()(主机到网络短)。 这会将数据从主机字节顺序转换为网络字节顺序。 这种字节顺序混乱与称为 Endianness 的东西有关。 此处阅读更多。

最后,我们需要定义主从之间的实际连接! 为此,定义一个网络套接字,通过它可以发送数据。 将 master 视为有许多“电源插座”。 现在,我们需要在 slave 上构建一个适合 master 的“墙上插座”的“插头”。 我们可以使用套接字库的socket()功能。 多么方便!socket()包含 3 个参数:通信域、套接字类型和协议。

对于通信领域,您可能已经猜到了:AF_INET. 对于套接字类型,我们希望我们的套接字能够简单地双向传输数据。 因此,使用给定的宏SOCK_STREAM. 让我们不用担心套接字协议。 这是一个相当基本的网络,所以让我们使用一个值0表示默认协议。 该函数返回一个int代表套接字。 将此值存储在频道中。

接下来,我们要启动我们的插座(将奴隶插入主人的墙上插座)。 调用 C 函数connect(). 这需要三个参数:通道、sockaddr 结构和结构的大小(以字节为单位)。 如果connect()返回一个正整数,你与master的连接成功! 为了测试我们新发现的连接,让我们向 master 发送问候! 填充我们的消息缓冲区并使用respond()(尚未实施)发送msg通过通道回到主人。 最后,我们希望init_channel()函数返回这个成功的连接。

int init_channel (char *ip, int port, char *name) {	char msg[CMD_LENGTH];	struct sockaddr_in server;	server.sin_addr.s_addr = //convert the ip to network byte order	server.sin_family = //set the server"s communications domain  server.sin_port = //convert port to network byte order  int channel = //define a SOCK_STREAM socket  if(channel < 0) {    perror ("socket:");    exit(1);  }  int connection_status = //use the defined channel to connect the slave to the master server    if (connection_status < 0) {    perror ("connect:");    exit(1);  }  //send a greeting message back to master by loading a string into msg (hint: snprintf will come in handy)  respond (channel, msg);  return channel;}

2. 监听消息
一旦从站连接到主站,它需要不断地监听消息并立即根据命令采取行动。 因此,让我们使用无限 while 循环来接收和解析这些消息。 在 bot.c 中,在printf语句,添加一个调用两个函数的无限 while 循环:recieve()和parse()以该顺序。 两个函数都取channel和msg堆栈缓冲区作为参数。 您可以在 lib/utils.h 中找到它们的函数签名。 这应该类似于:

Infinite Loop {  recieve(...);  parse(...);}

去 utils.c 执行recieve()和respond().recieve()从频道中抓取消息并respond()通过通道发回消息。respond()的参数是套接字地址,s,和我们的堆栈缓冲区,msg_buf. 我们要使用 C 函数write()将堆栈缓冲区包含的任何内容写入通道并返回其状态。write()需要 3 个参数:套接字地址、消息缓冲区和消息长度。

int respond(int s, char *msg_buf) {    //write the contents of msg_buf into socket s and return status}

recieve()也是一个简单的帮手。 重置msg缓冲区(提示:使用memset())。 现在,调用套接字库函数read()阅读消息。read()采用 3 个参数:套接字地址、消息缓冲区和消息的最大预期长度。

int recieve(int s, char *msg) {    //reset the msg buffer    int read_status = //read contents of socket s into msg    if (read_status) {      perror("log:");      exit(1);    }    return 0;} 

3. 执行命令

快完成了! 我们的僵尸网络现在很无聊。 它只能通过套接字接收和传输消息。 让我们让它实际执行它在终端上收到的内容。 我们先实现函数parse(). 它的作用正如其名:解析命令。 我们可以做一些简单的错误检查来查看消息是否格式错误。 此外,我们希望默默地忽略收到但并非有意为之的消息。 该消息将从 master 格式化为(僵尸网络的名称):(要执行的命令)。 我已经为你做了前者。 如果两项检查都通过,让我们将命令传递给execute()功能。

int parse (int s, char *msg, char* name) {  char *target = msg;  //check whether the msg was targetted for this client. If no, then silently drop the packet by returning 0  char *cmd = strchr(msg, ":");  if (cmd == NULL) {    printf("Incorrect formatting. Reference: TARGET: command");    return -1;  }  //adjust the cmd pointer to the start of the actual command  //adjust the terminated character to the end of the command  //print a local statement detailing what command was recieved  execute (s, cmd);  return 0;}

关键部分,execute()应该将它接收到的任何命令通过管道传输到终端并将任何输出写入套接字回主。 创建一个堆栈缓冲区来存储每一行​​输入。 然后使用popen()C函数运行输入并将输出存储在文件中f(此时有很多方法可以解决这个问题。

您可以自定义您的僵尸网络以使用主输入做非常酷的事情,并与僵尸网络中的其他节点执行一些自主协作/更新。随意发挥您的创造力。我们现在只会坚持我们的香草目标)。 解析通过f逐行并通过套接字转储所有内容。 关闭 f 就完成了!

int execute (int s, char *cmd) {  FILE *f = //use popen to run the command locally  if (!f) return -1;  while (!feof (f)) {    //parse through f line by line and send any output back to master  }  fclose(f);  return 0;}

使用以下终端命令编译您的新僵尸网络:

gcc -lcurl lib/connect.c lib/utils.c bot.c -o bin/slave

在一个终端窗口上运行 bin/master,在其他窗口上运行 bin/slave。 输入命令为(从用户名):(远程终端命令)。 恭喜! 你刚刚建立了一个僵尸网络!

4. 伪装你的恶意软件

你可以做一些很酷的事情来伪装和部署恶意软件。 事实上,它本身就是一个完整的领域。 您可以做的一个示例是将恶意软件屏蔽为图像。 让我们使用熊猫的图像。 我在 utils.c 中添加了一个简单的函数,它可以卷曲熊猫的图像并将其呈现在预览中。 这为用户提供了打开熊猫图像的概念,而实际上用户正在运行您的恶意软件。 要添加它,请在 bot.c 中包含以下代码行:

char* open_cmd = alias_img();system(open_cmd);free(open_cmd);

接下来,右键单击任何图像并选择“获取信息”。 对 bin/slave 执行相同操作。 将图像缩略图拖到 bin/slave 的可执行缩略图上。 这应该会改变它在桌面上的外观。 但是,我们仍然缺少特征 .png 文件结尾。 将您的可执行文件重命名为

panda⒈png

现在,这看起来像一个 png 文件。 但是,我们使用 Unicode 字符“1”。 代替 ”。” 隐藏这仍然是 Unix 可执行文件的事实。 您可以使用更多可信的 Unix 技巧,例如用于屏蔽可执行文件名的 LEFT-TO-RIGHT OVERRIDE 字符。 在更极端的情况下,您可以在图像和文件宏中嵌入代码以在主机打开时同时运行(有点像特洛伊木马…)。 然而,因为 TreeHacks 没有人是网络罪犯,我们不应该太在意这些技术。

5. 扩展

既然您拥有一个完全可以正常工作的僵尸网络,那么您可以使用许多扩展来挑战自己。 我们的僵尸网络仍然很无趣。 除非用户每次都点击它,否则它无能为力。 以下是一些建议:

  1. 实现持久性

如果僵尸网络以某种方式留在计算机上,即使计算机关闭,它们也可以真正成为攻击者恶意活动的可靠来源。 尝试在每次启动时重新启动奴隶。 这样,一旦用户点击恶意软件,他/她的计算机就会被感染,直到他清除它。 实现这一目标的一个建议是将您的可执行进程变成一个守护进程。 然后,生成一个配置文件,将您的可执行文件添加到应在启动时执行的守护程序列表(云存储应用程序、团队消息传递平台等已经执行此操作)。

  1. 实现点对点网络

实现对等网络无非是重新安排网络设计。 然而,P2P 网络的关键是管理员/攻击者可以通过网络上的任何节点实现主控。 因此,攻击者应该拥有某种主密钥和加密登录,以允许对任何节点进行主控。

  1. 添加多个级别的误导

你实现的主从结构不是很安全。 通过杀死主节点可以轻松地释放从节点。 最佳情况下,您将切换到 P2P 设计。 但是,您也可以在将 master 的命令部署到僵尸网络之前,通过一系列攻击者控制的 bot 随机引导它的命令,从而稍微提高 master 的安全性。 这使得专家更难定位命令中心并跟踪攻击者节点和客户端节点之间的僵尸网络调用。

  1. 探索合适的网络协议

也许,更重要的是,您想更多地玩弄网络。 我们的网络非常简单。 在很多方面,它都极其薄弱,绝对不严谨。 因此,您可能想要探索已建立的网络协议,例如 Internet 中继聊天 (IRC),以构建更合适的网络。 虽然这需要一段时间,但它极具教育意义,而且是一笔值得的投资。

  1. 尝试实现自己的master

在这个 hackpack 中,我们使用了一个免费的开源项目来替代我们的主服务器。 然而,其中涉及许多缺点。 首先,我们无法自定义我们的主服务器以通过我们的网络发送自动命令。 它仅限于使用命令行输入。 其次,您可能已经注意到,僵尸网络上的所有奴隶都会收到每个命令。

我们执行的条件是检查目标名称是否与从站名称匹配。 如果为 false,则该命令将被静默删除。 这被称为广播网络。 更优化的可能是多播网络。 在广播网络中,节点将数据包中继到其所有连接的节点。 在多播系统中,可以指定某个节点子集来接收数据包。 此外,使用多播网络将命令分配从客户端移动到它所属的主服务器。 实现您自己的主节点以将僵尸网络从广播切换到多播。

当然,我们面对DDoS当然是可以防御的,就比如云清洗。我写这篇文章的目的是为了让大家更多的去了解如何防护DDoS攻击,所以请勿用作违法行为!愿这个世界再无黑产

最后,学习网络安全的朋友可以点击【网络安全学习资料·攻略】查看学习思路,也可以私信我获取网络安全相关书籍、工具、教程

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/124697.html

相关文章

  • 阿里云推企业云安全架构 11层防护武装到“牙齿”

    摘要:年,阿里云在全球范围内率先发起数据保护倡议。借助阿里云的网络溯源,警方最终成功抓捕到名犯罪嫌疑人,将黑客组织一网打尽。过去两年,阿里云已陆续协助警方破获案件数十起攻击相关案件,抓捕百余人次。9月28日,阿里云正式发布首个企业云安全架构和《2017阿里云安全白皮书》(以下简称白皮书),企业可参考架构指南和白皮书构建安全、稳固的信息化架构。白皮书将用户隐私和数据安全列为第一原则,并于2015年全...

    Kaede 评论0 收藏0
  • 如何有效的治理僵尸网络以此来避免遭遇DDOS

    摘要:大家都知道的攻击是由僵尸网络组建成的,那么如何有效的治理僵尸网络以此来避免遭遇治理僵尸网络的,可以切断攻击的源头。另一种是接管或摧毁整个僵尸网络。所以墨者安全认为对僵尸网络治理的问题应该先重视起来。 现阶段重视网络安全的程度从最近的护网行动中就可以看出,其中也涉及到了大批量的微信社群被封,不正规的网站被封等等,网络安全的实质就是技术人员与技术人员的较量,这属于一场网络战争。那么各自的进...

    G9YH 评论0 收藏0
  • 放大倍数超5万倍的Memcached DDoS反射攻击,怎么破?

    摘要:腾讯云捕获多起反射型攻击截止月日,腾讯云已捕获到多起利用发起的反射型攻击。腾讯云数据监测显示,黑产针对腾讯云业务发起的反射型攻击从月日起进入活跃期,在月日达到活跃高峰,随后攻击次数明显减少,到月日再次出现攻击高峰。 欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯游戏云发表于云+社区专栏 背景:Memcached攻击创造DDoS攻击流量纪录 近日,利用Memca...

    TalkingData 评论0 收藏0
  • 从保障淘宝到全球市场“第一阵营”,阿里云的DDoS防护路走了多远?

    摘要:目前,阿里云防护网络已经覆盖了全球主要区域,共个大流量清洗中心,总清洗能力大于。除了全球部署以外,阿里云的还有一大特点就是默认防护。总结目前,阿里云防护产品平均每天抵御起攻击事件,年,成功抵御的最大攻击峰值为。 2年前,不少技术圈的朋友,读过论坛里的一篇解读文章:DDoS,阿里为什么要走自己的一条路(https://bbs.aliyun.com/read/2...),文章讲述了阿里巴巴...

    dkzwm 评论0 收藏0
  • 放大倍数超5万倍的Memcached DDoS反射攻击,怎么破?

    摘要:腾讯云捕获多起反射型攻击截止月日,腾讯云已捕获到多起利用发起的反射型攻击。腾讯云数据监测显示,黑产针对腾讯云业务发起的反射型攻击从月日起进入活跃期,在月日达到活跃高峰,随后攻击次数明显减少,到月日再次出现攻击高峰。 欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 作者:腾讯游戏云 背景:Memcached攻击创造DDoS攻击流量纪录 近日,利用Memcached服务器实施...

    TigerChain 评论0 收藏0

发表评论

0条评论

NeverSayNever

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<