網路掃描是滲透測試流程中不可或缺的環節,用於識別目標網路中的活動主機和開放埠。本文將逐步講解如何使用 Python 實作 Ping 掃描和 TCP 掃描,並探討如何利用多執行緒技術提升掃描效率。首先,我們會介紹 Ping 掃描的原理和基本 Python 實作,包括使用 os 模組執行系統 Ping 命令和跨平台程式碼的撰寫。接著,我們將深入 TCP 掃描,根據 TCP 三次握手原理,使用 socket 模組建立 TCP 連線,並判斷目標埠是否開放。最後,針對大規模網路掃描的效能瓶頸,我們將引入多執行緒技術,並提供多執行緒 Ping 掃描和 TCP 掃描的 Python 程式碼範例,同時分析 Linux 環境下使用原始通訊端和 ICMP 封包的高效能掃描器實作。

網路掃描與滲透測試:Python實務應用

網路掃描是指一系列調查主機狀態、主機型別、開放埠及執行服務的程式。這是情報收集的一部分,攻擊者藉此建立目標組織的輪廓。

如何檢查網路中的活動主機

Ping掃描涉及向主機傳送ICMP ECHO請求。如果主機活動,它將傳回ICMP ECHO回應。作業系統的Ping命令提供了檢查主機是否活動的功能。

Ping掃描原理

Ping掃描用於透過傳送ICMP ECHO請求和ICMP ECHO回應來識別活動主機的IP位址範圍。攻擊者或滲透測試者可以從子網路和網路位址計算網路範圍。

使用Python實作Ping掃描

以下是一個簡單的Python程式碼範例,用於Ping掃描:

import os

response = os.popen("ping -n 1 10.0.0.1").readlines()
for line in response:
    print(line)

這個程式碼使用了os模組來執行作業系統的Ping命令,並讀取命令的輸出結果。

程式碼解密:

  1. import os:匯入os模組,以便能夠執行作業系統命令。
  2. response = os.popen("ping -n 1 10.0.0.1").readlines():使用os.popen()函式執行Ping命令,並將輸出結果讀取到response變數中。-n 1引數指定傳送一個ICMP ECHO請求包。
  3. for line in response: print(line):遍歷response中的每一行輸出結果,並將其列印出來。

Ping掃描的改進

為了使Ping掃描更加高效和易於閱讀,我們需要對程式碼進行改進,使其能夠跨平台執行並產生易於閱讀的輸出結果。

範例程式碼:

import os
import platform

def ping_ip(ip_address):
    if platform.system().lower() == 'windows':
        ping_cmd = f'ping -n 1 {ip_address}'
    else:
        ping_cmd = f'ping -c 1 {ip_address}'
    
    response = os.popen(ping_cmd).readlines()
    for line in response:
        print(line.strip())

# 範例使用
ping_ip('10.0.0.1')

程式碼解密:

  1. import osimport platform:匯入必要的模組。
  2. def ping_ip(ip_address)::定義一個函式,用於Ping指定的IP位址。
  3. if platform.system().lower() == 'windows'::檢查作業系統型別,以確定使用的Ping命令引數。
  4. ping_cmd = f'ping -n 1 {ip_address}'(Windows)或 ping_cmd = f'ping -c 1 {ip_address}'(其他作業系統):根據作業系統型別建構Ping命令。
  5. response = os.popen(ping_cmd).readlines():執行Ping命令並讀取輸出結果。
  6. for line in response: print(line.strip()):列印輸出結果,每行去除前後空白字元。

網路掃描與滲透測試的下一步

在下一章中,我們將探討如何使用TCP掃描器來檢測遠端主機上執行的服務。透過結合Ping掃描和TCP掃描,我們可以更全面地瞭解目標網路的拓撲結構和潛在的安全風險。

掃描滲透測試章節 2:網路掃描與TCP掃描實作

在前一章節中,我們探討了使用ICMP ECHO請求和回應來進行網路掃描的技術。然而,許多使用者會關閉ICMP ECHO回應功能或使用防火牆來阻擋ICMP封包,這使得我們的ping掃描器無法正常運作。在這種情況下,我們需要使用TCP掃描技術。

TCP掃描概念及其Python指令碼實作

TCP掃描根據TCP的三次握手原理。建立TCP連線的過程包括以下三個步驟:

  1. 使用者端傳送一個包含SYN旗標的段,請求伺服器啟動一個會話。
  2. 伺服器回應一個包含ACK和SYN旗標的段。
  3. 使用者端回應一個包含ACK旗標的段。

TCP掃描Python指令碼

import socket
from datetime import datetime

net = raw_input("Enter the Network Address ")
net1 = net.split('.')
a = '.'

