在学习完《Python绝技》一章后,认真的总结下笔记。
常见的端口扫描是基于TCP三次握手或者是四次挥手过程,常见的是发送一个TCP syn包到指定主机的指定端口,根据返回的结果判断该端口是否开放。
1. TCP端口扫描根据不同的发包可以分为:
(1)TCP SYN扫描:也称半开放扫描,该扫描类型发送一个SYN的TCP链接数据包等待响应,当返回RST数据包表示端
口关闭,返回ACK表示端口开放。
(2)TCP NULL扫描:TCP空扫描设置TCP的标志头为零,如果返回一个RST数据包则表示这个端口是关闭的。
(3)TCP FIN扫描:TCP FIN扫描发送一个FIN数据包,请求关闭链接,等待一个个圆满的终止,如果返回RST数据包则
表示该端口是关闭的。
(4)TCP XMAS扫描:TCP XSMAS扫描设置PSH,FIN和URG TCP的标志位,如果返回RST数据包则表示这个端口是关
闭的。
2.扫描器设计思路:
(1)用户输入目标主机名和要扫描的常用端口列表,通过主机名得到目标网络的IP地址,用列表中的每一个端口号去链
接目标地址,最后确定端口上运行的特殊服务,可以发送特定的数据,并读取特定应用程序返回的标识。
(2)从用户那里接收主机名和端口,利用optparse标准库来解析命令行选项,调用optparse.OptionParser()创建一个
选项分析器,然后通过parser.add_option()函数来指定命令选项。
3.多线程端口扫描器应注意:
(1)多线程在速度上有明显优势,但是端口回显的信息可能是无序的,必须在同一时间内只有一个打印信息的函数,但
是访问端口的却可以是多个的,同时还要避免重复访问同一个端口,造成资源浪费。因此,必须使用信号量加锁
(2)使用acquire()加锁,新好像允许信号运行,如果锁定了必须要等到信号量的进程释放锁,利用信号量可以保证在同
一时间只有一个线程在打印输出结果
4.用到的模块及函数
(1)optparse模块:
optparse.OptionParser()
optparse.add_option()
optparse.parse_args()
以上三个函数不多介绍,基本就是命令解释的作用。如果感兴趣,请参考大神的文章:点击打开链接
(2)sock模块:
socket.gethostbyname(hostname):将主机名转换成IP地址返回
socket.gethostbyaddr(ip_address):传入一个Ip地址返回一个元组,其中包括主机名,别名列表和同一接口的Ip地址列表 socket.socket():创建一个socket
socket. connect(address,timeout,source_address):传入Ip地址和端口号返回一个socket对象,可以设置超时重连的时间
socket.send(data):项目地主机端口发送数据 socket.recv(size):从socket中接受size大小的字节数据
(3)threading模块:
threading.Semaphore(value=num):创建信号量为num的锁
threading.acquire():加锁
threading.release():解锁,释放信号量
5.程序代码:
# coding = UTF-8
import optparse
import socket
import threading
screenLock = threading.Semaphore(value = 1)
def connScan(tgtHost,tgtPort):
try:
connSkt = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
connSkt.connect((tgtHost,tgtPort))
connSkt.send('ViolentPython\r\n')
results = connSkt.recv(100)
screenLock.acquire()
print('[+]%d/tcp open' %tgtPort)
print('[+]' + results.decode('utf-8'))
except:
screenLock.acquire()
print('[-]%d/tcp closed' %tgtPort)
finally:
screenLock.release()
connSkt.close()
def portScan(tgtHost,tgtPorts):
try:
tgtIP = socket.gethostbyname(tgtHost)
except:
print("[-] Cannot resolve '%s': Unknown host" %tgtHost)
return
try:
tgtName = socket.gethostbyaddr(tgtIP)
print('\n [+]Scan Results for:' + tgtName[0])
except:
print('\n [+]Scan Results for:' + tgtIP)
socket.setdefaulttimeout(1)
for tgtPort in tgtPorts:
print('Scanning por' + str(tgtPort))
t = threading.Thread(target = connScan,args = (tgtHost,int(tgtPort)))
t.start()
def main():
parser = optparse.OptionParser('usage %prog -H -p ')
parser.add_option('-H',dest = 'tgtHost',type = 'string',help = 'specify target host')
parser.add_option('-p',dest = 'tgtPort',type ='int',help = 'specify target port')
(options,args) = parser.parse_args()
tgtHost = options.tgtHost
tgtPort = options.tgtPort
if(tgtHost == None) or (tgtPort == None):
print('[-] You must specify a target host and port[s]!')
exit(0)
portScan(tgtHost,args)
if __name__ == '__main__':
main()
运行结果如下: