入侵检测自动化一条龙

简介

Breaking Point System(BPS),一个用于根据攻击名称生成响应数据包的设备。日常编写入侵防御(IPS)规则的时候,就是根据BPS设备产生的数据包来写规则,首先使用snort做测试,最后把写好的全部规则升到公司设备上,再做一遍测试。这中间有很多繁杂的操作,这里介绍如何编写脚本来实现工作减负。

筛选文件

首先,我们拿到的是这样的一张Excel表,这里面包含了所有负责人的任务,以及,我们会拿到成百上千个数据包,里面包含了所有人的数据包。我们我要拿到属于自己的那张Excel表,这一点,可以通过Excel自带的“筛选”可以做到,然后是筛选出自己的数据包,这就需要脚本了。
在这里插入图片描述

脚本

下面的代码块里其实是两个脚本,上面那个跟下面那个(被注释)的区别是后者支持导出结果,前者不支持。
使用方法:
【数据包中,有的可能是空包,有的可能不存在,这里都能检查出来】
1:直接运行脚本,
2:复制存放所有数据包的文件路径,到脚本中
3:新建一个文件夹,把文件路径放到脚本中
4:复制Excel表bps攻击名的那一列(需要事先过滤一下Excel表)
5:结束
在这里插入图片描述

import os
import shutil
import copy

print('''
工具会根据你输入的多行文本,逐行去搜索目标文件夹中的所有文件
只要你输入的某行字符存在于某文件中,软件就把符合要求的文件放到一个新文件夹中
如果你输入的某行字符用逗号分割了,软件取第一个逗号前的字符串作为该行字符
避免出错,请确保新文件夹是空文件夹!!!
''')

# 一个隐藏功能,如果是pcap后缀的文件
# 会在上面说到的新文件夹中再新建一个文件夹存储空数据包
path1 = input(r'1:请给出源文件夹路径,或按回车键选择脚本所在路径:')
if len(path1):
    pass
else:
    path1 = os.getcwd()

path2 = input(r'2:请给出目标文件夹路径:')
path3 = os.path.join(path2, '空数据包')  # path3用来存储空数据包
os.makedirs(path3)  # 创建用来存放空数据包的文件夹
count = 0
empty_packet = []  # 用来最后打印有效数据包
full_packet = []  # 用来最后打印空数据包

# 下面的代码用来接收用户的多行输入
# 下面的代码允许输入:由复制粘贴进来的多行字符
print("请输入关键字(输入quit结束输入):")
word = []  # 存储用户输入的内容
while True:
    char = input()
    char = char.strip()
    # 下面的两个if主要是判断输入的内容中是否:某行是空白,某行用逗号分割了字符串(主要适用于多个tid)
    if char == '':
        continue
    if ',' in char:
        char = char.split(',', 1)[0]
    if 'quit' in char:
        break
    word.append(char)
lost_word = copy.deepcopy(word)  # 存储用户输入的内容中,如果有的内容无法找到相关文件,就打印出来通知用户

# 下面的代码用来实现文件的复制
for current_folder, list_folders, files in os.walk(path1):
    for f in files:  # 用来遍历所有的文件,只取文件名,不取路径名
        if f.endswith('pcap'):  # 操作数据包
            for w in word:  # 用来遍历用户每行的内容
                if w in f:  # 判断用户输入的这行内容是否在文件名中
                    copy_f = current_folder + '\\' + f  # 给出要复制的文件的路径

                    # 接下来判断这个文件应该放到path2还是path3
                    if os.path.getsize(copy_f) == 24:
                        count += 1
                        shutil.copy(copy_f, path3)
                        print('筛选出{}'.format(copy_f))
                        empty_packet.append(w + ':' + os.path.basename(copy_f))  # 保存数据包时,只保留文件名,不保留路径
                    else:
                        count += 1
                        shutil.copy(copy_f, path2)
                        full_packet.append(w + ':' + os.path.basename(copy_f))  # 保存数据包时,只保留文件名,不保留路径
                        print('筛选出{}'.format(copy_f))
        else:  # 操作普通文件
            for w in word:  # 用来遍历用户每行的内容
                if w in f:  # 判断用户输入的这行内容是否在文件名中
                    copy_f = current_folder + '\\' + f  # 给出要复制的文件的路径
                    count += 1
                    shutil.copy(copy_f, path2)
                    print('筛选出{}'.format(copy_f))