net2 = net1[0] + a + net1[1] + a + net1[2] + a
st1 = int(raw_input("Enter the Starting Number "))
en1 = int(raw_input("Enter the Last Number "))
en1 = en1 + 1

t1 = datetime.now()

def scan(addr):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    socket.setdefaulttimeout(1)
    result = sock.connect_ex((addr, 135))
    if result == 0:
        return 1
    else:
        return 0

def run1():
    for ip in xrange(st1, en1):
        addr = net2 + str(ip)
        if scan(addr):
            print(addr, "is live")

run1()

t2 = datetime.now()
total = t2 - t1
print("scanning complete in ", total)

程式碼解密:

  • 首先,我們匯入必要的模組,包括socketdatetimesocket模組用於建立網路連線,而datetime用於計算掃描所花費的時間。
  • 程式碼要求使用者輸入網路地址、起始數字和最後數字,分別用於定義掃描的IP範圍。
  • scan函式使用socket建立到特定IP和埠(本例中為135)的連線。如果連線成功(即埠開放),函式傳回1,否則傳回0。
  • run1函式遍歷指定的IP範圍,對每個IP呼叫scan函式。如果scan傳回1,表示該IP是活躍的,並列印出來。
  • 最後,程式碼計算並列印掃描所花費的總時間。

網路掃描與TCP掃描的比較

  • 網路掃描(ping掃描)根據ICMP協定,可能被防火牆阻擋或被使用者端關閉ICMP回應功能而失效。
  • TCP掃描則透過嘗試建立TCP連線來判斷主機是否活躍,不依賴ICMP,因此在某些情況下更為可靠。

提升網路掃描效率:多執行緒技術的應用

在網路安全掃描與滲透測試中,掃描網路主機是一項基本任務。然而,傳統的順序掃描方式往往效率低下,尤其是在面對龐大的 IP 地址範圍時。本章將探討如何利用 Python 的多執行緒技術來提升網路掃描的效率,並介紹一個結合多執行緒的 Ping Sweep 掃描器實作。

為何需要多執行緒?

在前面的章節中,我們已經實作了一個簡單的 Ping Sweep 掃描器和一個 TCP 掃描器。雖然這兩個工具能夠完成掃描任務,但它們都是以單執行緒的方式運作。當面對大量 IP 地址時,這種方式會導致掃描過程非常緩慢。例如,掃描 60 個主機時,Ping Sweep 掃描器需要 2 分鐘 35 秒,而 TCP 掃描器也需要接近 1 分鐘。如此低下的效率顯然無法滿足實際需求。

多執行緒技術的優勢

Python 提供了多執行緒(Multithreading)技術,可以有效地提升程式的執行效率。透過將任務分配給多個執行緒平行處理,可以大幅縮短整體執行時間。在網路掃描的場景中,多執行緒技術可以同時對多個 IP 地址進行掃描,從而顯著提升掃描速度。

多執行緒 Ping Sweep 掃描器的實作

下面是一個結合多執行緒技術的 Ping Sweep 掃描器實作範例:

import datetime
import collections
import threading

# 定義網路位址輸入
net = input("Enter the Network Address ")
net1 = net.split('.')
a = '.'

# 取得起始和結束 IP 地址範圍
net2 = input("Enter the Starting Number ")
net3 = int(net2)
net4 = input("Enter the Last Number ")
net5 = int(net4)

# 計算總共需要掃描的 IP 地址數量
net_final = int(net5) - int(net3)

# 建立有序字典用於儲存結果
dic = collections.OrderedDict()

# 定義 Ping 函式
def scan(addr):
    # 省略 Ping 操作的具體實作
    output = os.popen("ping -n 1 " + addr).read()
    if 'TTL=' in output:
        dic[addr] = output

# 多執行緒類別定義
class myThread(threading.Thread):
    def __init__(self, start, end):
        threading.Thread.__init__(self)
        self.start = start
        self.end = end

    def run(self):
        for i in range(self.start, self.end):
            addr = net1[0] + a + net1[1] + a + net1[2] + a + str(i)
            scan(addr)

# 設定每個執行緒處理的 IP 地址數量
num_threads = 20
thread_list = []

