Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a6aba5a2a | ||
|
|
ca0ec1f99d | ||
|
|
4e167486a1 | ||
|
|
503bbcd995 | ||
|
|
b160d2f634 | ||
|
|
2e7628a837 | ||
|
|
1259948ed7 | ||
|
|
81881ae1a4 | ||
|
|
0b5c581aca | ||
|
|
eb3614ed0c | ||
|
|
eb50513277 | ||
|
|
c3af73b8cf | ||
|
|
b552164a13 | ||
|
|
b6dc9ecadb | ||
|
|
0723dc8dbb | ||
|
|
0b1fffb5bf | ||
|
|
a39d87e5c5 | ||
|
|
0b0c3310cf | ||
|
|
f75c3750a5 | ||
|
|
3da760721b | ||
|
|
a9ad3feeec |
No files matched your search
Binary file not shown.
@@ -70,7 +70,7 @@ class MainWindow_Controller(QMainWindow): # 初始化主程式
|
||||
|
||||
def init_config_vars(self): # 初始化變數
|
||||
self.pyae_version = "AI Engine"
|
||||
self.pyas_version = "3.2.9"
|
||||
self.pyas_version = "3.3.0"
|
||||
self.mbr_value = None
|
||||
self.track_proc = None
|
||||
self.first_startup = 1
|
||||
@@ -78,6 +78,7 @@ class MainWindow_Controller(QMainWindow): # 初始化主程式
|
||||
self.gc_collect = 0
|
||||
self.block_window = 0
|
||||
self.total_scan = 0
|
||||
self.scan_time = 0
|
||||
self.virus_lock = {}
|
||||
self.virus_list_ui = []
|
||||
self.Process_quantity = 0
|
||||
@@ -1194,6 +1195,7 @@ class MainWindow_Controller(QMainWindow): # 初始化主程式
|
||||
pass
|
||||
self.scan_file = True
|
||||
self.total_scan = 0
|
||||
self.scan_time = time.time()
|
||||
self.virus_lock = {}
|
||||
self.virus_list_ui = []
|
||||
self.ui.Virus_Scan_Solve_Button.hide()
|
||||
@@ -1270,17 +1272,19 @@ class MainWindow_Controller(QMainWindow): # 初始化主程式
|
||||
try:
|
||||
QMetaObject.invokeMethod(self.ui.Virus_Scan_title, "setText",
|
||||
Qt.QueuedConnection, Q_ARG(str, self.trans("病毒掃描")))
|
||||
if self.virus_lock:
|
||||
if self.virus_list_ui:
|
||||
self.ui.Virus_Scan_Solve_Button.show()
|
||||
self.ui.Virus_Scan_Break_Button.hide()
|
||||
self.ui.Virus_Scan_choose_Button.show()
|
||||
text = self.trans(f"當前發現 {len(self.virus_lock)} 個病毒,共掃描 {self.total_scan} 個檔案")
|
||||
text = self.trans(f"當前發現 {len(self.virus_list_ui)} 個病毒")
|
||||
else:
|
||||
self.virus_scan_break()
|
||||
text = self.trans("當前未發現病毒")
|
||||
takes_time = int(time.time() - self.scan_time) + 1
|
||||
text_end = self.trans(f",耗時 {takes_time} 秒,共掃描 {self.total_scan} 個檔案")
|
||||
QMetaObject.invokeMethod(self.ui.Virus_Scan_text, "setText",
|
||||
Qt.QueuedConnection, Q_ARG(str, text))
|
||||
self.send_notify(text)
|
||||
Qt.QueuedConnection, Q_ARG(str, text+text_end))
|
||||
self.send_notify(text+text_end)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
@@ -1363,21 +1367,21 @@ class MainWindow_Controller(QMainWindow): # 初始化主程式
|
||||
|
||||
def start_scan(self, file): # 調用掃描引擎
|
||||
try:
|
||||
match_data = self.model.get_type(file)
|
||||
for section, data in match_data.items():
|
||||
label, level = self.model.dl_scan(data)
|
||||
if label and label in self.model.detect:
|
||||
if self.config_json["sensitivity"]:
|
||||
return f"{label}.{level}"
|
||||
elif level >= self.model.values:
|
||||
return f"{label}.{level}"
|
||||
label, level = self.model.dl_scan(file)
|
||||
if label and self.config_json["sensitivity"]:
|
||||
return f"{label}.{level}"
|
||||
elif label and level >= self.model.values:
|
||||
return f"{label}.{level}"
|
||||
except Exception as e:
|
||||
print(e)
|
||||
try:
|
||||
if self.config_json["extend_mode"]:
|
||||
label, level = self.rules.yr_scan(file)
|
||||
if label and isinstance(level, str):
|
||||
return f"{label}.{level}"
|
||||
return False
|
||||
except:
|
||||
return False
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return False
|
||||
|
||||
def repair_system(self): # 修復系統
|
||||
try:
|
||||
|
||||
+76
-42
@@ -1,5 +1,5 @@
|
||||
import os, sys, time, json, yara
|
||||
import numpy, pefile, onnxruntime
|
||||
import os, sys, time, json, yara, numpy
|
||||
import chardet, pefile, onnxruntime
|
||||
from PIL import Image
|
||||
|
||||
class YRScan:
|
||||
@@ -38,19 +38,27 @@ class YRScan:
|
||||
class DLScan:
|
||||
def __init__(self):
|
||||
self.models = {}
|
||||
self.valid_interpolations = {"none": Image.Resampling.NEAREST,
|
||||
"box": Image.Resampling.BOX, "bilinear": Image.Resampling.BILINEAR,
|
||||
"hamming": Image.Resampling.HAMMING, "bicubic": Image.Resampling.BICUBIC,
|
||||
"lanczos": Image.Resampling.LANCZOS, "nearest": Image.Resampling.NEAREST}
|
||||
self.shells = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!o',
|
||||
'cry', 'test', 'ace', 'yg', 'obr', 'tvm', 'dec', 'enc', 'b1_', 'base',
|
||||
'bss', 'clr_uef', 'cursors', 'trs_age', 'engine', 'enigma', 'protect',
|
||||
'nep', 'no_bbt', 'wpp_sf', 'retpol', 'rt', 'rwexec', 'rygs', 'poolmi',
|
||||
's:@', 'pgae', 'proxy', 'wisevec', 'segm', 'transit', 'vmp', 'extjmp',
|
||||
'upx', 'tracesup', 'res', 'lzma', 'malloc_h', 'miniex', 'ndr64', 'be',
|
||||
'mssmixer', 'wow', 'press', 'fio', 'pad', 'hexpthk', 'h~;', 'icapsec',
|
||||
'sanontcp', 'secur', 'asmstub', 'nsys_wr', 'orpc', 'pack', 'wow64svc',
|
||||
'uedbg', 'viahw', 'data', 'zk', 'fothk', 'qihoo']#"""
|
||||
self.valid_interpolations = {
|
||||
"box": Image.Resampling.BOX,
|
||||
"none": Image.Resampling.NEAREST,
|
||||
"bilinear": Image.Resampling.BILINEAR,
|
||||
"hamming": Image.Resampling.HAMMING,
|
||||
"bicubic": Image.Resampling.BICUBIC,
|
||||
"lanczos": Image.Resampling.LANCZOS,
|
||||
"nearest": Image.Resampling.NEAREST}
|
||||
|
||||
shell_section = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||
"cry", "tvm", "dec", "enc", "vmp", "upx", "aes", "lzma", "press",
|
||||
"pack", "enigma", "protect", "secur"]
|
||||
unknown_section = ["asmstub", "base", "bss", "clr_uef", "cursors",
|
||||
"engine", "fio", "fothk", "h~;", "icapsec", "malloc_h", "miniex",
|
||||
"mssmixer", "ndr64", "nsys_wr", "obr", "wow", "wow64svc", "wpp_sf",
|
||||
"pad", "pgae", "poolmi", "proxy", "qihoo", "res", "retpol", "uedbg",
|
||||
"rwexec", "rygs", "s:@", "sanontcp", "segm", "test", "tracesup",
|
||||
"transit", "trs_age", "wisevec"]
|
||||
unimportant_section = ["viahwaes", "orpc", "nep", "ace", "extjmp",
|
||||
"no_bbt", "data", "page", "hexpthk"]
|
||||
self.shells = shell_section + unimportant_section + unknown_section
|
||||
|
||||
def load_model(self, file_path):
|
||||
try:
|
||||
@@ -68,38 +76,63 @@ class DLScan:
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
def dl_scan(self, file_data):
|
||||
def dl_scan(self, file_path):
|
||||
try:
|
||||
label_similarities = {label: [] for label in self.labels}
|
||||
image_data = self.preprocess_image(file_data, tuple(self.resize))
|
||||
image_array = numpy.asarray(image_data).astype('float32') / 255.0
|
||||
image_expand = numpy.expand_dims(image_array, axis=(0, -1))
|
||||
batch_images = []
|
||||
for section, file_data in self.get_type(file_path).items():
|
||||
image_data = self.preprocess_image(file_data, tuple(self.resize))
|
||||
image_array = numpy.asarray(image_data).astype('float32') / 255.0
|
||||
if len(image_array.shape) == 2:
|
||||
image_array = numpy.expand_dims(image_array, axis=-1)
|
||||
batch_images.append(image_array)
|
||||
batch_results = [{label: [] for label in self.labels} for _ in range(len(batch_images))]
|
||||
batch_images = numpy.stack(batch_images, axis=0)
|
||||
for model_name, model in self.models.items():
|
||||
input_name = model.get_inputs()[0].name
|
||||
pre_answers = model.run(None, {input_name: image_expand})[0][0]
|
||||
for k, score in enumerate(pre_answers):
|
||||
label_similarities[self.labels[k].strip()].append(score)
|
||||
label_percentage = {label: (sum(similarities) / len(self.models)) * 100
|
||||
for label, similarities in label_similarities.items()}
|
||||
label, level = max(label_percentage.items(), key=lambda x: x[1])
|
||||
return label, int(level)
|
||||
predictions = model.run(None, {input_name: batch_images})[0]
|
||||
for i, pre_answers in enumerate(predictions):
|
||||
for k, score in enumerate(pre_answers):
|
||||
batch_results[i][self.labels[k].strip()].append(score)
|
||||
final_results = []
|
||||
for result in batch_results:
|
||||
label_percentage = {label: (sum(scores) / len(scores)) * 100
|
||||
for label, scores in result.items()}
|
||||
best_label, best_confidence = max(label_percentage.items(), key=lambda x: x[1])
|
||||
final_results.append((best_label, int(best_confidence)))
|
||||
if best_label in self.detect:
|
||||
return best_label, int(best_confidence)
|
||||
return False, False
|
||||
except Exception as e:
|
||||
return False, False
|
||||
|
||||
def preprocess_image(self, file_data, target_size):
|
||||
width, height, channels, interpolation = target_size
|
||||
wah = int(numpy.ceil(numpy.sqrt(len(file_data))))
|
||||
file_data = numpy.frombuffer(file_data, dtype=numpy.uint8)
|
||||
image_array = numpy.zeros((wah * wah,), dtype=numpy.uint8)
|
||||
image_array[:len(file_data)] = file_data
|
||||
wah = int(numpy.ceil(numpy.sqrt(len(file_data) / channels)))
|
||||
array_data = numpy.frombuffer(file_data, dtype=numpy.uint8)
|
||||
expected_size = wah * wah * channels
|
||||
image_array = numpy.zeros((expected_size,), dtype=numpy.uint8)
|
||||
image_array[:len(file_data)] = array_data
|
||||
if channels == 1:
|
||||
image = Image.fromarray(image_array.reshape((wah, wah)), 'L')
|
||||
reshape = image_array.reshape((wah, wah))
|
||||
image = Image.fromarray(reshape, 'L')
|
||||
elif channels == 3:
|
||||
image = Image.fromarray(image_array.reshape((wah, wah)), 'RGB')
|
||||
reshape = image_array.reshape((wah, wah, 3))
|
||||
image = Image.fromarray(reshape, 'RGB')
|
||||
if width == 0 and height == 0:
|
||||
return image
|
||||
interpolations = self.valid_interpolations[interpolation.lower()]
|
||||
return image.resize((width, height), interpolations)
|
||||
i = self.valid_interpolations.get(interpolation.lower(), Image.BILINEAR)
|
||||
return image.resize((width, height), i)
|
||||
|
||||
def is_text_file(self, content, sample_size):
|
||||
try:
|
||||
raw_data = content[:sample_size]
|
||||
encoding = chardet.detect(raw_data)["encoding"]
|
||||
if encoding in ["ascii", "utf-8", "utf-8-sig"]:
|
||||
if raw_data.decode(encoding):
|
||||
return True
|
||||
return False
|
||||
except:
|
||||
return False
|
||||
|
||||
def get_type(self, file_path):
|
||||
match_data = {}
|
||||
@@ -108,13 +141,14 @@ class DLScan:
|
||||
try:
|
||||
with pefile.PE(file_path, fast_load=True) as pe:
|
||||
for section in pe.sections:
|
||||
section_name = section.Name.rstrip(b'\x00').decode('latin1')
|
||||
name = section.Name.rstrip(b'\x00').decode('latin1')
|
||||
if (section.Characteristics & 0x00000020 and not
|
||||
any(shell in section_name.lower() for shell in self.shells)):
|
||||
match_data[section_name] = section.get_data()
|
||||
any(s in name.lower() for s in self.shells)):
|
||||
print(name)
|
||||
match_data[name] = section.get_data()
|
||||
except:
|
||||
if ftype in [".bat", ".cmd", ".ps1", ".vbs", ".wsf", ".html",
|
||||
".js", ".txt", ".htm", ".hta", ".php", ".css", ".xml", ".json"]:
|
||||
with open(file_path, 'rb') as file:
|
||||
match_data[ftype] = file.read()
|
||||
with open(file_path, 'rb') as f:
|
||||
file_content = f.read()
|
||||
if self.is_text_file(file_content, 1024):
|
||||
match_data[ftype] = file_content
|
||||
return match_data
|
||||
+1
-1
@@ -1112,7 +1112,7 @@ class Ui_MainWindow(object):
|
||||
self.Window_title.setGeometry(QtCore.QRect(10, 0, 661, 41))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Microsoft YaHei")
|
||||
font.setPointSize(15)
|
||||
font.setPointSize(13)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
self.Window_title.setFont(font)
|
||||
|
||||
+2
-1
@@ -62,4 +62,5 @@ translate_dict = {
|
||||
"指定":"Specify ","清空":"Empty ","資源回收桶":"Recycle Bin ",
|
||||
"與":"With ","當":"When ","功能":"Function ","異常":"Abnormal ",
|
||||
"重置":"Reset ","窗口":"Window ","暫存":"Temp ","自訂":"Custom ",
|
||||
"不支持":"Not Support ","共":"Total ","時":""," ":" "}}
|
||||
"不支持":"Not Support ","共":"Total ","秒":"Seconds ","耗時":"Takes ",
|
||||
"時":""," ":" "}}
|
||||
+1
-1
@@ -2,7 +2,7 @@ import pyinstaller_versionfile
|
||||
|
||||
pyinstaller_versionfile.create_versionfile(
|
||||
output_file="versionfile.txt",
|
||||
version='3.2.9',
|
||||
version='3.3.0',
|
||||
company_name="PYAS Security",
|
||||
file_description="Python Antivirus Software",
|
||||
internal_name="PYAS",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# PYAS (Python Antivirus Software)
|
||||
|
||||

|
||||

|
||||
|
||||
## Readme Language
|
||||
|
||||
@@ -11,13 +11,15 @@
|
||||
## Requirements
|
||||
|
||||
```
|
||||
pip install pefile==2023.2.7
|
||||
pip install pyperclip==1.8.2
|
||||
pip install PyQt5==5.15.9
|
||||
pip install yara-python==4.5.1
|
||||
pip install numpy==2.1.1
|
||||
pip install chardet==5.2.0
|
||||
pip install numpy==1.26.3
|
||||
pip install onnxruntime==1.18.1
|
||||
pip install pefile==2023.2.7
|
||||
pip install pillow==10.4.0
|
||||
pip install pyperclip==1.8.2
|
||||
pip install PyQt5==5.15.11
|
||||
pip install requests==2.32.3
|
||||
pip install yara-python==4.5.1
|
||||
```
|
||||
|
||||
## File Information
|
||||
|
||||
+8
-6
@@ -1,17 +1,19 @@
|
||||
# PYAS (Python 杀毒软件)
|
||||
|
||||

|
||||

|
||||
|
||||
## 安装要求
|
||||
|
||||
```
|
||||
pip install pefile==2023.2.7
|
||||
pip install pyperclip==1.8.2
|
||||
pip install PyQt5==5.15.9
|
||||
pip install yara-python==4.5.1
|
||||
pip install numpy==2.1.1
|
||||
pip install chardet==5.2.0
|
||||
pip install numpy==1.26.3
|
||||
pip install onnxruntime==1.18.1
|
||||
pip install pefile==2023.2.7
|
||||
pip install pillow==10.4.0
|
||||
pip install pyperclip==1.8.2
|
||||
pip install PyQt5==5.15.11
|
||||
pip install requests==2.32.3
|
||||
pip install yara-python==4.5.1
|
||||
```
|
||||
|
||||
## 文件信息
|
||||
|
||||
+8
-6
@@ -1,17 +1,19 @@
|
||||
# PYAS (Python 防毒軟體)
|
||||
|
||||

|
||||

|
||||
|
||||
## 安裝要求
|
||||
|
||||
```
|
||||
pip install pefile==2023.2.7
|
||||
pip install pyperclip==1.8.2
|
||||
pip install PyQt5==5.15.9
|
||||
pip install yara-python==4.5.1
|
||||
pip install numpy==2.1.1
|
||||
pip install chardet==5.2.0
|
||||
pip install numpy==1.26.3
|
||||
pip install onnxruntime==1.18.1
|
||||
pip install pefile==2023.2.7
|
||||
pip install pillow==10.4.0
|
||||
pip install pyperclip==1.8.2
|
||||
pip install PyQt5==5.15.11
|
||||
pip install requests==2.32.3
|
||||
pip install yara-python==4.5.1
|
||||
```
|
||||
|
||||
## 檔案資訊
|
||||
|
||||
Reference in new issue
Block a user