print()
print('筛选完毕,筛选了{}个文件'.format(count))
print()
print('可用数据包共{}个'.format(len(full_packet)))
for fp in full_packet:
    print('可用数据包:' + fp)

print()
print('空数据包共{}个'.format(len(empty_packet)))
for ep in empty_packet:
    print('空数据包:' + ep)
if len(empty_packet) == 0:
    os.rmdir(path3)
    print('不存在空数据包,删除“空数据包”文件夹')

# 下面的代码用来存储path2路径中,用户输入的内容中查找失败的
find_files2 = os.listdir(path2)
for ff2 in find_files2:
    for user_word2 in lost_word:
        if user_word2 in ff2:
            lost_word.remove(user_word2)

# 下面的代码用来存储path3路径中,用户输入的内容中查找失败的
if os.path.isdir(path3):  # 判断path3是否存在
    find_files3 = os.listdir(path3)
    for ff3 in find_files3:
        for user_word3 in lost_word:
            if user_word3 in ff3:
                lost_word.remove(user_word3)
print()
print('不存在的数据包{}个'.format(len(lost_word)))
for lw in lost_word:
    print('未找到包含此关键字的文件:{}'.format(lw))

# os.system('pause')  # 在脚本中运行时可以删除此行

'''
下面的代码是个升级版,提供了把终端中显示的内容输出到path2路径中的一个txt文件中
'''
#
# import os
# import shutil
# import copy
#
# print('''
# 工具会根据你输入的多行文本,逐行去搜索目标文件夹中的所有文件
# 只要你输入的某行字符存在于某文件中,软件就把符合要求的文件放到一个新文件夹中
# 如果你输入的某行字符用逗号分割了,软件取第一个逗号前的字符串作为该行字符
# 避免出错,请确保新文件夹是空文件夹!!!
# ''')
#
# # 一个隐藏功能,如果是pcap后缀的文件
# # 会在上面说到的新文件夹中再新建一个文件夹存储空数据包
# path1 = input(r'1:请给出源文件夹路径,或按回车键选择脚本所在路径:')
# if len(path1):
#     pass
# else:
#     path1 = os.getcwd()
#
# path2 = input(r'2:请给出目标文件夹路径:')
# path3 = os.path.join(path2, '空数据包')  # path3用来存储空数据包
# path_result = os.path.join(path2, 'result.txt')  # 用来存储终端中输出的内容到一个文本中,方便用户使用数据,此为文本路径
# result = []  # 使用列表来存储终端中输出的内容
# os.makedirs(path3)  # 创建用来存放空数据包的文件夹
# count = 0
# empty_packet = []  # 用来最后打印有效数据包
# full_packet = []  # 用来最后打印空数据包
#
# # 下面的代码用来接收用户的多行输入
# # 下面的代码允许输入:由复制粘贴进来的多行字符
# print("请输入关键字(输入quit结束输入):")
# word = []  # 存储用户输入的内容
# while True:
#     char = input()
#     char = char.strip()
#     # 下面的两个if主要是判断输入的内容中是否:某行是空白,某行用逗号分割了字符串(主要适用于多个tid)
#     if char == '':
#         continue
#     if ',' in char:
#         char = char.split(',', 1)[0]
#     if 'quit' in char:
#         break
#     word.append(char)
# lost_word = copy.deepcopy(word)  # 存储用户输入的内容中,如果有的内容无法找到相关文件,就打印出来通知用户
#
# # 下面的代码用来实现文件的复制
# for current_folder, list_folders, files in os.walk(path1):
#     for f in files:  # 用来遍历所有的文件,只取文件名,不取路径名
#         if f.endswith('pcap'):  # 操作数据包
#             for w in word:  # 用来遍历用户每行的内容
#                 if w in f:  # 判断用户输入的这行内容是否在文件名中
#                     copy_f = current_folder + '\\' + f  # 给出要复制的文件的路径
#                     # 接下来判断这个文件应该放到path2还是path3
#                     if os.path.getsize(copy_f) == 24:
#                         count += 1
#                         shutil.copy(copy_f, path3)
#
#                         # 下面两行用来存储要打印出来的数据到result中
#                         result3 = '筛选出' + copy_f
#                         result.append(result3)
#
#                         print('筛选出{}'.format(copy_f))
#                         empty_packet.append(w + ':' + os.path.basename(copy_f))  # 保存数据包时,只保留文件名,不保留路径
#                     else:
#                         count += 1
#                         shutil.copy(copy_f, path2)
#
#                         # 下面两行用来存储要打印出来的数据到result中
#                         result2 = '筛选出' + copy_f
#                         result.append(result2)
#
#                         print('筛选出{}'.format(copy_f))
#                         full_packet.append(w + ':' + os.path.basename(copy_f))  # 保存数据包时,只保留文件名,不保留路径
#         else:  # 操作普通文件
#             for w in word:  # 用来遍历用户每行的内容
#                 if w in f:  # 判断用户输入的这行内容是否在文件名中
#                     copy_f = current_folder + '\\' + f  # 给出要复制的文件的路径
#                     count += 1
#                     shutil.copy(copy_f, path2)
#                     print('筛选出{}'.format(copy_f))
# print()
# print('筛选完毕,筛选了{}个文件'.format(count))
# result.append('筛选完毕,筛选了' + str(count) + '个文件')
# print()
# print('可用数据包共{}个'.format(len(full_packet)))
# result.append('可用数据包共' + str(len(full_packet)) + '个')
# for fp in full_packet:
#     print('可用数据包:' + fp)
#     result.append('可用数据包:' + fp)
#
# print()
# print('空数据包共{}个'.format(len(empty_packet)))
# result.append('空数据包共' + str(len(empty_packet)) + '个')
# for ep in empty_packet:
#     print('空数据包:' + ep)
#     result.append('空数据包:' + ep)
# if len(empty_packet) == 0:
#     os.rmdir(path3)
#     print('不存在空数据包,删除“空数据包”文件夹')
#
# # 下面的代码用来存储path2路径中,用户输入的内容中查找失败的
# find_files2 = os.listdir(path2)
# for ff2 in find_files2:
#     for user_word2 in lost_word:
#         if user_word2 in ff2:
#             lost_word.remove(user_word2)
#
# # 下面的代码用来存储path3路径中,用户输入的内容中查找失败的
# if os.path.isdir(path3):  # 判断path3是否存在
#     find_files3 = os.listdir(path3)
#     for ff3 in find_files3:
#         for user_word3 in lost_word:
#             if user_word3 in ff3:
#                 lost_word.remove(user_word3)
# print()
# print('不存在的数据包{}个'.format(len(lost_word)))
# result.append('不存在的数据包' + str(len(lost_word)) + '个')
# for lw in lost_word:
#     print('未找到包含此关键字的文件:{}'.format(lw))
#     result.append('未找到包含此关键字的文件:{}'.format(lw))
#
# # 下面的代码用来把终端中的内容输出到一个文本中
# a = open(path_result, 'w', encoding='utf8')
# for r in result:
#     a.write(r)
#     a.write('\n')
# a.close()
#
# # os.system('pause')  # 在脚本中运行时可以删除此行

