python 端口在线扫描

Mr.Wu 1,365 0

引言

在渗透过程中,经常会遇到 nmap 扫描不出端口的情况,web 端口确定开放,且用网上的在线端口扫描是可以扫描到的,但是 nmap 就是无法扫出来,因此花了些时间写了 2 个基于 python 端口扫描工具。

基于在线网站调用扫描工具

截图

python 端口在线扫描

代码

# -*- coding: utf-8 -*-
import sys, getopt
import requests
import json
import click

def banner():
    print('''  _____           _      _____                 
 |  __ \         | |    / ____|                
 | |__) |__  _ __| |_  | (___   ___ __ _ _ __  
 |  ___/ _ \| '__| __|  \___ \ / __/ _` | '_ \ 
 | |  | (_) | |  | |_   ____) | (_| (_| | | | |
 |_|   \___/|_|   \__| |_____/ \___\__,_|_| |_|
                                               
    Author:MrWu           Blog:www.mrwu.red        
                                               ''')

def save(data):
    f = open(r'F:\桌面\端口结果.txt', 'a')  #记得修改此处路径为你要存放结果的路径
    f.write(data + '\n')
    f.close()

def run(url):
    try:
        for port in range(1,65536):
            headers ={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36'}
            data = {'port':url,'ports':port}
            data = requests.post('http://www.yzcopen.com/seo/getport',data=data,headers = headers)
            data = json.loads(data.text)
            result = data["restparm"]
            data = " ".join('%s' %a for a in result)
            if "开启" in data:
                click.secho(f"[√] %s   端口开启"%(port), fg="red")
                save("%s:%s   端口开启"%(url,port))
            else:
                print("[×] %s  端口关闭"%(port))
        click.secho(f"[ok] 全部端口扫描完毕", fg="red")
    except:
        pass

def main(argv):
    banner()
    try:
        options, args = getopt.getopt(argv, "hp:i:", ["help", "url="])
    except getopt.GetoptError:
        print("使用方法: python portscan.py --url www.baidu.com")
        sys.exit()
 
    for option, value in options:
        if option in ("-h", "--help"):
            print("使用方法: python portscan.py --url www.baidu.com")
        if option in ("-u", "--url"):
            print("目标:%s  端口扫描任务现在开始\n"%(value))
            run(value)

if __name__ == '__main__':
    main(sys.argv[1:])

说明

  • 修改代码中 19 行,成功结果保存路径为你自己的路径。
  • 由于是调用第三方,所以并没有加入多线程,否则会触发防火墙拉IP。
  • 工具默认扫描 1-65535 全端口,如果需要扫描指定端口范围,可修改代码 25 行中的 1 (起始端口) 和 65536 (结束端口)

基于 socket 的多线程扫描工具2

截图

python 端口在线扫描

代码

# -*- coding: utf-8 -*-
# @Author: mrwu
# @Date:   2022-05-12 16:46:09
# @Last Modified by:   mrwu
# @Last Modified time: 2022-05-17 15:23:51

# 多线程扫描工具
import queue
import socket
import sys
import threading
import time
 
def banner():
    print('''  _____           _      _____                 
 |  __ \         | |    / ____|                
 | |__) |__  _ __| |_  | (___   ___ __ _ _ __  
 |  ___/ _ \| '__| __|  \___ \ / __/ _` | '_ \ 
 | |  | (_) | |  | |_   ____) | (_| (_| | | | |
 |_|   \___/|_|   \__| |_____/ \___\__,_|_| |_|
                                               
    Author:MrWu           Blog:www.mrwu.red        
                                               ''')
	
# 定义端口扫描类
# 要想创建一个线程对象,只要继承类threading.Thread,然后在__ init__里边调用threading.Thread.__init__()方法
class PortScaner(threading.Thread):
	def __init__(self, ip, portqueue, timeout=3):
		threading.Thread.__init__(self)
		self.portqueue = portqueue
		self.ip = ip
		self.timeout = timeout

	def run(self):
	    while True:
	        # 判断当前端口是否为空,为空跳False跳出循环,否则从队列中取出端口,判断当超过指定时间的话退出等待
	        if self.portqueue.empty():
	            break
	        port = self.portqueue.get(timeout=0.5)
	        time.sleep(0.2)
	        print("\r[-] 正在扫描端口: ".format(port)+str(port)+"/"+str(end_port), end="")
	        try:
	            # Ipv4网络协议        提供面向连接的稳定数据传输,建立可靠的通讯,即TCP协议
	            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	            # 超时调用,超过时间,就执行
	            s.settimeout(self.timeout)
	            result_code = s.connect_ex((self.ip, port))  # 该方法如果链接成功会返回0,失败会返回errno库中的errorcode中的key,当为0是代表端口开放
	            if result_code == 0:
	                sys.stdout.write(f"\r[!] 目标: {self.ip}:%d 端口开放\n" % port)
	        except Exception as e:
	            print(e)
	        finally:
	            s.close()
 
 
# 根据用户输入的参数来指定目标ip,端口队列的生成以及子线程的生成,同时还支持单个端口的扫描和范围端口的扫描
def StartScan(targetip, start_port, end_port, threadNum):
    portlist = []  # 端口列表
    for i in range(start_port, end_port):
        portlist.append(i)
    # 目标ip地址
    ip = targetip
    # 线程列表
    threads = []
    # 线程数量
    threadNumber = threadNum
    # 端口队列
    portQueue = queue.Queue()
    # 生成端口,加入端口队列
    for port in portlist:
        portQueue.put(port)
    for t in range(threadNumber):
        threads.append(PortScaner(ip, portQueue, timeout=3))
    # 启动线程
    for thread in threads:
        thread.start()
    # 阻塞线程
    for thread in threads:
        thread.join()
 
 
# 主函数
if __name__ == '__main__':
	banner()
	print("----------------------------------------------")
	ip = input('   输入目标IP:')
	if not ip:
		ip = '127.0.0.1'
	print("   >>>>[1] 端口范围    [2] 指定端口")
	dk = input('   根据上述输入选择 (默认1):')
	if not dk:
		dk = '1'
	if dk == '1':
		start_port = input('   输入起始端口 (默认1):')
		if not start_port:
			start_port = 1
		end_port = input('   输入结束端口 (默认65535):')
		if not end_port:
			end_port = 65535
	elif dk == '2':
		start_port = input('   输入指定端口:')
		end_port = start_port
	threadNum = input('   输入线程数 (默认100-太高容易不准确):')
	if not threadNum:
		threadNum = 100
	print("----------------------------------------------")
	#print('\n')
 
StartScan(ip, int(start_port), int(end_port)+1, int(threadNum))
print("\r[√] 所有扫描均已完成!")

说明

  • 线程最好不要太高,太高会漏掉一些开放的端口。

打赏
发表评论 取消回复
表情 图片 链接 代码

分享
微信
微博
QQ