# 建立並啟動多個執行緒
for i in range(num_threads):
    start = net3 + i * (net_final // num_threads)
    end = start + (net_final // num_threads)
    thread = myThread(start, end)
    thread_list.append(thread)
    thread.start()

# 等待所有執行緒完成
for thread in thread_list:
    thread.join()

# 列印存活主機的 IP 地址
for key in dic:
    print(key, '
---
> Live')

print('Number of Threads active:', threading.active_count())
print('Exiting Main Thread')

程式碼解析:

  1. 輸入網路位址與範圍:首先,程式要求使用者輸入網路位址和需要掃描的 IP 地址範圍。
  2. 計算總共需要掃描的 IP 地址數量:根據輸入的起始和結束數字,計算需要掃描的 IP 地址總數。
  3. 定義 Ping 函式scan 函式負責對指定的 IP 地址執行 Ping 操作,並將結果儲存在有序字典 dic 中。
  4. 多執行緒類別myThread 繼承自 threading.Thread,用於定義每個執行緒的行為。每個執行緒負責掃描一段 IP 地址範圍。
  5. 建立並啟動多個執行緒:根據設定的執行緒數量,將整個 IP 地址範圍劃分為多段,每段由一個執行緒負責掃描。
  6. 等待所有執行緒完成:主程式等待所有執行緒完成後,再列印存活主機的 IP 地址。

多執行緒技術的優勢與應用場景

透過引入多執行緒技術,Ping Sweep 掃描器的效率得到了顯著提升。在相同的測試環境下,多執行緒版本的掃描器能夠在更短的時間內完成對大量 IP 地址的掃描。

這種技術不僅適用於 Ping Sweep 掃描器,也可以應用於其他需要大量網路操作的場景,如 TCP 埠掃描、網路服務探測等。

掃描滲透測試章節 2:高效能 IP 掃描器的實作與最佳化

在前一章節中,我們探討了使用多執行緒技術實作基本的 IP 掃描器。本章節將深入討論如何進一步最佳化掃描器的效能,特別是在 Linux 環境下。

多執行緒 TCP 掃描器的實作

首先,我們來分析一個使用 TCP 掃描方法的多執行緒程式。這段程式碼展示瞭如何透過多執行緒技術提高掃描效率。

import threading
import time
import socket

def scan(ip):
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((ip, 80))
        print(f"{ip} --> Live")
    except Exception as e:
        pass
    finally:
        s.close()

def main():
    network = input("Enter the Network Address ")
    start = int(input("Enter the starting Number "))
    end = int(input("Enter the last Number "))
    num_threads = 4
    total_ips = end - start + 1
    total_threads = total_ips // num_threads

    threads = []
    for i in range(num_threads):
        thread = threading.Thread(target=scan_ips, args=(network, start + i * total_threads, start + (i + 1) * total_threads - 1))
        threads.append(thread)
        thread.start()

    for thread in threads:
        thread.join()

    print("Exiting Main Thread")

if __name__ == "__main__":
    main()

程式碼解析:

  1. 多執行緒管理:程式碼中使用了 threading 模組來建立和管理多個執行緒,每個執行緒負責掃描指定範圍內的 IP 位址。
  2. TCP 掃描scan 函式嘗試與目標 IP 的特定埠(此例中為 80)建立 TCP 連線,以判斷該 IP 是否活躍。
  3. IP 範圍劃分:根據使用者輸入的起始和結束 IP 號,將掃描任務分配給多個執行緒,以提高掃描效率。

Linux 環境下的高效能 IP 掃描器

在 Linux 環境下,我們可以利用原始通訊端(raw socket)和 ICMP 封包實作更高效的 IP 掃描。

程式碼範例:

import socket
import struct
import threading
import time

def send_ping(sock, ip):
    # 建立 ICMP echo 請求封包
    packet = struct.pack('!BBHHH', 8, 0, 0, 0, 1)
    packet = packet + b'abcdefgh'
    try:
        sock.sendto(packet, (ip, 0))
    except Exception as e:
        print(f"Error sending ping to {ip}: {e}")

def sniffing(sock):
    while True:
        try:
            data, addr = sock.recvfrom(1024)
            # 解析 ICMP 回應封包
            icmp_type, icmp_code = struct.unpack('!BB', data[20:22])
            if icmp_type == 0:  # ICMP echo 回應
                print(f"{addr[0]} --> Live")
        except Exception as e:
            pass

def main():
    # 建立原始通訊端
    sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
    # 建立並啟動 sniffing 執行緒
    sniff_thread = threading.Thread(target=sniffing, args=(sock,))
    sniff_thread.daemon = True
    sniff_thread.start()

    # 傳送 ICMP echo 請求
    for ip in ips_to_scan:
        send_ping(sock, ip)

if __name__ == "__main__":
    main()

程式碼解析:

  1. 原始通訊端:使用 socket.SOCK_RAWsocket.IPPROTO_ICMP 建立原始通訊端,直接傳送和接收 ICMP 封包。
  2. ICMP echo 請求send_ping 函式建立並傳送 ICMP echo 請求封包到目標 IP。
  3. Sniffingsniffing 函式負責接收並解析 ICMP 回應封包,判斷目標主機是否活躍。