Python安全之NMAP模块满足客户爸爸的任性需求

背景:
客户爸爸最近突然要求我对公司所有IP进行一次操作系统识别的扫描。听起来这个要求并无过分,然而却有以下难点:
1、客户爸爸不能提供具体要扫描的IP地址,只能提供整个IP规划。甚至连一个EXCEL表格的子网都无法提供,仅仅丢了一个用于分配子网的某应用系统给我。(客户爸爸连自己的网内终端的操作系统都搞不清楚,资产识别这方面的管理可见一斑,更别指望提供别的了。)
2、客户爸爸提供的子网规划异常混乱,里面既有32位掩码、30位掩码的设备用IP,也有16位、15位、13位掩码的海量IP池。体现不出明显的包含关系,需要自己去梳理判断。
3、客户爸爸的体量超乎想象,全国各地都有它的组织,19到24位掩码之间的子网都有400多个。折合IP能有几十万。
4、客户爸爸不接受一个报告,必须每一个组织一个报告,方便他们阅读并发放给对应组织。
分析:
1、子网梳理:经过分析发现,客户爸爸的子网掩码在19到24位间是分配给具体的组织的(分子公司、项目组、商业体等)。那么我需要先去掉表格(自己导出的)中的类似16位、15位掩码的大区子网,去掉类似30位、32位的特殊设备(如路由器、VPN)等使用的子网。最终保留一个子网对应组织的关系。原始表如下图(乱)。
原始表
2、操作系统识别方法:用天镜、Nessus等扫描器都可以,然而他们输出的报告都太臃肿无法满足客户的需要,杀鸡焉用牛刀?况且要在扫描器上创建400多个任务,然后再导出400多份报告也太痛苦了(当然可以使用爬虫自动化,但也无比麻烦)。那么最好的选择无疑是Python的Nmap模块了。
3、输出报告设计:
1)每个子网一个报告,报告以子网所在的组织命名
2)报告只显示3列,IP、开放端口、操作系统
代码实现:
代码部分分两个文件,一个用于处理子网,另一个用于nmap识别操作系统并输出报告。
子网处理代码把ip.xls的文件经过处理后输出到new_ip.xls,如下:

import xlrd #读excel模块
import xlwt #写excel模块

def read_excel(excel_name,sheetname):
    # 打开Excel文件
    wb = xlrd.open_workbook(excel_name)
    sheet = wb.sheet_by_name(sheetname)
    dic = {}

    # 把第2列作为字典的键,一行数据保存为列表,作为字典的值。列表中也包含第一列的值哦
    for i in range(sheet.nrows-1):
        lis = []
        for j in range(sheet.ncols):
            lis.append(sheet.cell(i+1,j).value)
        dic[sheet.cell(i+1,1).value] = lis
    find_and_delete(dic)

def find_and_delete(dic):
    for k in list(dic.keys()):  #这里一定要遍历列表,如果遍历字典就会报错,原因是字典在遍历过程中不能pop
        if '/30' in str(k) or '/32' in str(k) or '/15' in str(k) or '/16' in str(k) or '/17' in str(k):
            dic.pop(k)
    write_excel(dic)

def write_excel(dic):
    book = xlwt.Workbook(encoding='utf-8', style_compression=0) #创建对象
    sheet = book.add_sheet('Subnets', cell_overwrite_ok=True)
    x = -1   #单元格x坐标
    for i in dic.keys():
        x += 1
        y = 0   #单元格y坐标
        for j in dic[i]:    #列表中的元素就是单元格的值
            sheet.write(x, y, j)
            y += 1
    book.save('new_ip.xls')

if __name__=='__main__':
    read_excel('ip.xls','Subnets')

Namp识别操作系统并输出报告代码如下:

import nmap
import xlrd #读excel模块
import xlwt #写excel模块
#import threading

# 逐行读取表里的内容,提取子网和对应的分公司名,子网用于扫描,分公司名作为扫描报告的文件名
def get_subnets(excel_name,sheetname):
    wb = xlrd.open_workbook(excel_name) # 打开excel文件创建对象
    sheet = wb.sheet_by_name(sheetname) # 获取表内容
    for i in range(sheet.nrows):    # 遍历所有的行
        lis = []    #创建空列表用于保存子网和公司名
        # threading_list=[]
        for j in range(1, 3):   # 每行只遍历第2列和第3列的内容,也就是子网和分公司名
            lis.append(sheet.cell(i + 1, j).value)  # 将每行2列、3列的内容作为元素添加到列表(+1是为了去掉首行)
        network = lis[0]
        company = lis[1]
        print(network, company)
        # for x in range(0, 11):
        #     th = threading.Thread(target=nmap_scan, args=(network,company,))
        #     threading_list.append(th)
        # for t in threading_list:
        #     t.start()
        # for t in threading_list:
        #     t.join()
        nmap_scan(network,company)

# namp扫描并将结果输出到excel表中作为报告
def nmap_scan(network,company):
    excel_name=company.replace('/','_')+'.xls'  # 将‘/’替换成‘_’,否则不能作为文件名
    #创建excel对象以及先将首行写好
    book = xlwt.Workbook(encoding='utf-8', style_compression=0)  # 创建对象
    sheet = book.add_sheet('os', cell_overwrite_ok=True)
    style = xlwt.XFStyle()  # 初始化样式
    font = xlwt.Font()  # 为样式创建字体
    font.name = 'Times New Roman'
    font.bold = True  # 黑体
    style.font = font  # 设定样式
    sheet.write(0, 0, 'IP', style)  # 首行第一列
    sheet.write(0, 1, '开放端口', style)    # 首行第二列
    sheet.write(0, 2, '操作系统', style)    # 首行第三列
    x = 0   # 行数计数器

    #nmap扫描并获取ip、端口、操作系统
    nm=nmap.PortScanner()  #实例化
    os_scan=nm.scan(hosts=network,arguments='-sS -O --open')    # nmap使用的关键参数
    os_scan_d1=os_scan['scan']  # 取结果的scan键的值(对我这个任务来说有用的信息在这里)
    for v in os_scan_d1.values():
        x+=1    #行数计数器,用于后面写入excel
        ip = v['addresses']['ipv4'] # 取IP
        try:
            os = v['osmatch'][0]['name']    # 取操作系统类型,因为有些识别不到操作系统,所以用了try避免报错程序结束
        except:
            pass
        portlist = []   #取端口的空列表
        for p in v['tcp'].keys():
            portlist.append(str(p)) #将每个端口都加到列表中
            ports = ','.join(portlist)  #将列表中的所有元素以‘,’号连接成一个字符串,用于写入excel(因为单元格不能写列表)
        #print(ip, ports, os)

        #以下将nmap的结果ip, ports, os写入excel表
        sheet.write(x, 0, ip)
        sheet.write(x, 1, ports)
        sheet.write(x, 2, os)
    sheet.col(0).width = 4000   #第1列宽度
    sheet.col(1).width = 8000
    sheet.col(2).width = 10000
    book.save(excel_name)   #保存为以分公司名命名的excel文件

if __name__=="__main__":
    get_subnets('new_ip.xls','Subnets') #传入的是excel名和表名

最终结果:
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值