python 编写端口扫描器

编写一个端口扫描器(TCP全连接扫描)

借鉴于:《python绝技:运用python成为顶级黑客》

需要用到的模块:

socket
optparse(感觉这个不用也可以,但可以学习一下这个模块)

模块小讲解:

socket:
主要用来构建TCP连接,发送包,和接收包
百度上对于该模块的说明以及很详细了
比如这个:https://www.cnblogs.com/aylin/p/5572104.html

TCP连接:
比如向一个地址(或服务器)请求连接,你需要先给它发送一个请求连接的包。服务器收到包后,会回复给你一个确认包(该包会存放一些该服务器的信息),若是reset包则说明该端口是关闭的。你收到这个包后,再回复服务器一个包。这样你的主机和那服务器就建立好了连接。(详情参见TCP/IP三次握手)

如果仅仅只是用于扫描,就不用把TCP连接建立完(否则很费时间),只需要当你向服务器发送一个包后,只要你收到了该服务器回复的确认包,那就可以说明该地址(服务器)的该端口是开放的。相反,如果是reset包,则说明该端口是关闭的。

optparse:
用来给自己写的函数 设置如何输入,输入什么类型的值,以及设置帮助说明(有点难理解?看看下面吧)
如何使用:
1.载入OptionParser类,新建对象: OptionParser()
parser=OptionParser()

2.添加选项: add_option(…)
例如:
parser.add_option('-H', dest='tgtHost', type='string', help='specify target host')
意思是:我对函数设置了一个操作,这个操作的使用方式是-H,后面输入的参数赋值给tgtHost,参数的类型必须是string, 使用-help可以获取帮助信息(这里就是specify target host)
这样我们在 命令行下 使用这个python函数时,则需要下面的形式进行使用:
传递参数:-H 172.2.22.222 (172.2.22.222将传递给形参tgtHost)
获取帮助则是:-H -help
再通过
tgtHost = options.tgtHost
将接收到的tgtHost参数递出,在这里也可以对参数进行切片等操作
例如:

tgtHost = str(options.tgtHost).split('.')  #根据 . 进行分割

则实际传递出去就变成了[‘172’ ,‘2’ ,‘22’, ‘222’ ] 这样一个list

3.参数解析: parse_args()
用来传出之前得到的输入
parse_args() 返回的两个值:
options,它是一个对象,保存有之前接收到的命令行参数值。
比如通过options.tgtHost就可以得到之前输入的‘172.2.22.222’
args ,它是没被解析的命令行参数的列表。

如果还不太清楚可以参见下:https://www.jianshu.com/p/bec089061742
或者看看接下来的代码

照着书上敲的代码:

一些说明:接下来,我们要生成两个函数connScan和portScan。portScan函数以参数的形式接收主机名和目标端口列表。它首先会尝试用gethostbyname()函数确定主机名对应的IP地址。接下来,它会使用connScan函数输出主机名(或IP地址),并使用connScan()函数尝试逐个连接我们要连接的每个端口。connScan函数接收两个参数:tgtHost和tgtport,它会去尝试建立与目标主机和端口的连接。如果成功,connScan将打印出一个端口开放的消息。如果不成功,它会打印出端口关闭的消息。

def connScan(tgtHost,tgtPort):
    try:
        connSkt=socket(AF_INET,SOCK_STREAM)
        	 #创建socket对象
   			# socket = socket.socket( family, type )
        	#family参数代表地址家族,可为AF_INET或AF_UNIX。AF_INET家族包括Internet地址,AF_UNIX家族用于同一台机器上的进程间通信。
       		#type参数代表套接字类型,可为SOCK_STREAM(流套接字)和SOCK_DGRAM(数据报套接字)。
        connSkt.connect((tgtHost,tgtPort)) 	 #以元组(host,port)的形式表示地址  #连接到address处的套接字。一般,address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
        connSkt.send("violentpython\r\n")  		#调用send,并采用字符串形式向客户发送信息。send方法返回已发送的字符个数。 使用recv方法从客户接收信息
        results=connSkt.recv(100)   #接受套接字的数据。数据以字符串形式返回,()内是指定最多可以接收的数量
        print('[+]%d/tcp open'% tgtPort)
        print('[+] '+str(results))
        connSkt.close()   #关闭TCP连接
    except:
        print('[-]%d/tcp closed'% tgtPort)


def portScan(tgtHost,tgtPorts):
    try:
        tgtIP=gethostbyname(tgtHost)  	# gethostbyname 返回的是主机名的IPv4 的地址格式,如果传入的参数是IPv4 的地址格式,则返回值跟参数一样,这个函数不支持IPv6 的域名解析
    except:
        print('[-] cannot resolve "s": Unknown host' %tgtHost)
        return
    try:
        tgtName=gethostbyaddr()  #返回对应于给定 地址 的包含主机名字和地址信息的hostent结构指针
        print('\n[+] Scan Results for:' +tgtName[0])
    except:
        print('\n[+] Scan Results for:' +tgtIP)
    setdefaulttimeout(1)  #设置全局的超时时间为1s,即当socket尝试重连到1秒时,就会停止一切操作
    for tgtPort in tgtPorts:     #因为可能的输入为多个端口
        print('Scanning port' +tgtPort)
        connScan(tgtHost,int(tgtPort))


def main():
    parser = optparse.OptionParser('usege %prog' + '-H  -P ')  #usage 帮助部分一般在 OptionParser 初始化时输入,为第一个参数, 也可以用具体形参名指定. 可以使用 %prog 来表示当前的程序名.
    parser.add_option('-H', dest='tgtHost', type='string', help='specify target host')    #定义parser的操作,这里说明了使用方式为: -H tgtHost   查看帮助就是:-H -help
    parser.add_option('-P', dest='tgtPort', type='string', help='specify target port')   #定义了parser另一个操作,这里说明了使用方式为:-P tgtPort  查看帮助就是:-P -help
    (options, args) = parser.parse_args()      #parse_args() 返回的两个值(options,args),options是一个对象,保存有之前接收到的命令行参数值,可以通过options.tgtHost获取之前输入的tgtHost。  args 是没被解析的命令行参数的列表。
    tgtHost = options.tgtHost     #通过options.tgtHost获取之前输入的tgtHost,并传递
    tgtPorts = str(options.tgtPort).split(',')    #对options.tgtPort按,切片,后传递
    if (tgtHost == None) | (tgtPorts[0] == None):
        print('[-] you must specifyn a target host and port[s].')
        exit(0)
    portScan(tgtHost,tgtPorts)

if __name__=='__main__':
    main()

因为使用的是pycharm编译,需要通过一些设置实现命令行式输入参数,设置方式如下:python 编写端口扫描器_第1张图片

python 编写端口扫描器_第2张图片
这之后再运行即可

附上一个运行结果:

-H 112.74.29.222 -P 80,20,21
[+] Scan Results for:112.74.29.222
Scanning port80
[-]80/tcp closed
Scanning port20
[-]20/tcp closed
Scanning port21
[-]21/tcp closed

至于书上的多线程扫描,就先放着吧,以后有空再说。
然后,就没了…
该文章当中optparse模块部分讲解,由自己理解的内容居多,如果有错误或不足,欢迎指出。

你可能感兴趣的:(python)