批量跑snort

筛选出了数据包,也针对数据包写好了规则,有时候你不知道你这条规则能匹配多少个数据包,面对几十上百的数据包,你需要写个脚本来跑数据包

脚本

你可以很轻松的查看到你写的规则,匹配数据包的情况
1:你需要注意第28行,那个是跑snort的命令,根据你的情况进行适当调整
2:脚本默认是运行在脚本所在的文件夹,你可以使用os.chdir()来调节位置
3:然后可以直接运行脚本了
4:alert.txt表示告警的数据包,noalert.txt表示没有告警的数据包
在这里插入图片描述

# -*- coding:utf-8 -*-
from subprocess import Popen, PIPE
import os
import re
# import sys
# import shlex


class TestPacp(object):

    def __init__(self):
        self.pcaps = []     # 用来存储pcap后缀的数据包
        self.success = 0
        self.failed = 0
        self.stdout = ""
        self.stderr = ""

    # 用来获取pcap后缀的文件,并存储到列表里面
    def getFiles(self):
        files = os.listdir('./')
        for file in files:
            fileType = self.getFileType(file)
            if fileType == 'pcap':
                self.pcaps.append(file)

    def execute(self):
        for item in self.pcaps:
            command = r'snort -c C:\Snort\etc\snort.conf -l C:\Snort\log -r "{0}"'.format(item)
            try:
                p = Popen(command, stdout=PIPE, stderr=PIPE)        
                self.stdout, self.stderr = p.communicate()
            except:
                errmsg = "execute {0} error".format(item)
                print(errmsg)
            if self.handleResult(self.stderr, item):
                with open('alert.txt', 'a') as f:
                    f.write(item)
                    f.write('\n')
                continue
            # print(item)
            with open('noalert.txt', 'a') as f:
                f.write(item)
                f.write('\n')

    def handleResult(self, result, item):
        result_pattern = 'Alerts:\s+\d+\s+\(.+\)'
        num_pattern = '\d+\s'
        result = result.decode('utf-8')
        alerts = re.findall(result_pattern, result)
        if len(alerts) == 0:
            # with open("errmsg.txt", "a") as f:
            #     f.write(item)
            #     f.write('\n')
            return False
            # f.write(result)
            # sys.exit(-2)
        num = re.findall(num_pattern, alerts[0])
        if int(num[0].strip()) == 0:
            self.failed = self.failed + 1
            return False
        self.success = self.success + 1
        return True

    # 获取文件后缀
    def getFileType(self, file):
        fileType = os.path.splitext(file)[-1][-1]
        return fileType

    def run(self):
        self.getFiles()
        self.execute()
        msg = "数据包:{0}  告警个数:{1}  无告警个数:{2}".format(len(self.pcaps), self.success, self.failed)
        print(msg)


