This commit is contained in:
root
2019-04-05 16:22:03 +08:00
commit 9334a46f24
7 changed files with 1049 additions and 0 deletions

32
README.md Normal file
View File

@@ -0,0 +1,32 @@
### 工具介绍
绿盟远程安全评估系统漏洞数据导出工具只支持RSAS6.0以上版本。
写这个工具的时候刚开始接触Python采用的是先读取HTML内容写入到临时文件再用正则从临时文件匹配。
后来发现了xpath这个新大陆本打算重新写一下想了想能用就行了。
工具涉及读取目录下的文件、ZIP文件读取、正则表达式、Excel表格写入、文件读写、PyQt5、TKinter(舍弃)
### 功能
- [x] 自定义漏洞等级
- [x] 自定义导出数据
- [x] 自定义Excel模板
- [x] 支持导出的数据主机名、IP地址、端口、协议、服务、漏洞名称、风险等级、整改建议、漏洞描述、漏洞CVE编号、扫描起始时间、扫描结束时间、漏洞扫描月份
- [x] 导出不同端口的同一个漏洞,也就是一个端口对应一个漏洞,保证导出漏洞的完整性。
- [x] 导出端口和导出网站为单独的功能导出网站的功能是采用正则去匹配http、www这两个服务。
### 须知
- [x] 当一个漏洞存在两个或者两个以上CVE编号则只取第一个CVE漏洞编号。
- [x] 当一个漏洞不存在CVE编号时则替换为 漏洞暂无CVE编号 。
- [x] 当一个漏洞整改建议为空时(个别低危漏洞),导出留空。
### 下载
下载链接是Windows版本的如果需要在其他平台使用可下载源码自己打包。
链接: https://pan.baidu.com/s/1JyyNJGiK_ZEc7JUGm4Ap_Q 提取码: 5pxt
### 使用方法
导出的原始报告必须勾选主机报表才行程序是直接读取zip的不能解压把原始报告放到一个文件夹内路径选择对应的文件夹就可以了。
![](https://webing.io/do/images/rsas_1.8.gif)

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

70
gui/mainwindow.py Normal file
View File

@@ -0,0 +1,70 @@
import os
import re
from PyQt5 import QtGui, QtWidgets
from gui.ui_mainwindow import *
from .threads import WorkThread
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self.input_Button.clicked.connect(self.input_Button_click)
self.output_Button.clicked.connect(self.output_Button_click)
self.start_Button.clicked.connect(self.start_Button_click)
def input_Button_click(self):
self.input_Button_cent = QtWidgets.QFileDialog.getExistingDirectory(one)
self.input_lineEdit.setText(self.input_Button_cent)
def output_Button_click(self):
self.output_Button_cent = QtWidgets.QFileDialog.getExistingDirectory(one)
self.output_lineEdit.setText(self.output_Button_cent)
def start_Button_click(self):
if self.input_lineEdit.text():
self.input_Button_cent = self.input_lineEdit.text()
else:
try:
self.input_Button_cent = self.input_Button_cent
except Exception as e:
QtWidgets.QMessageBox.information(None, "提示!", "要先设置文件夹!", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No , QtWidgets.QMessageBox.Yes )
return e
if self.output_lineEdit.text():
self.output_Button_cent = self.output_lineEdit.text()
else:
try:
self.output_Button_cent = self.output_Button_cent
except Exception as e:
QtWidgets.QMessageBox.information(None, "提示!", "要先设置文件夹!", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No , QtWidgets.QMessageBox.Yes )
return e
self.dirList = os.listdir(self.input_Button_cent)
self.file_name_box = re.findall('.*?.zip',str(self.dirList))
try:
self.file_name_box[0]
except Exception as e:
QtWidgets.QMessageBox.information(None, "提示", "找不到原始报告,请查看使用说明!", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No , QtWidgets.QMessageBox.Yes )
return e
self.hight_status = self.hight_checkBox.isChecked()
self.middle_status = self.middle_checkBox.isChecked()
self.low_status = self.low_checkBox.isChecked()
self.port_status = self.port_checkBox.isChecked()
self.web_status = self.web_checkBox.isChecked()
self.start_Button.setChecked(True)
self.start_Button.setDisabled(True)
self.work = WorkThread(self.input_Button_cent,self.output_Button_cent,self.hight_status,self.middle_status,self.low_status,self.port_status,self.web_status)
self.work.log_return.connect(self.logger)
self.work.start()
def logger(self, msg):
str_log='{}\n'.format(msg)
self.log_textEdit.moveCursor(QtGui.QTextCursor.End)
self.log_textEdit.insertPlainText(str_log)
QtWidgets.QApplication.processEvents()
if self.work.isRunning() == False:
self.start_Button.setChecked(False)
self.start_Button.setDisabled(False)

496
gui/threads.py Normal file
View File

@@ -0,0 +1,496 @@
import os
import re
import sys
import html
import queue
import shutil
import zipfile
import datetime
import openpyxl
from PyQt5 import QtWidgets
from PyQt5.QtCore import QThread, pyqtSignal
from openpyxl.styles import PatternFill, Font, Alignment, Border, Side
class Vul_re(object):
def __init__(self):
super(Vul_re, self).__init__()
self.vul_list_re = '<python>ip<python>.*?<python>host<python>.*?<td valign="top".*?<th width="120">IP地址</th>.*?<td>(.*?)</td>.*?(\d+-\d+-\d+\s\d+:\d+:\d+).*?</td>.*?(\d+-\d+-\d+\s\d+:\d+:\d+).*?</td>.*?<python>host</python>.*?<python>vul_list<python>(.*?)<python>vul_list</python>.*?<python>ip</python>'
self.vul_ip_re = '(<python>ip<python>.*?<python>ip</python>)'
self.vul_detail_re = '<python>vul_detail<python>(.*?)<python>vul_detail</python>'
self.vul_details_re = '<python>vul_details<python>(.*?)<python>vul_details</python>'
self.danger_re = '<span class="level_danger_(.*?)".*?table_\d_(\d+).*?>(.*?)</span>'
self.title_re = '<python>title<python>(.*?)<python>title</python>'
self.time_re = '<python>host<python>.*?(\d+-\d+-\d+).*?<python>host</python>'
self.scan_time_re = '<python>host<python>.*?(\d+-\d+-\d+\s\d+:\d+:\d+).*?<python>host</python>'
self.other_re = '<td class="vul_port">(.*?)</td>.*?<td>(.*?)</td>.*?<td>(.*?)</td>.*?<td>.*?<ul>(.*?)</ul>'
self.host_name = '<python>host<python>.*?<td valign="top".*?<th>主机名</th>.*?<td>(.*?)</td>.*?</td>.*?<python>host</python>'
class File_re(object):
def __init__(self):
super(File_re, self).__init__()
self.file_re = '.*?.zip'
self.uzip_re = '.*?.html'
self.all_title_re = '<th width="120">任务名称</th>.*?<td>(.*?)</td>'
self.vul_list_re = '(<table id="vuln_list" class="report_table">.*?</table>)'
self.vul_detail_re = '(<div id="vul_detail">.*?</div>)'
self.vul_details_re = '(<tr class="solution.*?">.*?<td>.*?<table class="report_table plumb".*?>.*?</table>.*?</td>.*?</tr>)'
self.host_re = '(<td valign="top" style="width:50%;">.*?<table class="report_table plumb">.*?<tbody>.*?<th width="120">IP地址</th>.*?</tbody>.*?</table></td>)'
class Vul_content(object):
def __init__(self,vul_re):
super(Vul_content, self).__init__()
self.vul_ip_content = re.findall(vul_re.vul_ip_re,htmlcont,re.S|re.M)
self.vul_detail_content = re.findall(vul_re.vul_detail_re,htmlcont,re.S|re.M)
class Solve_re(object):
def __init__(self):
super(Solve_re, self).__init__()
self.solve_re = '<th width="100">解决办法</th>.*?<td>(.*?)</td>'
self.describe_re = '<tr class="solution.*?table_\d_(\d+).*?<th width="100">详细描述</th>.*?<td>(.*?)</td>'
self.cve_re = '<th width="100">CVE编号</th>.*?<td><a target=.*?>(.*?)</a>.*?</td>'
class Other(object):
def __init__(self, vul_re, all_vuln_list):
super(Other, self).__init__()
self.all_other = re.findall(vul_re.other_re,all_vuln_list,re.S|re.M)
class Danger(object):
def __init__(self, vul_re, other):
super(Danger, self).__init__()
self.danger_coneent = re.findall(vul_re.danger_re,other,re.S|re.M)
class Solve(object):
def __init__(self, solve, all_vul_details):
super(Solve, self).__init__()
self.solve_plumb = re.findall(solve.solve_re,all_vul_details,re.S|re.M)
self.describe_plumb = re.findall(solve.describe_re,all_vul_details,re.S|re.M)
self.cve_plumb = re.findall(solve.cve_re,all_vul_details,re.S|re.M)
class Port_File_re(object):
def __init__(self):
super(Port_File_re, self).__init__()
self.file_re = '.*?.zip'
self.uzip_re = '.*?.html'
self.all_title_re = '<th width="120">任务名称</th>.*?<td>(.*?)</td>'
self.host_re = '<th width="120">IP地址</th>.*?<td>(\d+.\d+.\d+.\d+)</td>.*?<th>扫描起始时间</th>.*?<td>(\d+-\d+-\d+).*?</td>.*?<thead>.*?<th>端口</th>.*?<th>协议</th>.*?<th>服务</th>.*?<th>状态</th>.*?</thead>.*?<tbody>(.*?)</tbody>'
self.port_re = '<tr class=".*?<td>(.*?)</td>.*?<td>(.*?)</td>.*?<td>(.*?)</td>.*?<td>(.*?)</td>.*?</tr>'
self.http_re = '.*?http.*?'
self.https_re = '.*?https.*?'
self.www_re = '.*?www.*?'
class WorkThread(QThread):
log_return = pyqtSignal(str)
def __init__(self,input_Button_cent,output_Button_cent,hight_status,middle_status,low_status,port_status,web_status):
super(WorkThread, self).__init__()
self.folder_start = input_Button_cent
self.folder_end = output_Button_cent
self.hight_status = hight_status
self.middle_status = middle_status
self.low_status = low_status
self.port_status = port_status
self.web_status = web_status
def run(self):
set_vul = []
excel = {}
letter = ['B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','AA','AB','AC','AD','AE','AF','AG','AH','AI','AJ','AK','AL','AM','AN','AO','AP','AQ','AR','AS','AT','AU','AV','AW','AX','AY','AZ']
with open('set.ini') as set_ini:
ini = set_ini.readlines()[1:3]
self.name_ini = ini[1].split('=')[1].strip()
self.company_ini = ini[0].split('=')[1].strip()
try:
with open('set.ini') as vulnerable_ini:
for vul in vulnerable_ini.readlines()[11:]:
set_vul.append(vul.strip().split('|'))
except Exception as e:
pass
with open('set.ini') as cent:
len_excel = 2
for ini,column in zip(cent.readlines()[5].split('|'),letter):
sign = ini.split(':')
excel[column] = sign[0],sign[1],sign[2].strip()
len_excel += 1
try:
shutil.rmtree('temp')
except Exception as e:
pass
if self.hight_status or self.middle_status or self.low_status == True:
try:
shutil.rmtree(self.folder_end+'/汇总-漏洞跟踪表')
except Exception as e:
pass
starttime = datetime.datetime.now()
self.log_return.emit('正在提取数据...')
os.mkdir('temp')
with open('temp/database.mdb', 'w',encoding='gb18030') as content:
content.write('')
self.dirList = os.listdir(self.folder_start)
for name in self.dirList:
all_file_name = re.findall(File_re().file_re,name)
for file_name in all_file_name:
try:
uzip = zipfile.ZipFile(self.folder_start+'/'+file_name)
except Exception as e:
self.log_textEdit.moveCursor(QtGui.QTextCursor.End)
self.log_textEdit.insertPlainText('\n{}不是正确的ZIP压缩包请检查\n\n'.format(file_name))
QtWidgets.QApplication.processEvents()
return e
try:
for uzip_content in uzip.namelist():
all_uzip_content = re.findall(File_re().uzip_re,uzip_content)
for all_uzip in all_uzip_content:
htmlcont_zip = uzip.open(all_uzip).read().decode('utf8')
title = re.findall(File_re().all_title_re,htmlcont_zip,re.S|re.M)
for title_content in title:
with open('temp/%s.mdb'%title_content, 'a',encoding='gb18030') as content:
content.write('<python>title<python>')
content.write(html.unescape(title_content))
content.write('<python>title</python>\n')
with open('temp/database.mdb','a',encoding='gb18030') as content:
content.write('temp/'+html.unescape(title_content)+'.mdb\n')
host = re.findall(File_re().host_re,htmlcont_zip,re.S|re.M)
for host_content in host:
with open('temp/%s.mdb'%title_content, 'a',encoding='gb18030') as content:
content.write('<python>ip<python>\n')
content.write('<python>host<python>\n')
content.write(html.unescape(host_content))
content.write('\n<python>host</python>\n')
vul_list = re.findall(File_re().vul_list_re,htmlcont_zip,re.S|re.M)
for list_content in vul_list:
with open('temp/%s.mdb'%title_content, 'a',encoding='gb18030') as content:
content.write('<python>vul_list<python>\n')
content.write(html.unescape(list_content))
content.write('\n<python>vul_list</python>\n')
vul_detail = re.findall(File_re().vul_detail_re,htmlcont_zip,re.S|re.M)
for detail_content in vul_detail:
with open('temp/%s.mdb'%title_content, 'a',encoding='gb18030') as content:
content.write('<python>vul_detail<python>\n')
vul_details = re.findall(File_re().vul_details_re,detail_content,re.S|re.M)
for list_details in vul_details:
with open('temp/%s.mdb'%title_content, 'a',encoding='gb18030') as content:
content.write('<python>vul_details<python>\n')
content.write(html.unescape(list_details))
content.write('\n<python>vul_details</python>\n')
with open('temp/%s.mdb'%title_content, 'a',encoding='gb18030') as content:
content.write('\n<python>vul_detail</python>\n')
content.write('<python>ip</python>\n')
self.log_return.emit('提取 {}'.format(title_content))
except Exception as e:
self.log_return.emit('{} 已被编辑,保存编码不一样,导出失败!'.format(file_name))
return e
self.log_return.emit('\n数据提取完成,正在生成漏洞跟踪表...')
os.mkdir(self.folder_end+'/汇总-漏洞跟踪表')
vul_re = Vul_re()
i = 1
wb = openpyxl.Workbook()
ws = wb.active
ws.freeze_panes = 'A2'
ws.title = '系统漏洞'
ws.column_dimensions['A'].width = 6
ws['A1'] = '序号'
for longs,column in zip(range(2,len(excel)+2),letter):
ws.column_dimensions[column].width = excel[column][1]
ws['{}1'.format(column)] = excel[column][2]
# 样式
font = Font(size=10, name='宋体')
thin = Side(border_style="thin")
border = Border(left=thin, right=thin, top=thin, bottom=thin)
# 对齐
alignment = Alignment(horizontal="center", vertical="center", wrap_text=True)
with open('set.ini') as colour:
for color in colour.readlines()[8].strip().split('|'):
one_color = color.split(':')
lter = one_color[0].split('-')
#设置第一行的格式
title_font = Font(size=12, bold=True, name='宋体', color= one_color[1])
ws.row_dimensions[1].height = 40
for title_style in ws['{}1:{}1'.format(lter[0],lter[1])]:
for title_cell in title_style:
title_cell.font = title_font
title_cell.border = border
title_cell.alignment = alignment
with open('temp/database.mdb',encoding='gb18030') as content:
for zip_content in content:
vul_all_list = []
vul_all_detail = {}
zip_cont = zip_content.strip()
content = open(zip_cont,'r',encoding='gb18030')
global htmlcont
htmlcont = content.read()
content.close()
sheet_name = re.findall(vul_re.title_re,htmlcont,re.S|re.M)[0]
sheet_time = re.findall(vul_re.time_re,htmlcont,re.S|re.M)[0]
vul_time = sheet_time.split('-')[1]
if vul_time[0] == '0':
vul_time = vul_time[1]
vul_time = vul_time + ''
self.log_return.emit('正在导出 {}'.format(sheet_name))
vul_content = Vul_content(vul_re)
for all_vul_ip in vul_content.vul_ip_content:
vul_list_content = re.findall(vul_re.vul_list_re,all_vul_ip,re.S|re.M)
host_name = re.findall(vul_re.host_name,all_vul_ip,re.S|re.M)
if host_name:
pass
else:
host_name = ['']
for all_vul_list in vul_list_content:
for other in Other(vul_re,all_vul_list[3]).all_other:
for danger in Danger(vul_re,other[3]).danger_coneent:
vul_name = danger[0]
if len(set_vul) > 0:
for set_vuls in set_vul:
if set_vuls[1] == danger[2]:
vul_name = set_vuls[0]
break
vul_all_list.append([danger[1],all_vul_list[0],danger[2].strip(),vul_name.replace('low','').replace('middle','').replace('high',''),other[0],other[1],other[2],all_vul_list[1],all_vul_list[2],host_name[0]])
for all_vul_detail in vul_content.vul_detail_content:
vul_details_content = re.findall(vul_re.vul_details_re,all_vul_detail,re.S|re.M)
for all_vul_details in vul_details_content:
vul_detail = Solve(Solve_re(),all_vul_details)
for solve,describe in zip(vul_detail.solve_plumb,vul_detail.describe_plumb):
cve = vul_detail.cve_plumb
if cve:
pass
else:
cve = ['漏洞暂无CVE编号']
vul_all_detail[describe[0]] = re.sub('\s{2,}','\n',html.unescape(re.sub('\s{2,}','',solve)).replace('<br/>','\n')),re.sub('\s{2,}','\n',html.unescape(re.sub('\s{2,}','',describe[1])).replace('<br/>','\n')),cve[0]
vul_amount = []
for wait_list in vul_all_list:
wait_detail = vul_all_detail[wait_list[0]]
vul_amount.append(['',self.company_ini,sheet_name,wait_list[9],wait_list[1],wait_list[4],wait_list[5],wait_list[6],wait_list[2],'漏洞',wait_list[3],wait_detail[0].strip(),wait_detail[1],wait_detail[2],wait_list[7],wait_list[8],vul_time])
for amount in vul_amount:
if self.hight_status == True and amount[10] == '':
ws.row_dimensions[i+1].height = 25
ws.append([i,amount[int(excel['B'][0]) if 'B' in excel else 0],amount[int(excel['C'][0]) if 'C' in excel else 0],amount[int(excel['D'][0]) if 'D' in excel else 0],amount[int(excel['E'][0]) if 'E' in excel else 0],amount[int(excel['F'][0]) if 'F' in excel else 0],amount[int(excel['G'][0]) if 'G' in excel else 0],amount[int(excel['H'][0]) if 'H' in excel else 0],amount[int(excel['I'][0]) if 'I' in excel else 0],amount[int(excel['J'][0]) if 'J' in excel else 0],amount[int(excel['K'][0]) if 'K' in excel else 0],amount[int(excel['L'][0]) if 'L' in excel else 0],amount[int(excel['M'][0]) if 'M' in excel else 0],amount[int(excel['N'][0]) if 'N' in excel else 0],amount[int(excel['O'][0]) if 'O' in excel else 0],amount[int(excel['P'][0]) if 'P' in excel else 0],amount[int(excel['Q'][0]) if 'Q' in excel else 0],amount[int(excel['R'][0]) if 'R' in excel else 0],amount[int(excel['S'][0]) if 'S' in excel else 0],amount[int(excel['T'][0]) if 'T' in excel else 0],amount[int(excel['U'][0]) if 'U' in excel else 0],amount[int(excel['V'][0]) if 'V' in excel else 0],amount[int(excel['W'][0]) if 'W' in excel else 0],amount[int(excel['X'][0]) if 'X' in excel else 0],amount[int(excel['Y'][0]) if 'Y' in excel else 0],amount[int(excel['Z'][0]) if 'Z' in excel else 0],amount[int(excel['AA'][0]) if 'AA' in excel else 0],amount[int(excel['AB'][0]) if 'AB' in excel else 0],amount[int(excel['AC'][0]) if 'AC' in excel else 0],amount[int(excel['AD'][0]) if 'AD' in excel else 0],amount[int(excel['AE'][0]) if 'AE' in excel else 0],amount[int(excel['AF'][0]) if 'AF' in excel else 0],amount[int(excel['AG'][0]) if 'AG' in excel else 0],amount[int(excel['AH'][0]) if 'AH' in excel else 0],amount[int(excel['AI'][0]) if 'AI' in excel else 0],amount[int(excel['AJ'][0]) if 'AJ' in excel else 0],amount[int(excel['AK'][0]) if 'AK' in excel else 0],amount[int(excel['AL'][0]) if 'AL' in excel else 0],amount[int(excel['AM'][0]) if 'AM' in excel else 0],amount[int(excel['AN'][0]) if 'AN' in excel else 0],amount[int(excel['AO'][0]) if 'AO' in excel else 0],amount[int(excel['AP'][0]) if 'AP' in excel else 0],amount[int(excel['AQ'][0]) if 'AQ' in excel else 0],amount[int(excel['AR'][0]) if 'AR' in excel else 0],amount[int(excel['AS'][0]) if 'AS' in excel else 0],amount[int(excel['AT'][0]) if 'AT' in excel else 0],amount[int(excel['AU'][0]) if 'AU' in excel else 0],amount[int(excel['AV'][0]) if 'AV' in excel else 0],amount[int(excel['AW'][0]) if 'AW' in excel else 0],amount[int(excel['AX'][0]) if 'AX' in excel else 0],amount[int(excel['AY'][0]) if 'AY' in excel else 0],amount[int(excel['AZ'][0]) if 'AZ' in excel else 0]])
i += 1
if self.middle_status == True and amount[10] == '':
ws.row_dimensions[i+1].height = 25
ws.append([i,amount[int(excel['B'][0]) if 'B' in excel else 0],amount[int(excel['C'][0]) if 'C' in excel else 0],amount[int(excel['D'][0]) if 'D' in excel else 0],amount[int(excel['E'][0]) if 'E' in excel else 0],amount[int(excel['F'][0]) if 'F' in excel else 0],amount[int(excel['G'][0]) if 'G' in excel else 0],amount[int(excel['H'][0]) if 'H' in excel else 0],amount[int(excel['I'][0]) if 'I' in excel else 0],amount[int(excel['J'][0]) if 'J' in excel else 0],amount[int(excel['K'][0]) if 'K' in excel else 0],amount[int(excel['L'][0]) if 'L' in excel else 0],amount[int(excel['M'][0]) if 'M' in excel else 0],amount[int(excel['N'][0]) if 'N' in excel else 0],amount[int(excel['O'][0]) if 'O' in excel else 0],amount[int(excel['P'][0]) if 'P' in excel else 0],amount[int(excel['Q'][0]) if 'Q' in excel else 0],amount[int(excel['R'][0]) if 'R' in excel else 0],amount[int(excel['S'][0]) if 'S' in excel else 0],amount[int(excel['T'][0]) if 'T' in excel else 0],amount[int(excel['U'][0]) if 'U' in excel else 0],amount[int(excel['V'][0]) if 'V' in excel else 0],amount[int(excel['W'][0]) if 'W' in excel else 0],amount[int(excel['X'][0]) if 'X' in excel else 0],amount[int(excel['Y'][0]) if 'Y' in excel else 0],amount[int(excel['Z'][0]) if 'Z' in excel else 0],amount[int(excel['AA'][0]) if 'AA' in excel else 0],amount[int(excel['AB'][0]) if 'AB' in excel else 0],amount[int(excel['AC'][0]) if 'AC' in excel else 0],amount[int(excel['AD'][0]) if 'AD' in excel else 0],amount[int(excel['AE'][0]) if 'AE' in excel else 0],amount[int(excel['AF'][0]) if 'AF' in excel else 0],amount[int(excel['AG'][0]) if 'AG' in excel else 0],amount[int(excel['AH'][0]) if 'AH' in excel else 0],amount[int(excel['AI'][0]) if 'AI' in excel else 0],amount[int(excel['AJ'][0]) if 'AJ' in excel else 0],amount[int(excel['AK'][0]) if 'AK' in excel else 0],amount[int(excel['AL'][0]) if 'AL' in excel else 0],amount[int(excel['AM'][0]) if 'AM' in excel else 0],amount[int(excel['AN'][0]) if 'AN' in excel else 0],amount[int(excel['AO'][0]) if 'AO' in excel else 0],amount[int(excel['AP'][0]) if 'AP' in excel else 0],amount[int(excel['AQ'][0]) if 'AQ' in excel else 0],amount[int(excel['AR'][0]) if 'AR' in excel else 0],amount[int(excel['AS'][0]) if 'AS' in excel else 0],amount[int(excel['AT'][0]) if 'AT' in excel else 0],amount[int(excel['AU'][0]) if 'AU' in excel else 0],amount[int(excel['AV'][0]) if 'AV' in excel else 0],amount[int(excel['AW'][0]) if 'AW' in excel else 0],amount[int(excel['AX'][0]) if 'AX' in excel else 0],amount[int(excel['AY'][0]) if 'AY' in excel else 0],amount[int(excel['AZ'][0]) if 'AZ' in excel else 0]])
i += 1
if self.low_status == True and amount[10] == '':
ws.row_dimensions[i+1].height = 25
ws.append([i,amount[int(excel['B'][0]) if 'B' in excel else 0],amount[int(excel['C'][0]) if 'C' in excel else 0],amount[int(excel['D'][0]) if 'D' in excel else 0],amount[int(excel['E'][0]) if 'E' in excel else 0],amount[int(excel['F'][0]) if 'F' in excel else 0],amount[int(excel['G'][0]) if 'G' in excel else 0],amount[int(excel['H'][0]) if 'H' in excel else 0],amount[int(excel['I'][0]) if 'I' in excel else 0],amount[int(excel['J'][0]) if 'J' in excel else 0],amount[int(excel['K'][0]) if 'K' in excel else 0],amount[int(excel['L'][0]) if 'L' in excel else 0],amount[int(excel['M'][0]) if 'M' in excel else 0],amount[int(excel['N'][0]) if 'N' in excel else 0],amount[int(excel['O'][0]) if 'O' in excel else 0],amount[int(excel['P'][0]) if 'P' in excel else 0],amount[int(excel['Q'][0]) if 'Q' in excel else 0],amount[int(excel['R'][0]) if 'R' in excel else 0],amount[int(excel['S'][0]) if 'S' in excel else 0],amount[int(excel['T'][0]) if 'T' in excel else 0],amount[int(excel['U'][0]) if 'U' in excel else 0],amount[int(excel['V'][0]) if 'V' in excel else 0],amount[int(excel['W'][0]) if 'W' in excel else 0],amount[int(excel['X'][0]) if 'X' in excel else 0],amount[int(excel['Y'][0]) if 'Y' in excel else 0],amount[int(excel['Z'][0]) if 'Z' in excel else 0],amount[int(excel['AA'][0]) if 'AA' in excel else 0],amount[int(excel['AB'][0]) if 'AB' in excel else 0],amount[int(excel['AC'][0]) if 'AC' in excel else 0],amount[int(excel['AD'][0]) if 'AD' in excel else 0],amount[int(excel['AE'][0]) if 'AE' in excel else 0],amount[int(excel['AF'][0]) if 'AF' in excel else 0],amount[int(excel['AG'][0]) if 'AG' in excel else 0],amount[int(excel['AH'][0]) if 'AH' in excel else 0],amount[int(excel['AI'][0]) if 'AI' in excel else 0],amount[int(excel['AJ'][0]) if 'AJ' in excel else 0],amount[int(excel['AK'][0]) if 'AK' in excel else 0],amount[int(excel['AL'][0]) if 'AL' in excel else 0],amount[int(excel['AM'][0]) if 'AM' in excel else 0],amount[int(excel['AN'][0]) if 'AN' in excel else 0],amount[int(excel['AO'][0]) if 'AO' in excel else 0],amount[int(excel['AP'][0]) if 'AP' in excel else 0],amount[int(excel['AQ'][0]) if 'AQ' in excel else 0],amount[int(excel['AR'][0]) if 'AR' in excel else 0],amount[int(excel['AS'][0]) if 'AS' in excel else 0],amount[int(excel['AT'][0]) if 'AT' in excel else 0],amount[int(excel['AU'][0]) if 'AU' in excel else 0],amount[int(excel['AV'][0]) if 'AV' in excel else 0],amount[int(excel['AW'][0]) if 'AW' in excel else 0],amount[int(excel['AX'][0]) if 'AX' in excel else 0],amount[int(excel['AY'][0]) if 'AY' in excel else 0],amount[int(excel['AZ'][0]) if 'AZ' in excel else 0]])
i += 1
for row in ws['A2:{}{}'.format(letter[len(excel)-1],i)]:
for cell in row:
cell.font = font
cell.border = border
cell.alignment = alignment
ws.delete_cols(len_excel,len(letter))
wb.save(self.folder_end+'/汇总-漏洞跟踪表/高中风险漏洞跟踪表--汇总.xlsx')
del vul_all_list[:]
vul_all_detail.clear()
self.log_return.emit('漏洞跟踪表导出完成,保存在输出路径 汇总-漏洞跟踪表 目录下。')
shutil.rmtree('temp')
endtime = datetime.datetime.now()
self.log_return.emit('导出花时:{}秒...\n'.format((endtime - starttime).seconds))
if self.port_status:
try:
shutil.rmtree(self.folder_end+'/汇总-端口对应关系表')
except Exception as e:
pass
self.log_return.emit('正在导出端口,请稍后!')
starttime = datetime.datetime.now()
os.mkdir(self.folder_end+'/汇总-端口对应关系表')
dirList = os.listdir(self.folder_start)
for name in dirList:
all_file_name = re.findall(Port_File_re().file_re,name)
for file_name in all_file_name:
uzip = zipfile.ZipFile(self.folder_start+'/'+file_name)
i = 1
wb = openpyxl.Workbook()
wps = wb.active
wps.column_dimensions['A'].width = 16.5
wps.column_dimensions['B'].width = 16
wps.column_dimensions['C'].width = 20
wps.column_dimensions['D'].width = 30
wps.column_dimensions['E'].width = 25
wps.column_dimensions['F'].width = 28
wps.column_dimensions['G'].width = 42
wps.column_dimensions['H'].width = 17
wps.title = '端口数据'
wps['A1'] = '设备端口和服务信息表'
wps.merge_cells('A1:H1')
wps['A2'] = '收集时间'
wps.merge_cells('A2:B2')
wps.merge_cells('C2:D2')
wps['E2'] = '所属系统'
wps.merge_cells('F2:H2')
wps['A3'] = '填表人'
wps['C3'] = self.name_ini
wps.merge_cells('A3:B3')
wps.merge_cells('C3:D3')
wps['E3'] = '系统责任人'
wps.merge_cells('F3:H3')
wps['A4'] = 'IP地址'
wps['B4'] = '端口'
wps['C4'] = '协议'
wps['D4'] = '服务'
wps['E4'] = '状态'
wps['F4'] = '访问权限开放范围'
wps['G4'] = '应用说明'
wps['H4'] = '备注'
# 样式
font = Font(size=12, name='宋体')
thin = Side(border_style="thin")
border = Border(left=thin, right=thin, top=thin, bottom=thin)
# 对齐
alignment = Alignment(horizontal="center", vertical="center", wrap_text=True)
#设置第一行的格式
one_font = Font(size=12, bold=True, name='宋体')
for one_style in wps['A1:H1']:
for one_cell in one_style:
one_cell.font = one_font
one_cell.border = border
one_cell.alignment = alignment
for excel_style in wps['A2:H4']:
for excel_cell in excel_style:
excel_cell.font = font
excel_cell.border = border
excel_cell.alignment = alignment
for uzip_content in uzip.namelist():
all_uzip_content = re.findall(Port_File_re().uzip_re,uzip_content)
for all_uzip in all_uzip_content:
htmlcont_zip = uzip.open(all_uzip).read().decode('utf8')
vul_title = re.findall(Port_File_re().all_title_re,htmlcont_zip,re.S|re.M)
for title_content in vul_title:
pass
vul_host = re.findall(Port_File_re().host_re,htmlcont_zip,re.S|re.M)
for host_content in vul_host:
for vul_port in re.findall(Port_File_re().port_re,host_content[2],re.S|re.M):
wps.row_dimensions[i+4].height = 15
wps['C2'] = '%s' % host_content[1]
wps.append([host_content[0],vul_port[0].replace(' ','').strip(),vul_port[1].replace(' ','').strip(),vul_port[2].replace(' ','').strip(),vul_port[3].replace(' ','').strip()])
for row in wps['A%s:H%s'%(i+4,i+4)]:
for cell in row:
cell.font = font
cell.border = border
cell.alignment = alignment
i += 1
wb.save(self.folder_end+'/汇总-端口对应关系表/端口服务对应关系表--%s.xlsx' % title_content)
self.log_return.emit('导出 %s'%title_content)
endtime = datetime.datetime.now()
self.log_return.emit('所有端口导出完成,保存在输出路径 汇总-端口对应关系表 目录下。')
self.log_return.emit('导出花时:%s秒...\n'%(endtime - starttime).seconds)
if self.web_status:
try:
shutil.rmtree(self.folder_end+'/汇总-WEB网站')
except Exception as e:
pass
self.log_return.emit('正在WEB网站请稍后')
starttime = datetime.datetime.now()
os.mkdir(self.folder_end+'/汇总-WEB网站')
dirList = os.listdir(self.folder_start)
for name in dirList:
all_file_name = re.findall(Port_File_re().file_re,name)
for file_name in all_file_name:
uzip = zipfile.ZipFile(self.folder_start+'/'+file_name)
x = 1
web = openpyxl.Workbook()
wes = web.active
wes.title = 'WEB网站'
wes.column_dimensions['A'].width = 16.5
wes.column_dimensions['B'].width = 16
wes.column_dimensions['C'].width = 20
wes.column_dimensions['D'].width = 30
wes.column_dimensions['E'].width = 25
wes.column_dimensions['F'].width = 45
wes['A1'] = 'IP地址'
wes['B1'] = '端口'
wes['C1'] = '协议'
wes['D1'] = '服务'
wes['E1'] = '状态'
wes['F1'] = 'WEB网站信息'
# 样式
font = Font(size=12, name='宋体')
thin = Side(border_style="thin")
border = Border(left=thin, right=thin, top=thin, bottom=thin)
# 对齐
alignment = Alignment(horizontal="center", vertical="center", wrap_text=True)
for uzip_content in uzip.namelist():
all_uzip_content = re.findall(Port_File_re().uzip_re,uzip_content)
for all_uzip in all_uzip_content:
htmlcont_zip = uzip.open(all_uzip).read().decode('utf8')
vul_title = re.findall(Port_File_re().all_title_re,htmlcont_zip,re.S|re.M)
for title_content in vul_title:
pass
vul_host = re.findall(Port_File_re().host_re,htmlcont_zip,re.S|re.M)
for host_content in vul_host:
for vul_port in re.findall(Port_File_re().port_re,host_content[2],re.S|re.M):
vul_web = re.findall(Port_File_re().http_re,vul_port[2].replace(' ','').strip(),re.S|re.M)
if vul_web:
wes.row_dimensions[x+1].height = 15
wes.append([host_content[0],vul_port[0].replace(' ','').strip(),vul_port[1].replace(' ','').strip(),vul_port[2].replace(' ','').strip(),vul_port[3].replace(' ','').strip(),'http://'+ host_content[0] + ':' + vul_port[0].replace(' ','').strip()])
x += 1
vul_web = re.findall(Port_File_re().https_re,vul_port[2].replace(' ','').strip(),re.S|re.M)
if vul_web:
wes.row_dimensions[x+1].height = 15
wes.append([host_content[0],vul_port[0].replace(' ','').strip(),vul_port[1].replace(' ','').strip(),vul_port[2].replace(' ','').strip(),vul_port[3].replace(' ','').strip(),'https://'+ host_content[0] + ':' + vul_port[0].replace(' ','').strip()])
x += 1
vul_web = re.findall(Port_File_re().www_re,vul_port[2].replace(' ','').strip(),re.S|re.M)
if vul_web:
wes.row_dimensions[x+1].height = 15
wes.append([host_content[0],vul_port[0].replace(' ','').strip(),vul_port[1].replace(' ','').strip(),vul_port[2].replace(' ','').strip(),vul_port[3].replace(' ','').strip(),'http://'+ host_content[0] + ':' + vul_port[0].replace(' ','').strip()])
x += 1
for row in wes['A1:F{}'.format(x)]:
for cell in row:
cell.font = font
cell.border = border
cell.alignment = alignment
web.save(self.folder_end+'/汇总-WEB网站/WEB网站--%s.xlsx' % title_content)
self.log_return.emit('导出 %s'%title_content)
endtime = datetime.datetime.now()
self.log_return.emit('所有WEB网站导出导出完成保存在输出路径 汇总-WEB网站 目录下。')
self.log_return.emit('导出花时:%s秒...'%(endtime - starttime).seconds)

167
gui/ui_mainwindow.py Normal file
View File

@@ -0,0 +1,167 @@
import images_ico
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
setini = """:::::::::导出的人员信息:::::::::
检查单位=宝宝
检查人员=宝宝
:::::::::自定义导出数据 - 可删除、添加、调换位置:::::::::
1:6:检查单位|2:28:系统名称|3:8:主机名|4:16:IP地址|5:8:端口|6:8:协议|7:8:服务|8:45:漏洞名称|9:8:风险分类|10:8:风险等级|11:45:整改建议|12:45:漏洞描述|13:13:漏洞CVE编号|14:11:扫描起始时间|15:11:扫描结束时间|16:11:漏洞发现月份
:::::::::自定义标题颜色:::::::::
A-S:ff0000
:::::::::自定义漏洞等级 - 可删除,添加:::::::::
中|检测到目标NTP服务支持monlist命令
中|目标主机rpcinfo -p信息泄露
中|可通过finger服务猜测用户名列表
中|可通过finger服务获取用户信息
中|可通过rusers服务获取用户信息
高|目标主机showmount -e信息泄露"""
try:
with open('set.ini') as info_ini:
ini = info_ini.readlines()[1:3]
self.name_ini = ini[1].split('=')[1].strip()
self.company_ini = ini[0].split('=')[1].strip()
except Exception as e:
with open('set.ini','a',encoding='gb18030') as set_ini:
set_ini.write(setini)
QtWidgets.QMessageBox.information(MainWindow, "提示!", "请修改同目录下的配置文件,重新打开软件!", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No , QtWidgets.QMessageBox.Yes )
exit()
title = 'RSAS漏洞数据导出工具1.8'
font = QtGui.QFont()
font.setFamily("宋体")
font.setPointSize(10)
MainWindow.setFont(font)
#定义程序的标题
MainWindow.setWindowTitle(title)
#设定程序的最大分辨率,禁止最大化、拖动窗口
MainWindow.setFixedSize(560, 310)
#设置图标
MainWindow.setWindowIcon(QtGui.QIcon(':/favicon.ico'))
#获取显示器的分辨率
screen = QtWidgets.QDesktopWidget().screenGeometry()
#获取程序的宽和高
size = MainWindow.geometry()
#实现在屏幕中间显示程序
MainWindow.move((screen.width() - size.width())/2, (screen.height() - size.height())/2)
#这是底部的状态栏
MainWindow.status = MainWindow.statusBar()
MainWindow.status.showMessage("检查单位:%s 检查人员:%s" % (self.company_ini,self.name_ini))
#这是一个框架,用来固定按钮用的
self.formLayoutWidget = QtWidgets.QWidget(MainWindow)
self.formLayoutWidget.setGeometry(QtCore.QRect(10, 10, 451, 54))
self.formLayoutWidget.setObjectName("formLayoutWidget")
self.formLayout = QtWidgets.QFormLayout(self.formLayoutWidget)
self.formLayout.setContentsMargins(0, 0, 0, 0)
self.formLayout.setObjectName("formLayout")
#文字:原始报告路径
self.input_label = QtWidgets.QLabel(self.formLayoutWidget)
self.input_label.setObjectName("input_label")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.input_label)
#文字:输出报告路径
self.output_label = QtWidgets.QLabel(self.formLayoutWidget)
self.output_label.setObjectName("output_label")
self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.output_label)
#原始报告路径后边的文本框
self.input_lineEdit = QtWidgets.QLineEdit(self.formLayoutWidget)
self.input_lineEdit.setObjectName("input_lineEdit")
self.formLayout.addWidget(self.input_lineEdit)
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.input_lineEdit)
#输出报告路径后边的文本框
self.output_lineEdit = QtWidgets.QLineEdit(self.formLayoutWidget)
self.output_lineEdit.setObjectName("output_lineEdit")
self.formLayout.addWidget(self.output_lineEdit)
self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.output_lineEdit)
#框架的结束部分
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.formLayout.setItem(1, QtWidgets.QFormLayout.LabelRole, spacerItem)
#这玩意就是打开路径按钮的框架
self.start_verticalLayoutWidget = QtWidgets.QWidget(MainWindow)
self.start_verticalLayoutWidget.setGeometry(QtCore.QRect(463, 2, 91, 71))
self.start_verticalLayoutWidget.setObjectName("start_verticalLayoutWidget")
self.start_verticalLayout = QtWidgets.QVBoxLayout(self.start_verticalLayoutWidget)
self.start_verticalLayout.setContentsMargins(0, 0, 0, 0)
self.start_verticalLayout.setObjectName("start_verticalLayout")
#这是原始报告路径后边的文本框后边的打开路径按钮
self.input_Button = QtWidgets.QPushButton(self.start_verticalLayoutWidget)
self.input_Button.setObjectName("input_Button")
self.start_verticalLayout.addWidget(self.input_Button)
#这是输出报告路径后边的文本框后边的打开路径按钮
self.output_Button = QtWidgets.QPushButton(self.start_verticalLayoutWidget)
self.output_Button.setObjectName("output_Button")
self.start_verticalLayout.addWidget(self.output_Button)
#这又是一个框架,固定用的
self.horizontalLayoutWidget = QtWidgets.QWidget(MainWindow)
self.horizontalLayoutWidget.setGeometry(QtCore.QRect(10, 75, 451, 21))
self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
#文字:选择导出数据
self.data_label = QtWidgets.QLabel(self.horizontalLayoutWidget)
self.data_label.setObjectName("data_label")
self.horizontalLayout.addWidget(self.data_label)
#复选框:高危
self.hight_checkBox = QtWidgets.QCheckBox(self.horizontalLayoutWidget)
self.hight_checkBox.setObjectName("hight_checkBox")
self.horizontalLayout.addWidget(self.hight_checkBox)
#复选框:中危
self.middle_checkBox = QtWidgets.QCheckBox(self.horizontalLayoutWidget)
self.middle_checkBox.setObjectName("middle_checkBox")
self.horizontalLayout.addWidget(self.middle_checkBox)
#复选框:低危
self.low_checkBox = QtWidgets.QCheckBox(self.horizontalLayoutWidget)
self.low_checkBox.setObjectName("low_checkBox")
self.horizontalLayout.addWidget(self.low_checkBox)
#复选框:端口
self.port_checkBox = QtWidgets.QCheckBox(self.horizontalLayoutWidget)
self.port_checkBox.setObjectName("port_checkBox")
self.horizontalLayout.addWidget(self.port_checkBox)
#复选框:网站
self.web_checkBox = QtWidgets.QCheckBox(self.horizontalLayoutWidget)
self.web_checkBox.setObjectName("web_checkBox")
self.horizontalLayout.addWidget(self.web_checkBox)
#这又是一个框架
self.end_verticalLayoutWidget = QtWidgets.QWidget(MainWindow)
self.end_verticalLayoutWidget.setGeometry(QtCore.QRect(463, 69, 91, 31))
self.end_verticalLayoutWidget.setObjectName("end_verticalLayoutWidget")
self.end_verticalLayout = QtWidgets.QVBoxLayout(self.end_verticalLayoutWidget)
self.end_verticalLayout.setContentsMargins(0, 0, 0, 0)
self.end_verticalLayout.setObjectName("end_verticalLayout")
#按钮:开始导出
self.start_Button = QtWidgets.QPushButton(self.end_verticalLayoutWidget)
self.start_Button.setObjectName("start_Button")
#框架结尾
self.end_verticalLayout.addWidget(self.start_Button)
#详细输出日志的文本框
self.log_textEdit = QtWidgets.QTextEdit(MainWindow)
self.log_textEdit.setGeometry(QtCore.QRect(5, 120, 550, 171))
self.log_textEdit.setObjectName("log_textEdit")
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
self.input_label.setText(_translate("MainWindow", "原始报告路径:"))
self.output_label.setText(_translate("MainWindow", "输出报告路径:"))
self.input_Button.setText(_translate("MainWindow", "打开路径"))
self.output_Button.setText(_translate("MainWindow", "打开路径"))
self.data_label.setText(_translate("MainWindow", "选择导出数据:"))
self.hight_checkBox.setText(_translate("MainWindow", "高危"))
self.middle_checkBox.setText(_translate("MainWindow", "中危"))
self.low_checkBox.setText(_translate("MainWindow", "低危"))
self.port_checkBox.setText(_translate("MainWindow", "端口"))
self.web_checkBox.setText(_translate("MainWindow", "网站"))
self.start_Button.setText(_translate("MainWindow", "开始导出"))

