基于python制作一个端口扫描工具

端口扫描工具

初学python尝试做的一个端口扫描工具 ,下面直接上教程

需要使用到的python库

import threading
import tkinter as tk
from socket import *

实际上 这里只需导入Threading以及Socket库就可以了 
 但是个人原因 就写了一个简单的可视化界面,所以引用了Tkinter库

导入库的作用

引用库的作用:
			Threading: 导入Threading库最核心的功能就是调用Thread类。
                                    每个Threading对象代表一个线程,在每个线程中,
                                    我们可以让程序处理所分配的不同任务,这就是最基本多线程编程。Threading对象
                                    最重要的就是target参数,下文使用时会详细说明。
                                    有关Threading的相关使用可以自行百度。
			Socket:Socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,
                                对于文件用【打开】【读写】【关闭】模式来操作。
                                socket(套接字)是应用层与TCP/IP协议族通信的中间软件抽象层,
                                它是一组接口,将复杂的TCP/IP协议族隐藏在接口后面,
                                让socket去组织数据以符合指定的协议。
                                socket就是该模式的一个实现,
                                socket即是一种特殊的文件,一些socket函数就是对其进行的操作
                               (读/写IO、打开、关闭)。同样,下文使用具体介绍相关参数。
                                Scoket相关内容连接:http://t.zoukankan.com/Forever77-p-10966483.html
			Tkinter:pytho常用的图形化库啦,这个网上有很多资料,这里就不过多说了。

全局使用的参数

lock = threading.Lock()  # 确保 多个线程在共享资源的时候不会出现脏数据
threads = []  # 线程池
out22 = ''

Socket部分

def portscanner(host, port):            //这里定义了一个函数名 参数是ip以及端口
    global out22                        //设置了一个全局变量 是字符串形式的 用来在可视化界面输出
    try:                                    //这里使用python中的异常处理  结合Socket使用 
        s = socket(AF_INET, SOCK_STREAM)    //  创建基于TCP面向网络的的工作流程
        s.connect((host, port))            //连接到host地址port端口的套接字 连接不上就返回error错误
        lock.acquire()                     //调用Threading的方法  此方法用于获取锁,阻塞或非阻塞。
        out22 += str(port) + " open\n"    //连接上就将端口写入该字符串 提示信息是端口open
        lock.release()                   //这里是释放锁  以便下一个线程获取锁开始执行
        s.close()                       //关闭流程
    except:
        pass                           
//这里的作用是 当S.connect返回的时错误的时候 表示目标端口并没有开放,不执行直接跳过

Threading部分

//因为代码是在主要方法里面 这里单拿出解释 后面会放完整代码
    
    for port in ports:       //使用for循环读入所有的端口范围
        t = threading.Thread(target=portscanner, args=(ip, port))   
        //创建线程 方法是Socke部分 传入的参数是ip地址以及端口  

        threads.append(t)     //将线程追加到线程池 
        t.start()             //这里开始线程
    for t in threads:       //for循环多线程
        t.join()            //执行线程

Tkinter部分

root = tk.Tk()                                  //导入库设置了别名tk 这里是定义root为Tk方法的别名
    root.title('XSCAN小工具')                     //设置可视化界面的标题  当然你可以改成你自己的
    screenWidth = root.winfo_screenwidth()       //获取屏幕分辨率  宽度
    screenHeight = root.winfo_screenheight()      //获取屏幕分辨率 高度
    x = int((screenWidth - 300) / 2)              
    y = int((screenHeight - 400) / 2)         //屏幕高宽取半 获取中心位置
    root.geometry(f'300x400+{x}+{y}')        //设置可视化界面的大小  设置坐标为居中 
    root.anchor('center')                   //模块居中 跟随窗口变化

    in1 = tk.Label(root, text='请输入你要扫描的ip', font=('华文行楷', 20, 'bold'), fg='red', anchor='center')
    in1.grid(row=1, column=0, sticky='N')

    en1 = tk.Entry(root, width=20)
    en1.grid(row=3, column=0, sticky='N')

    in2 = tk.Label(root, text='输入端口\n默认全扫描', font=('华文行楷', 15, 'bold'), fg='red', anchor='center')
    in2.grid(row=5, column=0, sticky='N')

    en2 = tk.Entry(root, width=20)
    en2.grid(row=7, column=0, sticky='N')
    
    //以上是设置的提示模块以及输入模块  具体可百度  
    AnNiu = tk.Button(root, text='提交', fg='blue', bd=2, width=10, command=main)
    AnNiu.grid(row=10, column=0, sticky='N')
    //设置了一个提交按钮   提交后  将输入模块的值传给主方法 
    out3 = tk.Text(root, width=20, height=15)    
    //输出界面  这里定义一个空内容 用于读取成功扫描的端口
    out3.grid(row=15, column=0, columnspan=7, sticky='N', )
    root.mainloop()     //执行界面   本人第一次接触的就是grid布局  喜欢用pack的也可以自行参考修改