if __name__ == '__main__':
    if os.path.exists('alert.txt'):
        os.remove('alert.txt')
    if os.path.exists('noalert.txt'):
        os.remove('noalert.txt')
    t = TestPacp()
    t.run()
    # os.system("pause")

改版,下面的版本,是拿来就能直接用,工作在脚本所在文件夹,支持有中文名称的数据包

# -*- coding:utf-8 -*-
from subprocess import Popen, PIPE
import os
import re
import sys
import shlex

class TestPacp(object):

    def __init__(self):
        self.pcaps = []
        self.success = 0
        self.failed = 0
        self.stdout = ""
        self.stderr = ""

    def getFiles(self):
        files = os.listdir('./')
        for file in files:
            fileType = self.getFileType(file)
            if fileType == 'pcap':
                self.pcaps.append(file)

    def execute(self):
        for item in self.pcaps:
            command = r'snort -c C:\Snort\etc\snort.conf -l C:\Snort\log -r "{0}"'.format(item)
            try:
                p = Popen(command, stdout=PIPE, stderr=PIPE)
                self.stdout, self.stderr = p.communicate()
            except:
                errmsg = "execute {0} error".format(item)
                print(errmsg)
            if self.handleResult(self.stderr, item):
                with open('alert.txt', 'a') as f:
                    f.write(item)
                    f.write('\n')
                continue
            # print(item)
            with open('noalert.txt', 'a') as f:
                f.write(item)
                f.write('\n')
            
    def handleResult(self, result, item):
        result_pattern = 'Alerts:\s+\d+\s+\(.+\)'
        num_pattern = '\d+\s'
        # result = result.decode('utf-8')
        result = result.decode('gbk')
        alerts = re.findall(result_pattern, result)
        if len(alerts) == 0:
            # with open("errmsg.txt", "a") as f:
            #     f.write(item)
            #     f.write('\n')
            print(item+')))')
            return False
                # f.write(result)
                # sys.exit(-2)
        num = re.findall(num_pattern, alerts[0])
        if int(num[0].strip()) == 0:
            self.failed = self.failed + 1
            return False
        self.success = self.success + 1
        return True

    def getFileType(self, file):
        fileType = os.path.splitext(file)[-1][1:]
        return fileType

    def run(self):
        print('running...')
        self.getFiles()
        self.execute()
        msg = "数据包:{0}  告警个数:{1}  无告警个数:{2}".format(len(self.pcaps), self.success, self.failed)
        print(msg)

if __name__ == '__main__':
    if os.path.exists('alert.txt'):
        os.remove('alert.txt')
    if os.path.exists('noalert.txt'):
        os.remove('noalert.txt')
    t = TestPacp()
    t.run()
    print('done.')
    # os.system("pause")

批量删除文件

跑完数据包,你会发现,总有些数据包出现在noalert.txt中,即便最简单的规则也无法匹配它,因为数据包是有问题的,这些数据包可能有很多,你需要删除它

脚本

