DAY10:Python-nmap及 socket 模块编写简单脚本
1、Nmap 四大功能:
主机发现
端口扫描
服务版本侦测
操作系统侦测
2、基本扫描策略
2.1、无任何附加参数
分情况:如果是超级用户,无参数扫描等价于 sS 参数扫描(SYN,半连接否则,无参数扫描等价于 sT 参数扫描(TCP,完整连接)
nmap xxx.xxx.x.x
2.2、冗余
按照基本法,v 参数通常表示冗余。我们使用两个 v 参数表示将侦测过程原原本本的打印输出出来。
nmap -vv xxx.xxx.x.x
2.3、指定端口号
这里 p 参数表示端口,标准写法后面跟的端口号之间没有空格。但是如果写一个空格也并无妨。4
nmap -p22 xxx.xxx.x.x
nmap -p 1-200 xxx.xxx.x.1 #-p参数 #规定端口范围扫描
2.4、操作系统侦测
操作系统侦测有两个参数选项,其一是参数 O,其二是参数 A,后者乃前者的冗余版本。更多的使用 A 参数,以得到更多的信息。
nmap -O xxx.xxx.x.x
nmap -A xxx.xxx.x.x
2.5、只进行主机发现
主机发现的手段不下几十种,但是最常用的却是 sn 参数,它表示 “使用 ping 扫描来侦测存活的主机,而不进行端口扫描”。
root@docker:~# nmap -sn xxx.xxx.x.x
Nmap scan report for xxx.xxx.x.x
Host is up (0.00034s latency).
MAC Address: xx:xx:xx:xx
2.6、跳过主机发现
有时候对方主机开启了防火墙(这是很自然的事情),可能过滤掉了你发送的 ICMP 协议数据包,这样如果想要使用 sn 参数来进行主机发现就不管用了,产生的结果也不可靠。于是你不得不使用 Pn 参数,它假设所有的目标 IP 均为存活,并一个一个主机的进行端口扫描,你懂的这样会牺牲一些时间作为代价。
nmap -Pn xxx.xxx.x.x
2.7、扫描和版本号侦测
该选项通过侦测开放的端口来判断开放的服务,并试图检测它的版本。虽然 A 选项也能做到,但是要检测开放的服务版本,sV 一定是最合适的。
nmap -sV xxx.xxx.x.x
2.8、UDP扫描
之前我们的扫描都是针对 TCP 的,而有些服务却是建立在 UDP 协议上的。比如 NTP(123端口)、SNMP(161端口)等服务,就必须使用 UDP 协议进行扫描。
nmap -sU xxx.xxx.x.x
3、python-nmap
两个常用类
3.1、PortScanner() 类
实现了一个 nmap 工具的端口扫描功能的封装
Class PortScanner(object):
def get_nmap_last_output #返回文本输出(可用于调试)
def nmap_version(self) #检查nmap的版本信息
def listenscan(self,host='127.0.0.1') #不进行扫描,但解析一个目标主机并返回一个列表
import nmap
nm=nmap.PortScanner()
nm.scan('www.baidu.com','22,80,443,8080','-sV')
def all_hosts(self) #以列表形式返回目标ip
nm.all_hosts()
def command_line(self) #返回输入的命令行
def scaninfo() #返回nmap扫描信息,格式为字典类型
nmscaninfo()
def scanstats() #以结构体形式返回扫描状态
def has_host(self,host) #若主机有回应就返回true
nm['14.215.177.38'].all_tcp() #返回扫描TCP协议端口的信息
nm['14.215.177.38'].hostname() #返回域名
nm['14.215.177.38'].state() #返回目标主机状态
nm['14.215.177.38'].all_protocols() #返回扫描协议
3.2、PortScannerHostDict() 类
实现了存储与访问主机的扫描结果
Class PortScannerHostDict(object):
hostname(self)
hostname()
tcp()
all_protocols()
hostname(self) #返回扫描对象的主机名
nm['192.168.1.22'].hostname()
u'SN2013-08-022'
state(self) #返回扫描对象的状态,包括4种状态(up、down、unknown、skipped)
nm['192.168.1.22'].state()
u'up'
all_protocols(self) #返回扫描的协议
nm['192.168.1.22'].all_prococols()
[u'tcp']
all_tcp(self) #返回TCP协议扫描的端口
nm['192.168.1.22'].all_tcp()
[22,80]
tcp(self,port) #返回扫描TCP扫描协议port(端口)的信息
nm['192.168.1.22'].tcp(22)
{'state': u'open','reason':u'syn-ack','name':u'ssh'}
4、socket 模块
4.1、socket()
套接字,应用程序通常通过套接字,来向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯
语法:
socket.socket([family[, type[, proto]]])
family #套接字家族可以使 AF_UNIX 或者 AF_INET。
type #套接字类型可以根据是面向连接的还是非连接分为 SOCK_STREAM 或 SOCK_DGRAM。
protocol #一般不填默认为 0。
4.2、Socket 对象(内建)方法
'''客户端套接字'''
s.connect() #主动初始化TCP服务器连接,。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误
'''服务器端套接字'''
s.listen() #开始TCP监听.backlog指定在拒绝连接前,操作系统可以挂起的最大连接数量.该值至少为1,大部分应用程序设为5就可以
s.accept() #被动接受TCP客户端连接,(阻塞式)等待连接的到来
s.bind() #绑定地址(host,port)到套接字, 在 AF_INET下,以元组(host,port)的形式表示地址
'''公共用途的套接字函数'''
s.close() #关闭套接字
s.recv() #接收 TCP 数据,数据以字符串形式返回,bufsize 指定要接收的最大数据量
s.send() #发送 TCP 数据,将 string 中的数据发送到连接的套接字
s.close() #关闭套接字
s.getsockname() #返回套接字自己的地址。通常是一个元组(ip,port)
s.gettimeout() #返回当前超时期的值,单位(秒),如果没有设置超时期,则返回None
4.3、Internet 模块
'''网络协议 功能用处 端口 python模块'''
HTTP 网页访问 80 httplib, urllib, xmlrpclib
NNTP 阅读和张贴文章 119 nntplib
FTP 文件传输 20 ftplib, urllib
SMTP 发送邮件 25 smtplib
POP3 接收邮件 110 poplib
IMAP4 获取邮件 143 imaplib
Telnet 命令行 23 telnetlib
Gopher 信息查找 70 gopherlib, urllib
示例:
1、判断主机是否存活
import nmap
nm = nmap.PortScanner()
nm.scan(hosts = '172.17.2.0/24', arguments='-n -sP -PE')
up_hosts = nm.all_hosts() # 获取存活主机列表
print(up_hosts)
2、单个IP扫描
import nmap # 导入 nmap.py 模块
nm = nmap.PortScanner() # 获取 PortScanner 对象
nm.scan('127.0.0.1', '22-443') # 扫描主机 127.0.0.1 端口号 22-443
nm.command_line() # 获取用于扫描的命令行:nmap -oX - -p 22-443 127.0.0.1
nm.scaninfo() # 获取本次扫描的信息 {'tcp': {'services': '22-443', 'method': 'connect'}}
nm.all_hosts() # 获取所有扫描到的主机
nm['127.0.0.1'].hostname() # 获取 127.0.0.1 的主机名
nm['127.0.0.1'].hostnames() #获取list格式的主机名dict 127.0.0.1 #如[{'name':'hostname1', 'type':'PTR'}, {'name':'hostname2', 'type':'user'}]
nm['127.0.0.1'].state() # 获取主机 127.0.0.1 的状态 (up|down|unknown|skipped)
nm['127.0.0.1']['tcp'].keys() # 获取所有tcp端口
nm['127.0.0.1'].all_tcp() # 获取所有tcp端口 (已排序)
nm['127.0.0.1'].all_udp() #获取所有tcp端口
nm['127.0.0.1'].all_ip() #获取所有tcp端口
nm['127.0.0.1'].all_sctp() #获取所有tcp端口
nm['127.0.0.1'].has_tcp(22) # 是否含有主机 127.0.0.1 的 22 端口的信息
nm['127.0.0.1']['tcp'][22] # 获取主机 127.0.0.1 22 端口(tcp)的所有信息
nm['127.0.0.1'].tcp(22) # 获取主机 127.0.0.1 22 端口的所有信息
3、主机存活扫描与帮助手册
import nmap
import optparse
def NmapScan(targetIP):
nm=nmap.PortScanner() # 实例化 PortScanner 对象
try:
result=nm.scan(hosts=targetIP,arguments='-sn -PE ') #hostse为目标IP地址,arguments为nmap扫描参数 -sn:使用ping进行扫描 -PE:使用icmp的echo请求包
state=result['scan'][targetIP]['status']['state'] #对扫描结果进行切片 提取主机扫描信息
print("[{}] is [{}]".format(targetIP,state))
except Exception as e:
pass
if __name__=="__main__":
parser=optparse.OptionParser('usage:python %prog -i ip \n\n'
'Example:python %porg -i 172.16.0.172[172.16.0.1-200]\n')
parser.add_option('-i','--ip',dest='targetIP',default='172.16.0.1',type='string',help='target ip address')
options,args=parser.parse_args() #添加目标ip参数 -i
if '-' in options.targetIP:
for i in range(int(options.targetIP.split('-')[0].split('.')[3]),int(options.targetIP.split('-')[1])+1):
NmapScan(options.targetIP.split('-')[0] + '.' + options.targetIP.split('.')[1] + '.' + options.targetIP.split('.')[2]) + '.' + str(i)
else:
NmapScan(options.targetIP)
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = sock.connect_ex(("127.0.0.1", 80))
if result == 0:
flag = True
else:
flag = False