一.前言

1.关于本人

本人仍然还在学习阶段,有问题欢迎大佬指正,希望我的文章能够帮助到你.以后我很多东西都会在博客更新,和大家一起进步,加油.

2.主题介绍

本次博客主要是开发一个端口扫描工具,用python语言,要求要能指定ip,指定c段,指定端口号和端口范围,还有多线程或者线程池实现,提高端口扫描效率.最重要的是掌握一些python的知识点,一些思路和提高python编程能力.

3.涉及的知识点

  • argparse模块:python用于解析命令行参数和选项的标准模块
  • os模块:python中执行cmd命令
  • ping命令参数
  • ThreadPoolExecutor模块:提高效率
  • socket编程:端口扫描的核心代码
  • 列表字符串等基础知识
  • c段扫描

二.程序代码与结果

1.核心代码:

import os
import socket
import sys
import argparse
import time
from threading import Thread
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
#端口扫描
def scan(ip,port):
        try:
                #for port in range(1, 65536):
                    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                    sock.settimeout(1)
                    result = sock.connect_ex((ip, port))
                    if result == 0:
                        print("Port: {} Open".format(port))
                    sock.close()
        except KeyboardInterrupt:
                sys.exit()
#指定端口
def sport(ip,port):
        # 指定特定端口
        if("," in port):
            ports=port.split(',')
            for p in ports:
                p=int(p)
                scan(ip,p)
        #指定端口范围
        elif("-" in port):
            ports=port.split('-')
            start=int(ports[0])
            end=int(ports[1])
            with ThreadPoolExecutor(100) as t:
             for p in range(start,end):
                 t.submit(scan, ip=ip, port=p)
        #单个端口
        else:
            scan(ip,int(args.port))
#探测ip存活
def check_ip(ip):
    check = os.popen(f"ping {ip} -w 1 -n 1")
    data=check.read()
    if("TTL" in data):
        return True;

parser = argparse.ArgumentParser()
#ip为必填:python scan.py ip
parser.add_argument('ip',type=str,help="give your ip")
#可以指定端口号,也可以指定端口范围
# (1)不指定-p,默认就是全端口扫描
# (2)指定特定的端口号,例如指定80和3306端口 -p 80,3306
# (3)可以指定端口范围,例如0-3306 -p 0-3306
# (4)指定一个端口:例如只扫描445端口,-p 445
parser.add_argument('-p','--port',type=str,help="give your port")
args = parser.parse_args()
ip=args.ip
if("/" in ip):
    ips = ip.split('.')
    ip=ips[0]+"."+ips[1]+"."+ips[2]+"."
    for i in range(1,254):
        ip = ips[0] + "." + ips[1] + "." + ips[2] + "."
        ip=ip+str(i)
        if(check_ip(ip)):
            print(ip+":")
            if args.port:
                port = args.port
                sport(ip, port)
            else:
                with ThreadPoolExecutor(100) as t:
                    for port in range(1, 65536):
                        t.submit(scan, ip=ip, port=port)
else:
    if(check_ip(ip)):
        print(ip+":")
        if args.port:
            port=args.port
            sport(ip,port)
        #全端口扫描
        else:
            with ThreadPoolExecutor(100) as t:
                for port in range(1,65536):
                    t.submit(scan,ip=ip,port=port)
    else:
        print("网络不可达")

2.运行结果

(1).单个ip,默认是全扫描

python资产扫描 python编写扫描工具_python资产扫描

(2).单个ip,指定特定的端口

 

python资产扫描 python编写扫描工具_python资产扫描_02

(3).单个ip,指定端口范围

python资产扫描 python编写扫描工具_网络安全_03

(4)扫描c段,指定特定的端口

python资产扫描 python编写扫描工具_开发语言_04

(5)扫描c段,指定端口范围

python资产扫描 python编写扫描工具_python_05

三.知识点

1.argparse模块:python用于解析命令行参数和选项的标准模块

(1)首先创建解析器

parser = argparse.ArgumentParser()

(2)添加必选参数:

add_argument方法添加参数

ip是必须有的,没填就会报错,且前面不用任何参数

parser.add_argument('ip',type=str,help="give your ip")

python资产扫描 python编写扫描工具_网络安全_06

(3)添加可选参数:

parser.add_argument里面的参数加上--或者-,或者两个都加

parser.add_argument('-p','--port',type=str,help="give your port")

-p或者-port可填可不填

(4)获取参数:

parse_args方法:获得所有参数

args = parser.parse_args() #此时args有所有输入的参数

args.ip #获得ip参数

args.port #获取port参数

(5)对应的代码:

python资产扫描 python编写扫描工具_网络安全_07

2.c段扫描

(1)c段

通俗来讲,就是例如192.168.0.0/24,就是192.168.0.1-192.168.0.254,前面24位不用变,最后8位改变.

(2)c段扫描的原理

由于c段主机比较多,所以在进行端口扫描时,最好先探测一下c段有什么主机哪些存活,再对c段存活的主机进行端口扫描,这样效率就比较快了.探测存活主机的方法,这里是使用ping命令,ping得到的主机就是存活主机,且ping通的主机都有TTL,程序可以根据有无TTL值来判断是否ping通

python资产扫描 python编写扫描工具_python资产扫描_08

(3)对应代码:

python资产扫描 python编写扫描工具_python资产扫描_09

3.ping命令参数

(1)ping命令时间问题:

ping 得到存活的主机速度比较快,但是ping到没有存活的主机速度比较慢

ping存活不到的主机要18秒,太慢了

python资产扫描 python编写扫描工具_网络安全_10

(2)ping命令参数:

查看ping命令参数

python资产扫描 python编写扫描工具_python资产扫描_11

(3)ping命令使用参数改进:

最主要的是-n和-w

我们可以使用-n参数,只显示一条回显结果 -n 1

我们还可以使用-w参数,设置超时时间为 -w 1

测试结果:时间快了好多

python资产扫描 python编写扫描工具_网络安全_12

(4)对应代码:

python资产扫描 python编写扫描工具_python_13

4.os模块:python中执行cmd命令

(1)os模块执行cmd命令的方法:

  • os.system(cmd)

这个方法在执行的时候,它会自动的打开一个终端,并且无法对cmd命令中执行的结果进行保存,简单的说就是使用这个方法,可以在一个脚本中对cmd进行执行操作

  • os.popen(cmd,mode)

这个方法是使用是对一个cmd进程中的管道进行打开操作它会返回一个文件对象,读写模式根据mode决定,可以是读也可以是写,如果mode为'r',可以使用此函数的返回值调用read()来获取cmd命令的执行结果。

所以为了读取执行结果,一般使用os.popen

(2)对应代码:

python资产扫描 python编写扫描工具_python资产扫描_14

5.socket编程:端口扫描的核心代码

(1)创建socket对象

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

socket.AF_INET是服务器之间网络通信

SOCK_STREAM是基于TCP连接的

(2)设置超时时间

sock.settimeout(1)

(3)连接对方的ip加端口

使用connect_ex方法,如果结果为0,说明对方ip+端口是存在的,端口扫描也是基于这个来处理的

result = sock.connect_ex((ip, port))
if result == 0:
print("Port: {} Open".format(port))

(4)关闭socket:

sock.close()

(5)涉及代码:

python资产扫描 python编写扫描工具_python_15

6.ThreadPoolExecutor模块:线程池提高效率

(1)导入模块:

from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor

(2)线程池解析:

with ThreadPoolExecutor(100) as t: #创建100个线程的线程池

for port in range(1,65536): #有这么多个任务

t.submit(scan,ip=ip,port=port) #调用的函数以及参数

所以函数体内尽量实现功能即可,for循环可以在外部做,这样效率就比较高

(3)对应代码:

python资产扫描 python编写扫描工具_开发语言_16