脚本可以在任意位置运行,被删除的文件会被丢到回收站
1:运行脚本
2:输入要操作的目标文件夹
3:输入noalert.txt中的数据
4:输入quit结束输入
5:结束
在这里插入图片描述

# -*- coding:utf-8 -*-
import os
import send2trash

print('''
删除文件plus版:支持根据你输入的多行文本,删除匹配的文件
''')
print('该脚本可以检查某文件夹下的所有文件')
print('通过你给出的关键字可以删除包含此关键字的所有文件')
print('被删除的文件可以通过回收站找回')
path = input(r'1:请给出路径,或按回车键选择脚本所在路径:')
if len(path):
    pass
else:
    path = os.getcwd()

print("2:请输入关键字(输入quit结束输入):")
word = []  # 存储用户输入的内容
while True:
    char = input()
    char = char.strip()
    # 下面的两个if主要是判断输入的内容中是否:某行是空白,某行用逗号分割了字符串(主要适用于多个tid)
    if char == '':
        continue
    if ',' in char:
        char = char.split(',', 1)[0]
    if 'quit' in char:
        break
    word.append(char)

print()
count = 0

for current_folder, list_folders, files in os.walk(path):
    for f in files:  # 遍历所有的文件
        for w in word:  # 遍历用户输入的所有内容
            if w in f:
                del_f = current_folder + '\\' + f  # 给出要删除的文件的路径
                send2trash.send2trash(del_f)
                count += 1
                print('已经删除:', del_f)

print('\n一共删除了{}个文件'.format(count))
os.system('pause')  # 在脚本中运行时可以删除此行

固网

填写数据包与tid对应的Excel表

简单来说,就是你只拿到一批数据包,领导给了你下面图片中的Excel表,你需要填入所有的数据包名字,以及对应的规则编号
在这里插入图片描述
1:首先,筛选数据包
使用“筛选文件”的脚本,把自己的数据包筛选出来

2:填写Excel表第一列
方法1:写一条有问题的规则,使用“批量跑snort”脚本拿到所有的数据包名称,直接粘贴到Excel表第一列
方法2:写一个小脚本,使用os.listdir()拿到目录下的所有文件的名字,复制粘贴到Excel表第一列
方法3:使用utools(一款软件)的复制路径功能,拿到所有数据包的绝对路径,然后用正则删除文件名前面的路径

3:编写规则
根据数据包写规则,由于大量存在一条规则匹配的那种攻击行为可以匹配几十个数据包的情况,所以需要一边写规则,一边使用“批量跑snort”测试。规则编写的差不多的时候,发现“批量跑snort”脚本中不出现“noalert.txt”说明规则编写完毕

4:如何把规则和数据包一一对应
一条规则匹配多个数据包,就意味着一个数据包可能对应多个规则。最近的一个固网任务中,近400个数据包,对应了20多条规则,那么,该如何把规则和数据包一一对应?
思路:使用“批量跑snort”测试得知一个规则对应的数据包之后,把他它写到Excel表中。这样只需要重复“批量跑snort”测试20来次就行,但是,填写Excel表就需要脚本了

脚本

1:脚本默认是运行在脚本所在的文件夹,你可以使用os.chdir()来调节位置
2:然后可以直接运行脚本了
3:输入告警的数据包对应的标记,不告警数据包对应的标记(可以只写1个,看需求)
4:结束
在这里插入图片描述

import openpyxl
import openpyxl.styles
import os
from openpyxl.utils import get_column_letter


