[Python セキュリティ プログラミング] Python はネットワーク ホストとポート スキャンを実装します

序文

この記事では主に、Python を使用してネットワーク スキャンを実現するいくつかの小さな例について説明します。これは、マルチスレッドまたはマルチプロセス プログラミングを組み合わせることで改善できます。


あなたに会うためにどれだけ遠くまで旅し、どれだけの海を渡ってきたか

環境整備

  • Python3環境
  • スカピーライブラリ
  • ソケットライブラリ
  • 物理マシンと正常に通信できる仮想マシン

この論文での実験の目的は、ネットワークスキャン、つまりネットワーク内で生き残っているホストを検出することであるため、実際のネットワーク環境への影響を避けるために、ネットワークが安全であることを保証するために仮想マシンを介して実験を行うことをお勧めします。ホストと仮想マシン間の通信は正常です。
scapy ライブラリとソケット ライブラリはどちらも pip コマンドを通じて直接インストールできます。

pip install scapy

Python はホスト スキャンを実装します

ARPプロトコルに基づく

ARP プロトコルについては、ここではあまり説明しません。自分で行うことができます。ターゲット ホストをスキャンする動作原理は、おおよそ次のとおりです。

  • まずARP Requestリクエストをターゲットホストに送信します。
  • ターゲット ホストが ARP 応答に応答した場合、ターゲット ホストが生き残る可能性があることを示します。
  • ターゲット ホストが応答しない場合、ターゲット ホストが非アクティブである可能性があります。

ここでは、データ パケットを各 IP ホストに個別に送信せずに、MAC アドレスがすべて F であるブロードキャスト パケットを直接送信できるため、システムの実行時間を大幅に最適化できることに注意してください。

実験的なコード

: ここの仮想マシンは VMnet8 仮想ネットワーク カード上にあるため、データ パケットを送信する際の実験には、対応するネットワーク カードを選択する必要があります。Windows では、ipconfig /all コマンドを使用して、対応するネットワーク カードの名前とプロパティを確認できます。

from scapy.all import *

# 设置发送数据包的网卡
send_iface = "VMware Virtual Ethernet Adapter for VMnet8"

# 扫描IP地址范围
ip_range = "10.0.0.0/24"

# 发送ARP请求并获取响应
ans, unans = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=ip_range), iface=send_iface, timeout=2)

# 打印响应结果
for snd, rcv in ans:
    print(f"{rcv.psrc} is up.")

コードの実行結果:
ここに画像の説明を挿入
10.0.0.171 が起動した仮想マシンです。コードが正常に実行され、ターゲット ホストの IP アドレスがスキャンされたことがわかります。

ICMPプロトコルに基づく

ICMP プロトコルに基づくホスト スキャンの原理も同様です。ここでは、ARP リクエスト メッセージを各ホストに送信する必要があります。

通常版

従来のように書かれたコードは次のとおりです。

from scapy.all import *

# 输入需要扫描的IP地址范围
ip_range = '10.0.0.0/24'

# 输入需要发送数据包的网卡名
iface = "VMware Virtual Ethernet Adapter for VMnet8"

# 定义发送的ICMP数据包
packet = IP(dst=ip_range)/ICMP()

# 扫描IP地址范围段
ans, unans = sr(packet, iface=iface)

# 输出扫描结果
print("以下IP地址可用:")
for s, r in ans:
    print(r.sprintf("%IP.src%"))

各 IP をトラバースして ICMP リクエスト パケットを送信する方法は遅いため、ネットワークの状況が許せば、上記のコードをマルチスレッド方式で書き換えることができます。

マルチスレッドバージョン

import threading
from scapy.all import *
import logging
#关闭warning警告信息
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)

def scan(ip_list, iface):
    for ip in ip_list:
        pkt = IP(dst=ip)/ICMP()
        res = sr1(pkt, timeout=1, iface=iface, verbose=0)
        if res:
            print(f"{ip} is up")

def scan_ips(target_ips, iface, thread_count=10):
    ip_lists = [[] for _ in range(thread_count)]
    for i, ip in enumerate(target_ips):
        ip_lists[i % thread_count].append(ip)

    threads = []
    for ip_list in ip_lists:
        thread = threading.Thread(target=scan, args=(ip_list, iface))
        threads.append(thread)
        thread.start()

    for thread in threads:
        thread.join()

if __name__ == '__main__':
    ips = ["10.0.0.{}".format(i) for i in range(1, 201)]
    iface = "VMware Virtual Ethernet Adapter for VMnet8"
    scan_ips(ips, iface, thread_count=10)


このコードを実行して、ターゲット ネットワーク セグメント内に残っているホスト IP を取得します。
ここに画像の説明を挿入

Pythonはポートスキャンを実装します

単一ポートをスキャンする

ここでの主なデモンストレーションは、ポート スキャンにソケット ライブラリを使用することです。ここでは、実験を行うための例として仮想マシンのポート 22 を使用します。

from socket import *

def portScanner(host, port):
	try:
		s = socket(AF_INET, SOCK_STREAM)
		s.connect((host,port))
		print('[*]',host,port,'open')
		s.close()
	except:
		print('[-]',host,port,'close')


portScanner('10.0.0.171',22)

ここに画像の説明を挿入

マルチスレッドによるポートスキャン

マルチスレッド ポート スキャンの使用例は次のとおりです。

import socket
import threading

# 定义扫描函数
def scan_port(ip, port):
    try:
        # 创建套接字
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(1)
        # 连接目标主机的指定端口
        result = sock.connect_ex((ip, port))
        if result == 0:
            print(f"Port {
      
      port} is open on {
      
      ip}")
        # 关闭套接字
        sock.close()
    except Exception as e:
        print(e)
        pass

# 定义多线程扫描函数
def scan_thread(ip, start_port, end_port):
    for port in range(start_port, end_port):
        scan_port(ip, port)

# 主函数
if __name__ == '__main__':
    # 设置要扫描的主机和端口范围
    target_host = '10.0.0.171'
    start_port = 1
    end_port = 65536

    tpool=[]

    # 创建多个线程进行扫描
    for i in range(start_port-1, (end_port+1)//100):
        t = threading.Thread(target=scan_thread, args=(target_host, i*100+1, (i+1)*100))
        t.start()
        tpool.append(t)
    for t in tpool:
        t.join()

実行結果:
ここに画像の説明を挿入

追記

以上がこの記事の全内容ですが、ご不明な点がございましたら、コメントまたはご連絡ください〜

おすすめ

転載: blog.csdn.net/monster663/article/details/129014765