主方法部分

def main():  
    global out2, out22, out3             //设置三个全局变量 用来接收和输出在可视化界面的数据
    out22=''                            //每次设置为空 避免可视化界面不刷新输出数据
    out3.configure(state="normal")     //状态设置为正常 可删除修改添加  便于更新输出界面数据
    out3.delete(0.0,'end')            //从开始删除数据  即清空上一次操作可视化界面输出的数据
    ip = en1.get()                   //get获取变量本身的值 这里是可视化界面传过来的要扫描的目标地址
    putport = en2.get()             //get获取变量本身的值 这里是可视化界面传过来的要扫描的目标端口
    if putport == '':              //判断是否有指定端口和端口范围  没有指定就默认全扫描 
        ports = range(65535)      //默认端口扫描范围为全部端口
    else:                        //有输入端口的情况
        getport = putport.split(',')      //因为传入端口是字符串 多端口用逗号间隔 这里分割放进列表
        ports = []                        //定义一个空的列表  作用是 提取传入端口中如果有指定范围
        for port in getport:              //for循环端口   查找是否有指定端口范围  ps:端口范围例子:1-10
            if port.find('-') != -1:         //匹配到为1 没匹配到为-1

                port = range(int(port.split('-')[0]), int(port.split('-')[-1]+1))
                //匹配到后 将范围开始和结束提取放进range中 因为结尾会少一个 所以结束的值要加1 

                for num in port:  
                    //因为直接列表中添加range 输出会不生效 且报错 所以逐个添加进新列表 
                    ports.append(num)         //将指定范围所有端口添加新列表
            else:
                ports.append(int(port))      //如果没有匹配 强转为int类型 放进列表
        ports.sort()                       //将得到的列表排序
    for port in ports:     //这里是之前所提到的Threading部分  可自行去上文查看
        t = threading.Thread(target=portscanner, args=(ip, port))
        threads.append(t)
        t.start()
    for t in threads:
        t.join()            //线程结束之前 不会执行下面的语句   下面语句所使用的数据在Socket部分
     
    out3.insert('end', out22)    //将成功的字符串添加进输出界面
    out3.configure(state="disabled")    //输出界面状态改为不可用  即禁止修改 

完整代码

import threading
import tkinter as tk
from socket import *

lock = threading.Lock()  # 确保 多个线程在共享资源的时候不会出现脏数据
threads = []  # 线程池
out22 = ''


def portscanner(host, port):
    global  out22
    try:
        s = socket(AF_INET, SOCK_STREAM)
        s.connect((host, port))
        lock.acquire()
        openNum += 1
        out22 += str(port) + " open\n"
        lock.release()
        s.close()
    except:
        pass
def main(): 
    global out22, out3
    out22=''
    out3.configure(state="normal")
    out3.delete(0.0,'end')
    ip = en1.get()
    putport = en2.get()
    if putport == '':
        ports = range(65535)
    else:
        getport = putport.split(',')
        ports = []
        for port in getport:
            if port.find('-') != -1:
                port = range(int(port.split('-')[0]), int(port.split('-')[-1]))
                for num in port:
                    ports.append(num)
            else:
                ports.append(int(port))
    for port in ports:
        t = threading.Thread(target=portscanner, args=(ip, port))
        threads.append(t)
        t.start()
    for t in threads:
        t.join()
    out3.insert('end', out22)
    out3.configure(state="disabled")


if __name__ == '__main__':
    root = tk.Tk()
    root.title('XSCAN小工具')
    screenWidth = root.winfo_screenwidth()
    screenHeight = root.winfo_screenheight()
    x = int((screenWidth - 300) / 2)
    y = int((screenHeight - 400) / 2)
    root.geometry(f'300x400+{x}+{y}')
    root.anchor('center')

    in1 = tk.Label(root, text='请输入你要扫描的ip', font=('华文行楷', 20, 'bold'), fg='red', anchor='center')
    in1.grid(row=1, column=0, sticky='N')

    en1 = tk.Entry(root, width=20)
    en1.grid(row=3, column=0, sticky='N')

    in2 = tk.Label(root, text='输入端口\n默认全扫描', font=('华文行楷', 15, 'bold'), fg='red', anchor='center')
    in2.grid(row=5, column=0, sticky='N')

    en2 = tk.Entry(root, width=20)
    en2.grid(row=7, column=0, sticky='N')

    AnNiu = tk.Button(root, text='提交', fg='blue', bd=2, width=10, command=main)
    AnNiu.grid(row=10, column=0, sticky='N')

    out3 = tk.Text(root, width=20, height=15)
    out3.grid(row=15, column=0, columnspan=7, sticky='N', )
    root.mainloop()

结尾

   因为本人是网络安全专业的,对于开发也是粗略的学习了一些,
   该代码还存在许多bug 以及功能不够全面等等问题。
   欢迎大家指出不足的部分和给予宝贵的意见以及建议!!
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值