def run(right, wrong):
    # 分别用来存储告警、不告警的数据包
    if os.path.exists('alert.txt'):
        success_list = read_file('alert.txt')
    else:
        success_list = []
    if os.path.exists('noalert.txt'):
        failed_list = read_file('noalert.txt')
    else:
        failed_list = []

    file = get_xlsx()  # 获取要操作的Excel表

    book = openpyxl.load_workbook(file)
    sheet = book.worksheets[0]  # 选择sheet1操作对象
    rows = sheet.max_row  # 获取行数,值是int型
    column = 6  # 设置添加的数据,写在第6列
    for i in range(1, rows):
        if sheet.cell(i, 1).value in success_list:  # 如果单元格的值在alert中找到了

            # 进行去重判断,判断单元格中有没有数据,有数据的话,有没有我即将要写入的这个数据
            if bool(sheet.cell(i, column).value):  # 如果单元格中有数据
                sheet.cell(i, column).value = str(sheet.cell(i, column).value)  # 防止单元格的数据类型不是字符串型
                if bool(right in sheet.cell(i, column).value):  # 如果,我们要写入单元格中的数据,已经存在过
                    pass  # 不再写入数据
                else:  # 如果,我们要写入的数据不在单元格中
                    sheet.cell(i, column).value = sheet.cell(i, column).value + ',' + right  # 那就写入数据
            else:  # 如果单元格中没有数据
                sheet.cell(i, column, right)  # 直接写入数据
            continue  # 在alert中找到了关键词,就跳过下面的noalert

        if sheet.cell(i, 1).value in failed_list:

            # 内容同上,只不过这里我们是检查noalert
            if bool(sheet.cell(i, column).value):  # 如果单元格中有数据
                sheet.cell(i, column).value = str(sheet.cell(i, column).value)  # 防止单元格的数据类型不是字符串型
                if bool(wrong in sheet.cell(i, column).value):  # 如果,我们要写入单元格中的数据,已经存在过
                    pass  # 不再写入数据
                else:  # 如果,我们要写入的数据不在单元格中
                    sheet.cell(i, column).value = sheet.cell(i, column).value + ',' + wrong  # 那就写入数据
            else:  # 如果单元格中没有数据
                sheet.cell(i, column, wrong)  # 直接写入数据

    # 设置对齐样式
    # 测试的时候发现,脚本填充的数据是左对齐的,但是鼠标双击选中单元格后,它就会变成”底端对齐“,没有”左对齐“,所以这里设置为左对齐
    # Alignment(horizontal=水平对齐模式,vertical=垂直对齐模式,text_rotation=旋转角度,wrap_text=是否自动换行)
    new_column = get_column_letter(column)  # 把列数(数字)转换为excel认识的字母
    cells = sheet[new_column]
    for cell in cells:
        alignment = openpyxl.styles.Alignment(horizontal="left", vertical="center", text_rotation=0, wrap_text=True)
        cell.alignment = alignment

    book.save(file)  # 保存excel表


# 用来读取存储告警、不告警的数据包
def read_file(file):
    with open(file, 'r', encoding='utf8') as f:
        return f.read()


# 请确保文件夹中只有一个xlsx文件,否则会出现问题
def get_xlsx():
    files = os.listdir()
    for file in files:
        if file.endswith('.xlsx'):
            return file


print('''
========固网专用工具========
软件描述:
软件检查alert.txt和noalert.txt ,当Excel表的第1列中的内容出现在txt文件中
就会在Excel表的第6列中输入你要标记的内容

注意事项:
1:请将告警的alert.txt和不告警的noalert.txt(二者可以只有一个),要操作的Excel表与此软件放一起【共3样东西】
2:请确保,存放txt文件和此软件的文件夹中,只存在1个Excel表
3:软件默认会把结果填写在第6列
4:软件填写在单元格中的数据都是不重复的(会去重)
5:软件填写在单元格中的数据默认是左对齐的
''')

r = input('请输入告警的单元格填写的数据:')
w = input('请输入不告警的单元格填写的数据:')
run(r, w)
os.system('pause')  # 在脚本中运行时可以删除此行

批量封装规则

近期拿到一批勒索病毒的数据包,长着下面的模样,任务目标就是封杀域名。
策略:先写出规则,在本地使用snort批量跑(主要是方便),确认规则无误之后再升到设备上。写出的规则是这样的

alert udp any any -> any any (msg:"1"; pcre:"/jovenesembajadoresdecristo.*?com/i"; metadata:service dns; sid:1; rev:1;)

使用正则来匹配数据包,其中,只有正则的内容,以及msg的内容和sid的内容变化的。所以,思路就是先手动获取所有数据包的所有域名,譬如下图中的域名altarek.com
在这里插入图片描述
1:手动逐个打开所有的数据包,复制域名粘贴到一个文本文件中
2:由于数据包中显示的.并非是16进制的\x2e(就是说,这个点并不真正的点,只是显示成了点),对着所有域名,使用内容替换,把.替换成.*?,这样就拿到了所有的正则
3:开始准备脚本

脚本

脚本的局限性在于应用场景局限,只能封装格式雷同的的规则
下面是两个代码,第一个代码用来生成符合设备要求的规则,第二个代码用来生成符合snort的规则
1:脚本在任意位置运行
2:手动粘贴你写好的规则
3:生成的结果放在桌面(需要手动修改第28行,61行,设置为你存放结果的路径)
在这里插入图片描述

