[Python security programming] Python implements network host and port scanning

foreword

This article mainly talks about a few small examples of using Python to realize network scanning, which can be improved by combining multi-threaded or multi-process programming

How far I have traveled,
how many oceans I have crossed to see you

Environmental preparation

  • Python3 environment
  • scapy-library
  • socket library
  • A virtual machine that can communicate normally with a physical machine

Since the purpose of the experiment in this paper is to realize network scanning, that is, to detect the surviving hosts in the network, in order to avoid affecting the real network environment, it is recommended to conduct experiments through virtual machines to ensure that the network communication between the host and the virtual machine is normal.
Both the scapy library and the socket library can be installed directly through the pip command:

pip install scapy

Python implements host scanning

Based on ARP protocol

The ARP protocol will not be explained too much here, you can do it yourself, and the working principle of scanning the target host is roughly as follows:

  • First send an ARP Request request to the target host
  • If the target host responds to ARP Reply, it indicates that the target host may survive
  • If the target host does not respond, the target host may be inactive

It should be noted that here we can directly send broadcast packets whose MAC addresses are all F, without sending data packets to each IP host separately, which can greatly optimize the system running time

experimental code

Note : Since the virtual machine here is on the VMnet8 virtual network card, we should select the corresponding network card for experiments when sending data packets. Under windows, you can check the name and properties of the corresponding network card through the ipconfig /all command

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.")

Code execution result:
insert image description here
10.0.0.171 is the virtual machine I started. You can see that the code was successfully executed and the IP address of the target host was scanned.

Based on ICMP protocol

The host scanning principle based on the ICMP protocol is similar, here we will need to send an ARP request message to each host

regular version

The conventionally written code is as follows:

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%"))

Since the method of traversing each IP and then sending the ICMP request packet is slow, the above code can be rewritten in a multi-threaded manner if the network conditions permit

multithreaded version

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)


Execute this code to get the surviving host IP in the target network segment
insert image description here

Python implements port scanning

scan a single port

The main demonstration here is to use the socket library for port scanning. Here we use port 22 of the virtual machine as an example to conduct experiments:

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)

insert image description here

Port scanning with multithreading

An example of using multi-threaded port scanning is as follows:

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()

running result:
insert image description here

postscript

The above is the whole content of this article. If you have any questions, please leave a comment or contact me~

Guess you like

Origin blog.csdn.net/monster663/article/details/129014765