274
images_ico.py Normal file
View File

@@ -0,0 +1,274 @@
# -*- coding: utf-8 -*-
# Resource object code
#
# Created by: The Resource Compiler for PyQt5 (Qt v5.11.1)
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore
qt_resource_data = b"\
\x00\x00\x0e\x0a\
\x00\
\x01\x08\x3e\x78\x9c\xed\x9d\x49\x93\x24\x37\x15\xc7\x5f\x53\x86\
\x36\x6b\x03\x36\xcb\x89\x06\x8c\x61\x58\x8c\xc1\x10\x66\x9b\xe8\
\xe6\x03\xc0\x00\x76\xb0\x83\x3d\x9c\xd8\x2e\x6c\x26\x86\x60\xa0\
\x8b\xfd\x0a\x17\x22\x80\x23\x60\xb3\x9b\xd5\x36\x5c\xa8\x0f\x00\
\xc1\xbe\x0f\xe1\x82\x30\xbb\x81\x86\x08\x7b\x6a\xec\x66\x06\xfd\
\x4a\xd2\x74\x95\x26\x95\x99\x95\x99\xca\x54\x66\xe9\xef\xf8\x8f\
\x47\x1d\x3d\x95\x4a\x3d\xe9\x6d\x7a\x52\x89\x6c\xa8\xff\xc6\x63\
\x51\x7f\x3e\x56\x8e\x5c\xbc\x21\x8f\x14\x91\x23\x8a\xea\x47\xfc\
\x70\xfe\x73\x8d\x0d\xb9\xe4\x81\x32\x67\x42\xc2\x9a\xe3\x3e\x8a\
\xc7\x14\x9f\x69\xfe\x9e\xb0\x3e\xb8\x48\xf1\xb8\xe2\x1d\x8a\xb7\
\x2a\x3e\xb9\xd3\xde\x24\xb4\x09\xd6\xfa\x75\x8a\x7f\x51\x3c\xa7\
\x78\xb7\xe2\x37\x14\xaf\xea\xb2\x53\x09\xad\x60\x24\x5a\xf6\x7f\
\x12\x2d\xfb\x45\x7e\x59\xf1\x72\x49\xb6\x60\xa8\x40\xf6\xc7\xe5\
\x70\xdd\xbb\xbc\x47\xb4\x2d\x78\x56\x47\xfd\x4b\x08\x07\xd6\xf4\
\xeb\x24\x7b\xdd\x2f\xf2\x5e\xc5\x9b\x14\x9f\x2a\xf3\xc8\x29\x61\
\x00\xc0\xd7\x7b\x83\x14\xcb\x7e\x71\x0e\xdc\x26\xc9\x27\x1c\x02\
\x58\xc3\xaf\x57\xfc\xb3\x94\x93\xbd\xe5\x69\xc5\xaf\x88\x8e\x0d\
\x13\xfa\x09\xd6\xfd\xf5\x52\x7e\xdd\xbb\x3c\xab\xf8\x55\xc5\x27\
\x49\xf2\x09\xfb\x06\xe4\x85\xec\x7d\xbe\x5e\x59\xce\x14\xbf\x23\
\x29\x36\xec\x13\xf0\xf3\xd1\xf9\x55\xd7\xbd\xcb\xff\x29\x7e\x5e\
\xb4\x1e\x48\x3e\x61\xdc\x40\xf6\xf8\x7a\xab\xda\xfb\x22\x1e\x28\
\x7e\x4f\xf1\x29\xed\xbd\x4a\xc2\x8a\xb0\x31\x5e\xd3\xb2\x5f\xb4\
\x05\x5f\x54\x7c\x86\x24\x3d\x10\x1b\x6c\x3e\xbf\x29\x9d\x9f\x67\
\x0b\xc8\x15\x1f\x69\xe5\xad\x12\xca\x80\x75\x8f\xbd\xaf\xeb\xeb\
\x95\xe5\x5d\x8a\xdf\x16\xad\x07\x12\xba\x05\xeb\xde\x97\xcf\x0f\
\x4d\xf2\x84\x29\x36\xec\x0e\x8c\xfb\x71\x69\x6f\xdd\xbb\xb4\x79\
\xc2\xa7\x07\x7e\xcf\x84\x0b\x81\x9f\x5f\x26\x9f\x1f\x9a\xec\x19\
\xdd\xa8\x78\xa5\x24\x9f\xb0\x2d\xd8\x7c\x7e\x28\x3f\x7f\x55\x12\
\x1b\xde\x22\xda\x16\x24\x84\x05\x6b\x2c\x64\x8c\x57\x95\xd4\x90\
\x7c\x5d\x92\x4f\x18\x12\x6d\xc5\x78\x55\xc9\x7e\xc1\x97\x44\xef\
\x1b\x26\x9f\xb0\x59\xb8\x35\x5b\xb1\x92\x1c\x11\x3e\x61\xd2\x03\
\xcd\x21\xaf\x66\x2b\x46\xe2\x0f\xb0\x5f\xf0\x34\x49\x3e\x61\x5d\
\x14\xd5\x6c\xc5\x4a\xf2\x84\xec\x17\x24\x9f\xb0\x3a\xca\xd6\x6c\
\xc5\x4a\x6a\x48\xa8\x29\x4d\x35\x24\xab\x23\xb6\x18\xaf\x8e\x1e\
\xa0\x86\x04\x9f\x30\xd9\x82\x72\x88\x35\xc6\xab\x4a\x62\x43\xea\
\x8a\xaf\x6c\x72\x90\x06\x8a\xba\x35\x5b\xb1\x92\xd8\x90\x3c\x21\
\x75\xc5\x29\x36\xcc\x46\x53\x35\x5b\xb1\x92\xb8\xe0\xbb\x92\x6a\
\x48\xb2\x80\xec\x5f\x2d\xc3\xd1\xf9\x3e\x9e\x11\xed\x0f\x3c\xbb\
\x99\x61\x1b\x0c\xb6\x14\x3f\x23\xda\x5f\xea\x5a\x46\xa1\x89\x7e\
\x3b\xd6\xcc\xb0\x0d\x06\xf7\x55\xbc\x5a\xf1\x0b\xa2\x73\x68\x5d\
\xcb\x28\x14\xff\xa9\xf8\x16\xc5\xcd\x66\x86\x6d\x70\x78\x82\xe2\
\xb7\x44\xeb\xc9\xae\x65\xd5\x34\xff\xae\xf8\x66\xd1\x73\x7d\xdd\
\x41\x8c\x97\xe5\x07\xf3\x33\x7c\xe4\xcf\xc9\xb0\x6c\xc1\x9d\x8a\
\x6f\x12\xff\xba\x5f\xa7\xdc\x80\x8d\xf1\xc8\xef\xf8\xc6\x83\x9a\
\x1a\xf6\xd4\x87\x60\x0b\xfe\x21\x5a\xe7\xdf\xcf\xf3\xae\x8f\x52\
\xbc\x41\x74\x9e\x70\xe8\xf3\x60\x31\xc6\xfb\x9d\xe2\x4b\xc4\x3f\
\x07\xb0\x05\xd4\x5b\x13\x37\x75\x2d\xc3\x3a\xb2\x7f\xa3\xf8\x65\
\xff\x68\xc5\x4f\x8b\xb6\x77\xe4\x88\x9e\x98\x37\x78\x3d\x87\x5b\
\xb3\x85\x7e\xff\x8d\xe8\xf9\x30\xca\xf8\x7d\xd6\x02\xe7\xae\xc8\
\xa1\xf7\x51\x0f\xa0\xf3\xdf\x2a\xfe\xf9\xfd\x08\xd1\x31\xcf\x69\
\xf3\xfb\xfc\xff\x66\x19\xe6\x7e\x41\xde\xb9\x9c\x5f\x28\x5e\xa3\
\xe8\xbb\x95\xec\x71\xa2\x7d\xc2\x3e\xe9\x01\x7c\x3d\xec\xbd\xcf\
\xd7\x43\xe7\x23\xfb\x7b\x9d\x7f\xc7\x9a\xa0\x86\x84\x1c\xd1\x50\
\xf2\x84\x65\xf2\xf9\xbf\x57\x7c\xb9\x64\xeb\x01\xc6\x81\xbd\x74\
\x62\xc3\x3e\xcc\x81\xa2\x18\x8f\xeb\xf9\xd0\xf9\x3e\x9d\x86\x1e\
\xb8\xd5\xbc\x73\xdf\xb1\x4a\xcd\xd6\x4f\x45\x9f\xe3\xb8\xd8\xf3\
\x59\x8c\x07\x67\x71\x4f\xe7\x7c\x46\xd7\x64\xdd\x23\x7b\xdf\xba\
\xb7\x3a\xff\x9e\x82\xcf\xb1\x35\x24\x57\x48\x7f\x7d\xc2\x2a\x35\
\x5b\xa7\x44\xe7\xc6\x2e\xca\xf8\x3c\xc6\x81\x7a\x0a\xf6\x51\x62\
\x8c\x0d\x6d\x8c\x97\xe7\xe7\x7f\x4a\xca\xe7\x36\xd8\x33\x42\x0f\
\x5c\xee\xf9\xbc\x98\x51\xb5\x66\xcb\xfa\x84\xc7\x25\xdb\x16\x00\
\x7c\x42\xce\xe0\xc5\x94\x23\xc2\xcf\xc7\xd7\xf3\xc9\xde\xae\xfb\
\x55\xfd\x58\xde\x11\xff\xb7\x4f\xfb\x05\x4d\xd4\x6c\xfd\x52\x74\
\x6c\xe8\xf3\x09\x1f\x2f\x7a\x0e\xc4\xe0\x0f\x94\x8d\xf1\x8a\x74\
\x7e\xde\x9a\x20\x2e\xe8\x43\x2d\x59\x93\x35\x5b\xbf\x15\xbd\x27\
\x98\xa5\x07\xf8\x19\xf5\x14\xf8\x84\x5d\xea\x81\x22\x5f\x8f\x75\
\x8f\xec\xeb\xfa\x2c\xb6\x86\xe4\x0a\xcf\x73\x62\x40\x88\x9a\xad\
\x9f\x88\x9e\x03\xf7\xf7\x3c\x93\xba\x2a\x62\xc3\x2e\x7c\xc2\xa2\
\x18\x0f\x3f\x3f\x2b\xc6\xab\x4a\xf4\x00\xbe\x0f\x73\xc0\x67\x1b\
\xbb\x42\xc8\x9a\x2d\x62\xc3\x17\x8b\x3f\x36\xe4\x2c\x3e\xe3\x72\
\x36\xc0\xb3\xf3\xd6\x3d\x7b\x39\x79\x31\x1e\xbe\x5e\xd3\x79\x2b\
\xe6\xd2\x2d\x12\xd7\xfd\x03\xa1\xcf\xe5\x20\xd7\x5f\x99\x67\xf8\
\xd6\x1a\x39\x33\xce\xe4\xb7\x91\x27\x6c\x2a\xc6\xab\x4a\xec\x1d\
\x79\x71\xee\x29\xed\x3a\x36\x6c\xb3\x66\x8b\x3c\x21\x3e\xa1\x2f\
\x3f\x70\x99\xe8\xda\x9a\x90\xb1\x21\x31\x5e\x91\xaf\xb7\x4a\x8c\
\x57\x67\x4d\x7c\x53\xf4\x1e\x49\x57\x68\xfa\x9e\xad\x22\x22\x57\
\x7c\x42\xec\x4c\x56\x6e\x94\xb5\x80\x1e\x08\x55\x43\x62\xf3\xf9\
\x4d\xc7\x78\x55\x89\xcf\x83\xef\xd3\xc5\x59\x33\x1b\xe3\x75\x51\
\xaf\xf7\x33\xd1\xb9\xe2\x07\x78\xfa\x46\xbe\x84\x71\x69\x52\xff\
\x86\x8e\xf1\xaa\x92\xf8\x17\x5b\x40\x6e\xb4\xad\xfd\x82\x18\xce\
\xe5\xe0\x13\xbe\x54\xfc\xb1\x21\x71\x01\x7a\xa0\x09\x9f\xb0\xad\
\x18\xaf\x2a\xd1\x37\xc4\x86\x6d\xd4\x15\xaf\x7a\x97\x72\x28\x22\
\xd7\x9f\x8b\xf6\x3d\x7c\x72\x21\x3f\x80\x1e\xb8\xbb\xc6\x73\x8a\
\x6a\xb6\x6c\x8c\xd7\xf6\xba\x77\xc9\xf3\xb9\x8f\x28\xe4\xdd\x74\
\x6d\xdf\xb3\x55\x86\xc4\x05\xc4\x86\x3e\xf9\x60\x0b\xd0\x8f\x55\
\x7c\xc2\xa2\x18\xcf\xe6\xf3\x63\xaa\x4d\x20\x06\xba\xcc\xd3\xdf\
\x3a\x88\xf5\x5c\x0e\x72\x3d\x65\xfa\xe6\xb3\x7f\xec\x17\x70\x97\
\xf7\x2a\x72\x2a\xaa\xd9\xb2\xbe\x5e\x4c\x7b\x10\xe7\x4c\x7f\xc8\
\x15\x37\xb9\x5f\xd0\x87\x73\x39\xd8\x82\x6b\xc5\xbf\x5f\x80\x1e\
\x60\x6d\x94\xd1\x03\xb1\xfa\x7a\x65\xc9\x3b\xb2\x67\xd4\xc4\xf7\
\x17\xb4\x1d\xe3\xd5\x21\xf5\x84\xaf\x10\xbf\x4f\x48\x5d\x31\x3e\
\x61\x9e\xdc\x62\x8b\xf1\xaa\x12\x5f\x94\xb3\x66\x75\x6a\x48\x42\
\xdd\xa5\x1c\x92\xc4\x86\xcc\x57\xdf\x7e\x01\xe3\x41\xde\x24\xcb\
\x27\xac\x5a\xb3\x15\x2b\xed\x77\xd9\xe0\x13\xae\x1a\x1b\xf6\xf9\
\x0c\x36\x39\xa2\x17\x49\x76\x0d\x09\xe3\x40\xce\xcc\x8d\x0d\xcb\
\xd6\x6c\xc5\x5c\x7b\x94\x45\xf2\x03\xd4\x4c\xad\x52\x57\x1c\xfb\
\x3d\x5b\x45\x44\xae\xa7\xa4\xb8\x86\x84\xfb\xda\xf0\x97\xb0\xf7\
\x79\x31\x5e\xe8\x7c\x7e\x68\xda\x33\xa7\x57\x7b\xde\x6f\x11\x7d\
\xb9\x67\xab\x0c\xb1\x05\xe4\x88\x7c\x79\x42\xab\x07\x90\x7d\x53\
\x35\x5b\xb1\x92\x35\x71\xb3\xe4\xef\x17\x74\x79\x97\x72\xa8\x77\
\x46\x0f\xbc\x46\xfc\x67\xcd\x88\x95\x7d\xfb\x49\xb1\xc6\x78\x55\
\x89\xed\xe2\x6e\xba\xac\x7b\x48\xfa\x7a\xcf\x56\x19\x52\x57\xcc\
\x1c\xf0\xe9\x81\x2c\xc4\x1e\xe3\x55\x25\x3e\x21\x3a\x8f\x39\x60\
\xd7\x04\xeb\xbe\xeb\x7c\x7e\x68\xda\xb3\x66\x3e\x3d\xbf\x88\xbe\
\xfa\x7a\x65\xc9\x9c\xa6\x86\xc4\xde\x49\xc5\xda\xe8\xa3\x9f\xbf\
\x0a\xb1\x05\xb6\xae\x38\x0f\xd8\x82\x4f\x4a\x7f\x62\xbc\xaa\x24\
\x7f\xf1\x35\xd1\x39\x91\x8f\x29\xee\x47\xd0\xa7\xd0\x24\xc6\x7b\
\x95\xe4\x03\x7f\x8f\x5c\x71\x8c\xe7\x0b\x9a\xe6\x0f\x45\xdb\x01\
\x6c\xdd\xdb\x14\xff\x1a\x41\x9f\x42\xb1\xa8\x66\xcb\x02\x5b\x48\
\x6c\x38\xf4\x7b\x48\x7e\xa0\xf8\x1c\x39\xf4\x01\xb8\x7f\xe7\x83\
\x32\xcc\x39\x50\x74\x2e\x27\x0b\xd4\xda\x63\x23\x87\xa8\x07\x58\
\xf7\xcf\xcd\x78\x67\xe6\xc0\x3b\x14\xff\x15\x41\x1f\x9b\x94\x7d\
\x5e\x3e\x9f\xfd\xa2\x2c\x9d\x40\x3c\xc4\x1c\xe8\xfb\xfd\x03\x2e\
\x59\xf7\xcf\xf3\x8c\x05\xb8\x54\xf1\xbd\x32\x8c\x38\xb0\xcc\x3e\
\xde\x27\x44\xef\x71\xf8\x72\x00\xd8\x47\xf2\x84\x77\x45\xf0\x3e\
\x75\xc9\xba\x2f\x93\x03\x24\x4e\xde\x53\xfc\x77\x04\x7d\xae\xca\
\xb2\x35\x5b\xd8\xf8\xbc\x1a\x12\xe2\x23\x72\x66\xf8\x84\x6d\x9e\
\x2f\x68\x9a\xac\xfb\xe7\x7b\xc6\x22\x0b\x97\x88\xb6\x05\x7d\xd4\
\x03\x65\x6b\xb6\x6c\x8c\x87\x5c\x6f\x17\x9d\xfb\xf4\xed\x17\x50\
\x6b\xcf\x9e\x7a\x1f\x73\x81\xc8\xbe\xcc\xba\x77\xf1\x10\xc5\x8f\
\x88\x5e\x4b\x5d\xbf\x43\x59\xd6\xa9\xd9\xe2\xac\x19\x35\x24\xbe\
\x3c\x21\x7b\x68\x7d\xf3\x09\xd1\xf9\xab\xac\x7b\x17\xf8\x84\xc4\
\x86\x7d\xf0\x09\x6d\xcd\x56\xd1\x3e\x5e\xde\x1a\xa6\xae\xd8\x57\
\x43\x62\xef\xa6\xbb\xb1\xe0\x33\x62\xa1\x8d\xf1\xea\x02\x5b\x30\
\x96\xb8\x73\x84\x4d\xd6\x6c\xb1\x6f\x48\x3e\xdc\x57\x43\xc2\xf9\
\x4b\x6a\x48\x62\xce\x0f\xb0\xee\x9b\x90\xbd\xc5\x83\x45\xc7\x05\
\x31\xfa\x84\x21\x6a\xb6\xc8\x15\x53\x43\xe2\x8b\x0d\xd9\x37\xc4\
\x1f\x88\xd1\x27\x5c\xd5\xd7\x2b\x0b\xc6\xf1\x5d\x12\x97\x4f\x68\
\xd7\x7d\x88\x9a\x2d\x5b\x57\xec\xfb\x6c\xf2\x84\xd4\x55\xd4\x39\
\x5f\xd0\x34\xcb\xc6\x78\x55\x41\xbe\xe4\xa3\x12\x87\x1e\x68\xa3\
\x66\xeb\xc7\x8a\x2f\xcb\x79\x06\x3e\x21\xb6\x20\x06\x9f\x90\x75\
\xff\x02\x4f\x3f\x9b\x84\xf5\x09\xef\x6c\xf9\xfd\x16\xd9\xd6\xb9\
\x1c\xf4\xfb\x54\xf4\xbe\x51\xd6\xb9\x1a\x7e\x46\x8e\x88\xbb\xba\
\xba\xf4\x07\xaa\xc6\x78\x55\xf1\x30\xc5\x0f\x49\x37\x3e\x61\xd1\
\x5d\xca\x21\xce\xe5\x14\xdd\x43\x42\x5c\x40\x6c\xd8\x45\xae\x18\
\x9d\x9f\x97\xd3\x0d\x05\xf2\x03\xef\x96\x76\x6d\x41\x97\xe7\x72\
\xa8\x21\x39\xe6\x79\xf6\xa2\x4f\xd8\xa6\x2d\x60\xdd\x67\xed\xe5\
\xb4\x05\xf4\xec\x09\x69\x67\xdf\x30\x86\x73\x39\xe4\x8a\xaf\x17\
\xbf\xee\xb1\x3e\x61\x1b\xfb\x05\x4d\xc7\x78\x55\x81\x4f\x88\x2d\
\x08\x99\x23\x42\xe7\xc7\x72\x06\x9b\x7a\x42\x5f\x2d\x99\xdd\x2f\
\xa0\xd6\x36\xa4\x1e\x08\x15\xe3\x55\xc5\xc3\x45\xfb\x84\x7f\x93\
\xe6\xdf\x35\xb6\x73\x39\xf8\x84\x7f\x10\x7f\x5d\x31\x40\x0f\x70\
\xf6\x26\x84\x1d\x6a\xdb\xd7\x2b\x8b\x87\x8a\xde\x2f\x40\x5e\x4d\
\xbd\x6b\xdd\xbb\x94\x43\x92\xd8\xf0\x95\xe2\xdf\x2f\xa0\xbe\x92\
\x7a\xeb\x26\xf5\x40\xdd\x7c\x7e\x68\x3c\x48\xf1\xed\xd2\x4c\x3d\
\x61\xd7\xf7\x6c\x95\x21\x39\xa2\x6b\x3c\x7d\x44\x37\x50\x43\x72\
\x53\x43\x7d\x8c\x75\xdd\xbb\xa0\x86\xe4\x7d\x52\x2f\x36\x2c\xaa\
\xd9\x6a\xeb\x9e\xad\x22\xda\x7b\x48\x38\x73\xea\xd3\x51\x9c\xbf\
\xa4\x86\xa4\x8e\x6f\xe2\xab\xd9\x8a\x15\xe8\x81\xf7\x4b\x35\x9f\
\x30\xd4\x5d\xca\x21\x49\x5c\xc0\x7e\x41\xd6\x1c\x40\x0f\xf0\x1d\
\x16\xd4\x5b\x57\xd9\x2f\x28\xaa\xd9\x8a\x15\xec\x1b\x62\x0b\x56\
\x89\x0d\x63\x88\xf1\xaa\xf2\x76\xd1\xfb\x86\x59\xe7\x8e\x01\x3e\
\x21\xf5\x84\xab\xcc\xdb\xd0\xf9\xfc\xd0\x20\x47\xc4\x7e\x41\x99\
\x1a\x92\xd8\xef\xd9\x2a\xc3\x1f\x89\xbe\x9b\xce\x57\x4f\xc8\x7e\
\x01\xe7\xb1\xcb\xe4\x09\x63\x8b\xf1\xaa\x02\x5b\x40\x6c\x98\x97\
\x27\x6c\xfb\x2e\xe5\x50\xb4\xfb\x05\xbe\xef\xb2\x21\x3f\x40\xae\
\xf8\xb3\x92\xef\xbb\xf4\xc5\xd7\x2b\x0b\x6c\xc1\x07\x24\xfb\x8c\
\x61\x1f\xef\xd9\x2a\xa2\xfd\x2e\x9b\xbc\xef\x37\x44\x0f\x64\xd9\
\xb1\xd8\x63\xbc\xaa\xa0\x86\x84\x5c\xf1\xa2\x1e\x68\xa2\x66\x2b\
\x56\x72\x0f\x09\xfb\x05\x59\xb6\xc0\xfa\x84\xee\x7d\xc5\x4d\xd5\
\x6c\xc5\x0a\x5b\x43\x42\x9e\xb0\xcc\x5d\xca\xf6\xbb\x11\xbb\x96\
\x65\x9d\x39\x70\x5d\xce\x3b\x2e\x7e\xbf\x61\xdf\x62\xbc\xaa\xc0\
\x1f\x20\x4f\x58\x66\x1f\xaf\x4f\x3a\xdf\x47\xf2\x84\xd4\x15\xfb\
\x6c\x01\x39\xa2\x8f\xcb\x30\x75\xbe\x0f\xd4\x90\xf8\x7c\x64\xec\
\x7d\xac\x31\x5e\x15\xe2\x13\xfe\x51\x74\xae\xd8\x77\x0f\xc9\xa5\
\x25\xc6\x6c\x1d\x30\xe4\xbb\x17\xd0\x03\xaf\x15\x7f\x0d\xc9\xba\
\xc3\xee\xe3\x0d\x65\xdd\x67\x91\xfd\x02\xea\x09\xd3\x1c\x58\x06\
\xb6\xe0\xc3\x32\x6c\xd9\x43\x6c\xc1\xaf\x45\xdf\x4b\x96\x70\x08\
\xf2\x84\xd4\x90\xf4\xe9\xac\x59\x55\xe2\xe7\x5f\xd5\xcc\xb0\x0d\
\x06\xe4\xc5\xc8\x11\x91\x27\x6c\xb2\x7e\x20\x36\xc6\x52\xb3\x15\
\x2b\xa8\x2b\x26\x36\x24\x2f\xd4\xb5\xac\x9a\xe6\x50\xf2\xf9\xa1\
\x81\x6f\xc4\xbe\xe1\x7f\xa4\x7b\x99\x35\x29\xfb\x21\xe5\xf3\x43\
\x83\x78\x98\xfa\x81\x21\xdc\x49\x98\xd6\x7d\x35\xb0\x5f\x70\x52\
\xfa\x71\xf6\x3c\xad\xfb\x30\x20\x0f\xfc\x4e\xe9\xa7\x4f\xd8\xd5\
\xb9\x9c\xa1\x81\x5c\x31\x3e\x61\x97\xe7\x0d\xab\xac\xfb\x75\xd8\
\xcb\x69\x0b\xec\x19\xf5\xe5\x6e\xba\xbe\xd7\x6c\xc5\x0a\x7c\x42\
\x5f\x0d\x49\x2c\x4c\xbe\x5e\x58\x70\xd6\x8c\x1a\x92\x18\x63\xc3\
\xe4\xeb\xb5\x03\xf6\x08\x39\x77\x1c\xe2\xac\x59\x1d\x9d\x9f\xd6\
\x7d\x7b\xb0\xfb\x05\x31\xe4\x09\x87\x5e\xb3\x15\x2b\x38\x6f\x88\
\x4f\xd8\x65\x5c\xb0\x2e\x35\x5b\xb1\x02\x9f\x90\x7b\xcb\xbb\xb0\
\x05\x7d\x3d\x97\x33\x34\xb0\x5f\x80\x3f\xf0\x5f\x69\x77\xdd\x27\
\x5f\x2f\x1e\x90\x27\xe4\x7e\xc2\x36\xee\x23\x6a\xeb\x9e\xad\x84\
\xd5\x80\x4f\xb8\x27\x61\xfd\x81\x14\xe3\xc5\x0d\x7b\x6f\x79\x88\
\xb8\x20\xe5\xf3\xfb\x01\x6a\x48\xa8\x25\x6c\x72\xcf\x28\xc5\x78\
\xfd\x02\x3e\xe1\x0d\xd2\x4c\x9e\x30\xd5\x6c\xf5\x13\xf8\x84\xdc\
\x43\x72\x87\xd4\x5b\xf7\x29\xaf\xd7\x5f\xb0\x5f\x50\xf5\xde\xf2\
\xe4\xeb\x0d\x03\x55\x6a\x48\xd2\xba\x1f\x16\xec\xf7\x1b\x96\x99\
\x03\x69\xdd\x0f\x13\xd4\x13\x72\xf6\x3c\xef\x8c\x49\x8a\xf1\x86\
\x0d\xeb\x13\x66\xe5\x09\x53\xcd\xd6\x7a\x80\xb3\x86\xef\x91\xe5\
\xd8\x30\xe9\xfc\xf5\x02\x35\x24\x63\xd1\xf5\x84\x7c\xd7\xcf\x0b\
\xbb\xec\x4c\x97\x38\x97\x8d\x83\xdd\xe5\xf6\xcc\x69\xef\x6f\x2f\
\xb7\xa7\x9b\xcb\xed\x89\xd3\x1e\x6f\x2c\xb7\x65\xb9\x7d\x56\x64\
\x6f\xe9\xf1\x22\x4b\x0f\x9c\x39\xed\x7d\xe5\xd1\x2d\x3d\xde\x69\
\x4f\x44\x46\x4b\x8f\x77\xda\xea\xc5\x17\x3b\xc0\xa9\xdc\xc5\x0e\
\x1c\x38\x6d\x6e\x21\x91\xed\xa5\xc7\x2f\xb5\xa7\xb4\x17\x3a\x30\
\xa1\xbd\xf0\xc0\xb1\xd3\x76\x86\xfe\xac\xd3\x3e\xd0\xed\xdd\xa5\
\xc7\x2f\x3c\x70\xdf\x69\x4f\x75\xfb\xfc\x90\x4f\x9c\xf6\x58\xb7\
\x47\x65\xdb\xce\xe7\x9d\x31\xed\xad\xef\x9b\xc7\xdb\xfe\x98\x37\
\x9e\x9e\xd0\xed\x1d\xd3\x9e\x1c\xd5\xed\x93\xe6\x03\xc6\x8f\xd1\
\xed\x99\x19\xf2\xb9\x33\xae\x04\xb0\xbf\x61\xde\x7e\x53\x8f\xd7\
\x54\x0f\xf9\x81\x8c\xe6\x6d\xf5\xd3\x3d\xfd\xf6\x1b\xf3\x17\xde\
\x1a\xeb\x37\xde\xd7\xb7\x0b\xcb\xb6\x19\x81\xa9\xae\x08\x94\x1d\
\x23\x82\xc9\xfc\xaf\xf3\xa3\x23\x23\xf3\x76\xf3\x0e\xcc\x4c\x5b\
\x7f\x94\xfe\x50\x33\xf8\x74\x60\x34\xd5\x6d\x06\x9f\x0e\xcc\x3b\
\xb5\xa7\x07\x9f\xdf\xe5\xdf\xf0\xc0\xf9\xb3\xf7\xe7\x8f\x9f\xb7\
\xa7\xe6\x59\x3b\x66\xc8\xe6\x7d\x3f\xaa\x4f\xae\xd0\x1e\x9b\xbe\
\xce\xcc\x10\xeb\xa1\x1c\xeb\x77\x12\x23\xfb\xcd\xf1\x48\x0f\xb2\
\x91\xfd\x68\xaa\xc7\x44\x76\xf5\x58\x6f\x4c\xb7\xb4\x90\xb6\x8d\
\xec\x67\xdb\x46\x26\x46\x36\x27\x77\x4c\x5b\xff\x33\x39\x7a\x52\
\xcc\x07\x1b\x59\x19\x99\xd9\xef\xb0\xd9\x32\x9f\x63\xb1\x39\xcd\
\x6f\xdb\xe7\x88\xf3\x79\x23\xf3\xbc\x1d\x33\x07\x46\x6e\x7f\x6c\
\x7f\xcd\x1c\xd8\x32\xef\xb3\x6f\xde\x67\xd7\x79\xdf\x3d\xdd\xde\
\x9c\x98\x0f\xde\x5b\x1e\xaf\x8d\xc3\xf1\xb4\xed\xf9\xef\xed\x1c\
\x8e\xf7\xbc\x03\x0b\xf2\x98\xff\xde\xcc\xcc\x81\x2d\x47\x9e\xbb\
\x46\xde\x53\x33\x52\xbb\x17\xce\x87\xf3\xf3\xc5\xb6\xc7\x46\xf6\
\x76\x3e\x4d\x0e\xe7\xdb\xa6\x99\x8f\xf3\xbe\x1c\x35\xed\x7d\x23\
\x7b\x3b\x5f\xcf\xcf\x67\xd3\x3e\x30\x83\x66\xe7\xbb\xbb\x1e\xce\
\xe9\xae\xaa\x0e\x98\xf5\x33\x36\xb2\x9f\x99\x05\x3b\x31\x63\x7d\
\xc2\xb4\xa7\x46\xf6\x76\x3d\xba\xeb\xf5\x8c\x91\xc9\xd6\x6e\xf6\
\x7a\xb7\xfa\xa3\xb4\xbe\x70\xdb\xee\xe7\xb9\xfa\xca\xf4\xc7\x3e\
\xfe\x02\x7d\xe7\xea\x43\x57\x5f\x5e\xa0\x4f\x27\x4e\x7b\x6a\x64\
\xbd\xd4\x81\xed\xc3\xb6\xab\xcf\x5d\x7d\xef\xda\x03\xd7\x5e\xd0\
\x81\xa5\xf6\x64\xe1\x6d\x4d\x07\x96\xec\x91\x6b\xaf\x5c\x7b\xe6\
\xda\xbb\xb3\xae\x61\x76\xdb\xae\x3d\x75\xed\xad\x6b\x8f\x5d\x7b\
\x3d\xb3\xed\xff\x03\xa4\x68\xdb\xc8\
"
qt_resource_name = b"\
\x00\x0b\
\x0a\xb8\x56\x7f\
\x00\x66\
\x00\x61\x00\x76\x00\x69\x00\x63\x00\x6f\x00\x6e\x00\x2e\x00\x69\x00\x63\x00\x6f\
"
qt_resource_struct_v1 = b"\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\
"
qt_resource_struct_v2 = b"\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x01\x65\xeb\xd5\xeb\xa7\
"
qt_version = [int(v) for v in QtCore.qVersion().split('.')]
if qt_version < [5, 8, 0]:
rcc_version = 1
qt_resource_struct = qt_resource_struct_v1
else:
rcc_version = 2
qt_resource_struct = qt_resource_struct_v2
def qInitResources():
QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
def qCleanupResources():
QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
qInitResources()

10
main.py Normal file
View File

@@ -0,0 +1,10 @@
import sys
from PyQt5.QtWidgets import QApplication
from gui.mainwindow import MainWindow
if __name__ == '__main__':
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
sys.exit(app.exec_())