'''
自动生成,升设备所用的规则
'''

# 获取用户的所有输入内容
print('''
工具会根据你写好的规则,对其进行封装,封装成什么样子取决于你
封装的格式在23行和56行
''')
print("请输入关键字(输入quit结束输入):")
word = []  # 存储用户输入的内容
while True:
    char = input()
    char = char.strip()
    if char == '':
        continue
    if 'quit' in char:
        break
    word.append(char)

result = []
for i in range(len(word)):
    a = 'pcre:"/{}/i"; metadata:service dns;'.format(word[i])
    print(a)

    result.append(a)

path_result = r'C:\Users\asuka\Desktop\结果.txt'
a = open(path_result, 'w', encoding='utf8')
for r in result:
    a.write(r)
    a.write('\n')
a.close()

# os.system('pause')  # 在脚本中运行时可以删除此行
#
# '''
# 查封域名专用
# 自动生成,snort所用的规则
# '''
#
# # 获取用户的所有输入内容
# print("请输入关键字(输入quit结束输入):")
# word = []  # 存储用户输入的内容
# while True:
#     char = input()
#     char = char.strip()
#     if char == '':
#         continue
#     if 'quit' in char:
#         break
#     word.append(char)
#
# result = []
# for i in range(len(word)):
#     a = 'alert udp any any -> any any (msg:"{}"; pcre:"/{}/i"; metadata:service dns; sid:{}; rev:1;)'.format(i,word[i],i)
#     print(a)
#
#     result.append(a)
#
# path_result = r'C:\Users\asuka\Desktop\结果2.txt'
# a = open(path_result, 'w', encoding='utf8')
# for r in result:
#     a.write(r)
#     a.write('\n')
# a.close()
#
# # os.system('pause')  # 在脚本中运行时可以删除此行
#

规则上传设备

规则写好,snort测试无误,就可以升到设备上,固网的时候,写的规则是同一种类型,意味着填写规则到平台上的时候,虽然变量很多,但是对于我们来说,真正意义上不可控的变量其实是规则的中英文标题,所以,脚本的局限性是只适用于变种规则
这里不方便截图,只贴代码

脚本

脚本可以在任意位置运行
1:需要手动修改第18行,指定最后一个变种的tid(防止覆盖别人的规则)
2:由于所有的中英文标题,都是在上一个tid的基础上,对变种号做加1操作,所以,运行脚本的时候,请确保没有人动你的规则,没有人跟你写同一种名称的规则
3:第21行用来指定输出结果的路径,结果中会包含规则tid及对应的中文攻击名

import pyautogui
import pyperclip
import csv
import re

print('''
==========固网专用==========
程序适用于频繁对同一种攻击类型添加变种
需要【手动输入起始tid,指定写有规则的文件】

1:请确保tid对应的攻击是该变种中的最后一个规则的tid
2:请确保在你操作的过程中,没有人动你的那个攻击类型
3:拿到的csv文件第2行数据,是冗余的,暂时需要手动删除

解释:程序拿到当前tid之后,可以自动拿到下一个tid,
并将下一个tid的攻击名中的数字提取出来,加1
''')
begin = '31413'  # 模板tid
movetime = 0.2  # 鼠标在屏幕上移动的时间
writetime = 0.2  # 鼠标在输入框中写字用的时间
rules = r'C:\Users\asuka\Desktop\1.txt'  # 存放本地规则的文件
csv_file = open('add_tid.csv', 'w', newline='')  # 把添加的tid和中文标题存储在一个csv文件中
write = csv.writer(csv_file)
write.writerow(['tid', '中文标题'])


