Python 实现端口扫描

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 实现端口扫描相关的知识,希望对你有一定的参考价值。

一、常见端口扫描的原理0、秘密扫描秘密扫描是一种不被审计工具所检测的扫描技术。它通常用于在通过普通的防火墙或路由器的筛选(filtering

参考技术A

一、常见端口扫描的原理

0、秘密扫描

秘密扫描是一种不被审计工具所检测的扫描技术。

它通常用于在通过普通的防火墙或路由器的筛选(filtering)时隐藏自己。

秘密扫描能躲避IDS、防火墙、包过滤器和日志审计,从而获取目标端口的开放或关闭的信息。由于没有包含TCP 3次握手协议的任何部分,所以无法被记录下来,比半连接扫描更为隐蔽。

但是这种扫描的缺点是扫描结果的不可靠性会增加,而且扫描主机也需要自己构造IP包。现有的秘密扫描有TCP FIN扫描、TCP ACK扫描、NULL扫描、XMAS扫描和SYN/ACK扫描等。

1、Connect()扫描

此扫描试图与每一个TCP端口进行“三次握手”通信。如果能够成功建立接连,则证明端口开发,否则为关闭。准确度很高,但是最容易被防火墙和IDS检测到,并且在目标主机的日志中会记录大量的连接请求以及错误信息。

TCP connect端口扫描服务端与客户端建立连接成功(目标端口开放)的过程:

① Client端发送SYN;

② Server端返回SYN/ACK,表明端口开放;

③ Client端返回ACK,表明连接已建立;

④ Client端主动断开连接。

建立连接成功(目标端口开放)

TCP connect端口扫描服务端与客户端未建立连接成功(目标端口关闭)过程:

① Client端发送SYN;

② Server端返回RST/ACK,表明端口未开放。

优点:实现简单,对操作者的权限没有严格要求(有些类型的端口扫描需要操作者具有root权限),系统中的任何用户都有权力使用这个调用,而且如果想要得到从目标端口返回banners信息,也只能采用这一方法。

另一优点是扫描速度快。如果对每个目标端口以线性的方式,使用单独的connect()调用,可以通过同时打开多个套接字,从而加速扫描。

缺点:是会在目标主机的日志记录中留下痕迹,易被发现,并且数据包会被过滤掉。目标主机的logs文件会显示一连串的连接和连接出错的服务信息,并且能很快地使它关闭。

2、SYN扫描

扫描器向目标主机的一个端口发送请求连接的SYN包,扫描器在收到SYN/ACK后,不是发送的ACK应答而是发送RST包请求断开连接。这样,三次握手就没有完成,无法建立正常的TCP连接,因此,这次扫描就不会被记录到系统日志中。这种扫描技术一般不会在目标主机上留下扫描痕迹。但是,这种扫描需要有root权限。

·端口开放:(1)Client发送SYN;(2)Server端发送SYN/ACK;(3)Client发送RST断开(只需要前两步就可以判断端口开放)

·端口关闭:(1)Client发送SYN;(2)Server端回复RST(表示端口关闭)

优点:SYN扫描要比TCP Connect()扫描隐蔽一些,SYN仅仅需要发送初始的SYN数据包给目标主机,如果端口开放,则相应SYN-ACK数据包;如果关闭,则响应RST数据包;

3、NULL扫描

反向扫描—-原理是将一个没有设置任何标志位的数据包发送给TCP端口,在正常的通信中至少要设置一个标志位,根据FRC 793的要求,在端口关闭的情况下,若收到一个没有设置标志位的数据字段,那么主机应该舍弃这个分段,并发送一个RST数据包,否则不会响应发起扫描的客户端计算机。也就是说,如果TCP端口处于关闭则响应一个RST数据包,若处于开放则无相应。但是应该知道理由NULL扫描要求所有的主机都符合RFC 793规定,但是windows系统主机不遵从RFC 793标准,且只要收到没有设置任何标志位的数据包时,不管端口是处于开放还是关闭都响应一个RST数据包。但是基于Unix(*nix,如Linux)遵从RFC 793标准,所以可以用NULL扫描。 经过上面的分析,我们知道NULL可以辨别某台主机运行的操作系统是什么操作系统。

端口开放:Client发送Null,server没有响应

端口关闭:(1)Client发送NUll;(2)Server回复RST

说明:Null扫描和前面的TCP Connect()和SYN的判断条件正好相反。在前两种扫描中,有响应数据包的表示端口开放,但在NUll扫描中,收到响应数据包表示端口关闭。反向扫描比前两种隐蔽性高些,当精确度也相对低一些。

用途:判断是否为Windows系统还是Linux。

4、FIN扫描

与NULL有点类似,只是FIN为指示TCP会话结束,在FIN扫描中一个设置了FIN位的数据包被发送后,若响应RST数据包,则表示端口关闭,没有响应则表示开放。此类扫描同样不能准确判断windows系统上端口开发情况。

·端口开放:发送FIN,没有响应

·端口关闭:(1)发送FIN;(2)回复RST

5、ACK扫描

扫描主机向目标主机发送ACK数据包。根据返回的RST数据包有两种方法可以得到端口的信息。方法一是: 若返回的RST数据包的TTL值小于或等于64,则端口开放,反之端口关闭。

6、Xmas-Tree扫描

通过发送带有下列标志位的tcp数据包。

·URG:指示数据时紧急数据,应立即处理。

·PSH:强制将数据压入缓冲区。

·FIN:在结束TCP会话时使用。

正常情况下,三个标志位不能被同时设置,但在此种扫描中可以用来判断哪些端口关闭还是开放,与上面的反向扫描情况相同,依然不能判断windows平台上的端口。

·端口开放:发送URG/PSH/FIN,没有响应

·端口关闭:(1)发送URG/PSH/FIN,没有响应;(2)响应RST

XMAS扫描原理和NULL扫描的类似,将TCP数据包中的ACK、FIN、RST、SYN、URG、PSH标志位置1后发送给目标主机。在目标端口开放的情况下,目标主机将不返回任何信息。

7、Dump扫描

也被称为Idle扫描或反向扫描,在扫描主机时应用了第三方僵尸计算机扫描。由僵尸主机向目标主机发送SYN包。目标主机端口开发时回应SYN|ACK,关闭时返回RST,僵尸主机对SYN|ACK回应RST,对RST不做回应。从僵尸主机上进行扫描时,进行的是一个从本地计算机到僵尸主机的、连续的ping操作。查看僵尸主机返回的Echo响应的ID字段,能确定目标主机上哪些端口是开放的还是关闭的。

二、Python 代码实现

1、利用Python的Socket包中的connect方法,直接对目标IP和端口进行连接并且尝试返回结果,而无需自己构建SYN包。

2、对IP端口进行多线程扫描,注意的是不同的电脑不同的CPU每次最多创建的线程是不一样的,如果创建过多可能会报错,需要根据自己电脑情况修改每次扫描的个数或者将seelp的时间加长都可以。

看完了吗?感觉动手操作一下把!

python学习网,免费的在线学习python平台,欢迎关注!

本文转自:https://www.jianshu.com/p/243bb7cfc40f

python实现FTP弱口令扫描器与简单端口扫描器

python实现FTP弱口令扫描器与简单端口扫描器

 

目录

FTP弱口令扫描器

简单端口扫描器

 

参考:

https://blog.csdn.net/rebelqsp/article/details/22109925

https://www.aliyun.com/jiaocheng/434055.html?spm=5176.100033.2.10.3571581eheCuHX

 

FTP弱口令扫描器

# Ftp匿名扫描器的实现,需要使用FTP这个类
# Ftp这个类实现了Ftp客户端的大多数功能,比如连接Ftp服务器、查看服务器中的文件、上传、下载文件等功能,

import  ftplib
import time
import argparse

#FTP匿名登录扫描
# 首先用主机名构造了一个Ftp对象(即ftp),然后用这个ftp调用不带任何参数的login()函数即表示要匿名登录这个Ftp服务器,如果登录过程中没有产生异常,则表明匿名登录成功,否则匿名登录失败!
def anonScan(hostname): #参数是主机名
    try:
        with ftplib.FTP(hostname) as ftp:#创建Ftp对象
            ftp.login() #Ftp匿名登录
            print(‘
[*] ‘ + str(hostname) + " FTP Anonymous login successful!") #不抛出异常则表明登录成功
            return True
    except Exception as e:#抛出异常则表明匿名登录失败
         print(‘
[-] ‘ + str(hostname) + " FTP Anonymous logon failure!")
         return False

# FTP弱口令扫描==暴力破解
# Ftp弱口令的扫描依赖于用户名和密码字典,我们的实验环境中会提供 pwd.txt 作为密码字典,字典的格式如下图所示:
# 用户名:密码

# 循环从字典中读取用户名和密码并尝试登陆,登陆成功则表明找到用户名和密码。由于这个函数将主机名定义成了可以用“,”分割的字符串。找到密码并不会终止程序,而是会继续扫描其他主机的弱口令,直到所有的主机都扫描一遍。
def vlcLogin(hostname, pwdFile):#参数(主机名,字典文件)
    try:
        with open(pwdFile, ‘r‘) as pf:#打开字典文件
            for line in pf.readlines(): #循环读取字典文件中的每一行
                time.sleep(1) #等待1秒
                userName = line.split(‘:‘)[0] #从读取的内容中取出用户名
                passWord = line.split(‘:‘)[1].strip(‘/r‘).strip(‘/n‘) #从读取的内容中取出密码
                print(‘[+]‘+str(hostname)+‘:Trying: ‘ + userName + ‘:‘ + passWord)
                try:
                    with ftplib.FTP(hostname) as ftp:#以主机名为参数构造Ftp对象
                        ftp.login(userName, passWord) #使用读取出的用户名密码登录Ftp服务器
                        #如果没有产生异常则表示登录成功,打印主机名、用户名和密码
                        print(‘[*] ‘ + str(hostname) + ‘ FTP Login successful: ‘+ userName + ‘:‘ + passWord)
                        return (userName, passWord)
                except Exception as e:
                # 产生异常表示没有登录成功,这里我们不用管它,继续尝试其他用户名、密码
                    pass
            print("破解失败")

    except IOError as e:
            print(‘Error: the password file does not exist!‘)
            print(‘[-] Cannot crack the FTP password, please change the password dictionary try again!‘)
            return (None,None)

def main():
    parser = argparse.ArgumentParser(description=‘FTP Scanner‘)
    # 添加-H命令dest可以理解为咱们解析时获取-H参数后面值的变量名,help是这个命令的帮助信息
    parser.add_argument(‘-H‘, dest=‘hostName‘, help=‘The host list with ","space‘)
    parser.add_argument(‘-f‘, dest=‘pwdFile‘, help=‘Password dictionary file‘)
    options = None
    try:
        options = parser.parse_args()
    except:
        print(parser.parse_args([‘-h‘]))

    ip = str(options.hostName)
    pwdFile = str(options.pwdFile)

    if  anonScan(ip):pass
    else:vlcLogin(ip,pwdFile)



if __name__ == ‘__main__‘:
    main()

 

 

 

 

简单端口扫描器

 

这里使用多线程的操作是很有必要的。这里,一个很自然的思路就是为每一个端口单独开一个线程进行扫描。 
所以你也可以将需要扫描的端口列表定为从Nmap中得到的前1000个使用频率最高的端口,例如下面:
port_list = [1,3,6,9,13,17,19,20,21,22,23,24,25,30,32,37,42,49,53,70,79,80,81,82,83,84,88,89,99,106,109,110,113,119,125,135,139,143,146,161,163,179,199,211,222,254,255,259,264
,280,301,306,3]

  

对于一个给定的ip地址,扫描的过程是这样的: 
1. 每一个端口创建一个线程,添加到线程列表
2. 利用connect_ex函数对该(ip,port)进行连接操作。 
3. 调用thread.start()和thread.join()方法,使扫描的子线程开始工作并且命令主线程等待子线程死亡后再结束。
4. 重复这个过程直到所有的端口都被扫描过。

  

 

 

import socket, time, threading
socket.setdefaulttimeout(3)

def socket_port(ip,port):
    """
    输入IP和端口号,扫描判断端口是否开放
    """

    try:
        if port>=65535:
            print(‘端口扫描结束‘)
        s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        result=s.connect_ex((ip,port)) #返回值为0则表示端口open
        if result==0:
            print(ip+‘:‘,port,‘端口开放‘)
        s.close() #
    except:
        print(‘端口扫描异常‘)



def ip_scan(ip,thread_list):
    """
    输入IP,扫描IP的0-65534端口情况
    """

    try:
        print(‘开始扫描 %s‘ % ip)
        start_time=time.time()
        for i in range(0,65534):
            t = threading.Thread(target=socket_port,args=(ip,i))
            t.start()
            thread_list.append(t)
        for thread in thread_list:
            thread.join()
        print(‘扫描端口完成,总共用时 :%.2f‘ %(time.time()-start_time))
    except:
        print(‘扫描ip出错‘)


if __name__==‘__main__‘:
    ip=input(‘Input the ip you want to scan:
‘)
    thread_list=[]
    lock = threading.Lock()
    ip_scan(ip,thread_list)

  

 





以上是关于Python 实现端口扫描的主要内容,如果未能解决你的问题,请参考以下文章

Python 实现端口扫描

运维脚本:python实现批量IP端口扫描

Python实现端口扫描,只需做这几步走战略

Python实现端口扫描

python实现端口状态扫描

Python 第三方模块pythonnmap来实现高效的端口扫描