# 下面的代码完成了打开平台规则的操作
def open_rule():
    # 搜索框
    pyautogui.moveTo(381, 206, duration=movetime)  # 鼠标移动到搜索框
    pyautogui.click(381, 206)  # 点击搜索框
    pyautogui.hotkey('ctrl', 'a')  # 构成组合快捷键Ctrl+a,全选搜索框中的内容
    pyautogui.typewrite(['backspace'])  # 清空搜索框的内容
    pyautogui.typewrite(begin, writetime)  # 在搜索框中输入tid

    # 查找出此tid
    pyautogui.moveTo(507, 206, duration=movetime)
    pyautogui.click(507, 206)

    # 选中此tid
    pyautogui.moveTo(507, 257, duration=movetime)
    pyautogui.click(507, 257)

    # 复制按钮
    pyautogui.moveTo(972, 206, duration=movetime)
    pyautogui.click(972, 206)

    '''
     下面的这段代码不能在别处使用,移植的话需要修改!!!
    '''
    # 修改中文标题
    pyautogui.moveTo(1144, 343, duration=movetime)
    pyautogui.click(1144, 343)
    pyautogui.hotkey('ctrl', 'a')
    pyautogui.hotkey('ctrl', 'x')  # 剪切中文标题
    textzh = pyperclip.paste()  # 获取剪贴板内容
    csv_file_nameindef = textzh  # 拿到中文标题
    csv_file_nameindef = str(csv_file_nameindef)
    reg = "[\D]"
    num = int(re.sub(reg, '', textzh))  # 获取标题中的数字内容
    num += 1
    textzh = re.sub(r'\d+', str(num), textzh)  # 修改后的中文标题
    pyperclip.copy(textzh)  # 修改后的中文标题写入到剪贴板
    pyautogui.hotkey('ctrl', 'v')  # 粘贴修改后的中文标题

    # 修改英文标题
    pyautogui.moveTo(1144, 371, duration=movetime)
    pyautogui.click(1144, 371)
    pyautogui.hotkey('ctrl', 'a')
    pyautogui.hotkey('ctrl', 'x')  # 剪切中文标题
    texten = pyperclip.paste()  # 获取剪贴板内容
    reg = "[\D]"
    num = int(re.sub(reg, '', texten))  # 获取标题中的数字内容
    num += 1
    texten = re.sub(r'\d+', str(num), texten)  # 修改后的英文标题
    pyperclip.copy(texten)  # 修改后的英文标题写入到剪贴板
    pyautogui.hotkey('ctrl', 'v')  # 粘贴修改后的英文标题

    # 修改规则内容
    # Point(x=921, y=780)
    pyautogui.moveTo(921, 780, duration=movetime)  # 鼠标移动到规则内容
    pyautogui.click(921, 780)  # 点击规则内容
    pyautogui.hotkey('ctrl', 'a')  # 构成组合快捷键Ctrl+a,全选搜索框中的内容
    pyautogui.typewrite(['backspace'])  # 清空搜索框的内容

    return csv_file_nameindef   # 返回新的中文标题


# 下面的代码完成复制规则,以及衔接open_rule()
# Point(x=963, y=613)
def copy_rule():
    pyautogui.moveTo(1316, 858, duration=movetime)  # 鼠标移动到复制按钮
    pyautogui.click(1316, 858)  # 点击复制按钮
    pyautogui.moveTo(887, 575, duration=movetime)  # 鼠标移动到完成复制的弹出框
    pyautogui.doubleClick(887, 575)  # 双击获得新的tid
    pyautogui.hotkey('ctrl', 'c')  # 构成组合快捷键Ctrl+c,拿到新的tid
    pyautogui.moveTo(963, 613, duration=movetime)  # 鼠标移动到ok按钮
    pyautogui.click(963, 613)  # 点击ok按钮
    beginindef = pyperclip.paste()  # 获取新的tid

    return beginindef   # 返回新的tid


# 读取规则
with open(rules, 'r', encoding='utf8') as files:
    file = files.readlines()
    for f in file:

        csv_file_tid = begin  # 拿到tid
        csv_file_name = open_rule()  # 调用准备好的平台,获取此tid对应的中文标题
        write.writerow([csv_file_tid, csv_file_name])

        new_f = f.replace('\n', '')

        pyperclip.copy(new_f)  # 把规则写入到剪贴板
        pyautogui.hotkey('ctrl', 'v')  # 粘贴规则进去
        begin = copy_rule()  # 调用填写规则之后的步骤,获取新的tid
    # 填写最后一次的tid,中文标题
    csv_file_tid = begin  # 拿到tid
    csv_file_name = open_rule()  # 调用准备好的平台,获取此tid对应的中文标题
    write.writerow([csv_file_tid, csv_file_name])

    pyautogui.moveTo(1391, 856, duration=movetime)  # 鼠标移动到取消按钮
    pyautogui.click(1391, 856)  # 点击取消

    csv_file.close()  # 关闭csv文件
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值