Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
316882bcd0 | ||
|
|
b204e52297 | ||
|
|
f82a63f4c8 | ||
|
|
cb0f2108a4 | ||
|
|
300b7a7a68 | ||
|
|
c3852ca60d | ||
|
|
a5fb735c93 | ||
|
|
d0b04ba84f | ||
|
|
9552742a39 | ||
|
|
8e9bdf6c0c | ||
|
|
818cc48502 | ||
|
|
adc4e28eb8 | ||
|
|
2e3a4d3bf1 | ||
|
|
d9bcac78e7 | ||
|
|
2342947849 | ||
|
|
19204dee8d | ||
|
|
863fa90b80 | ||
|
|
6fdef4a8f1 | ||
|
|
9469ceaa02 | ||
|
|
857f184409 | ||
|
|
a2f4a725f5 | ||
|
|
d12449bbb9 | ||
|
|
a41f4711dd | ||
|
|
3c2b018d49 | ||
|
|
e221a09709 | ||
|
|
26ff4bd843 | ||
|
|
d8e28f384a | ||
|
|
65e68c3cc4 | ||
|
|
7b76ab2a59 | ||
|
|
ae2a01b463 | ||
|
|
cda022a9f4 | ||
|
|
672e48c5f8 | ||
|
|
6fbdb1354f | ||
|
|
79bc7fd443 | ||
|
|
5578dd3339 | ||
|
|
0232dbd196 | ||
|
|
d44e192eaa | ||
|
|
4f12b19cf8 | ||
|
|
392ac1b1c7 | ||
|
|
8ad175aca3 | ||
|
|
6afa58c42b | ||
|
|
8be03cf232 | ||
|
|
23ea53d3ff | ||
|
|
294f40e7ac | ||
|
|
4f5f706ee5 |
No files matched your search
@@ -1,11 +0,0 @@
|
|||||||
[hollows_hunter]
|
|
||||||
|
|
||||||
https://github.com/hasherezade/hollows_hunter/releases
|
|
||||||
|
|
||||||
[pe_sieve]
|
|
||||||
|
|
||||||
https://github.com/hasherezade/pe-sieve/releases
|
|
||||||
|
|
||||||
[bitdefender]
|
|
||||||
|
|
||||||
https://github.com/87owo/bdc/tree/main/bitdefender
|
|
||||||
@@ -1 +1,9 @@
|
|||||||
{"Unknown": [59361295766927921263572072001677546892988818127554310688483531901728654248638, 110146453841778647644166243240178520536267161301604245683743524756419353678059], "White": [37818885244835446256584092883046666135310645230383968345516924743398787357048, 10034220084157156036025657182253677958809969876761493145101084060869839222562, 30518116137695254451083185640456062095466770588446551409776635626107619414618, 32296846483328285395942578479721462990874016817205213442337788571183455371823, 7830743514133643609056906037298883461849915236781505447055526355864156291200, 66766369194849842633273514861399590319048611179974316399223444661664643713116, 18024800263813114636032380772014473234719112317372083568645028513107740333097, 74141606019826610219493597417961411759319222262715747781530975858236840023868, 74141606019826815907563358349687985248520689328534980167895213718026559231805, 84904953027467628079124577278247620589188804906104233927770018096001490752110, 8646406253524489099322407463506197113190436222475229989113834496391933123177, 14801368362037157341349744372212469879911751347796432685445396742546138510527, 15894490895528857350444326816435305421376809085313851765402083488609039987721, 37852894007605849489952583567731004955434986444474399453030571998864861533218, 16007569107674673947537681801726481062730991620317178346097127572834907239433, 102633388988062357389851477595292272698878804202828382582477913233599597957741, 17029311058216545115926699358460765117955315322529387410067408192737238368209, 39401039939065971500355367115014580663179206620663500436171381542235009920591, 39402615232602811526308130026613523510869149389568467968898508123483647642239, 57593384293411341144654776428448217689576185693893444758365608040444018144505, 63841662487000088869831851027369141702999289853288215195372474540672652085448, 100721919041136871706536474323993763361887751761059594887258624287814536108709, 12431907255329162502980182262719209577155616944639082427720737656418745431535, 16038275485812550557063681634389014806352822616164076985257408379680031643065, 68405324198120933521050931648638618947369327745692667495883448104257901548799, 3460329908515126754637554126738713109961637027606158804093048546688108127547, 16106981637946225230178918605857052277649628614369112854963742434861832205050, 8448811436767749824740074881636806461590780110247030409064405873065872770413, 62657160528879197025196349384429226461581551965396254612319502660762849907110, 37362668350600312578741767096565745429284532702326298726894669202918919902841, 97046915551360110482543666063995603342646642693483132604859660767038789191075, 37750578778823141127513876578977618263821979566798398805475475810686050547035, 8899077763068952446283397850676779377182951563966752995966724510608273388087, 1430788410790588948768223740715242946047023771808936478434300982280927461576, 43245632164876912500721802614250505089424972269458388051200703985150176517646, 26527792976855638931546424443043598748359981077520025569533358689339312846119, 10034220138179482424453837496189500567990928858614529504432172551818139334184, 75535532059353249758793259643426543087630044975480683666280772562494352167023, 12532294779822530931293583148085641907686342350743362041338935273017351016633, 8958249342307639770700867008480561646791855695021266630701977360245761685282, 75528466396530722925390012197706855368372892751585509291513494409511440650351, 9011044384631604789230921306476923910566615376824882388358022480957734033082, 45182323877874305146934038679574733861884144375370883472937974036860962247097, 23700234601492692370460015976854345996007097410933046970328742403104651126256, 56970414078810407267232512181524454646035403709151864648837102879926562472603, 59336812026319177033098081135706956314151111314270392143237555422332208264206, 36707091377963660336346311143415935299335610930952028052854530836452557240295, 10202126012237964170766432051989140199469409759127192355002576100131006440555, 72691028651131468636833670875287650881223005399741112439972503306595446550906, 7689046024044190685500958862986168840617876576117297404374223308117258686587, 9583067470336071575558967777508800030690386213881092335354663342137641199143, 15970718419268871463478468058858796238959885761999117728999272834817179322168, 37903470032839160921304992353748519593005839718701840574746932332397170697534, 10723799110029366222468551244518699011059498785302648324191607904247307866219, 1651465247876746049352538052494320238190633259932155654005236273442992146011, 37535310575907540138572260167287591050679295649847144262742970882242576643629, 107406046477759675380805009872206073473308094017534113788736360913659778137364, 8648260909849054742383860213694016683253742610217956634993385753930945566715, 91094487239729265765473251155982579898413742412111963107157224383047507474015, 45128834383092335423669974709008139367933699120247789381146368929605724538431, 21573189465171437665670533096295878202170520697880590329439115191190251349169, 776778Line truncated
|
{
|
||||||
|
"Labels": ["White/Pefile", "White/Script", "Virus/Pefile", "Virus/Script"],
|
||||||
|
|
||||||
|
"Detect": ["Virus/Pefile", "Virus/Script"],
|
||||||
|
|
||||||
|
"Pixels": [224, 224],
|
||||||
|
|
||||||
|
"Values": 95
|
||||||
|
}
|
||||||
Binary file not shown.
@@ -1,12 +1,10 @@
|
|||||||
import os, gc, sys, time, json, yara
|
import os, gc, sys, time, json, psutil
|
||||||
import pefile, socket, msvcrt, psutil
|
import ctypes, struct, msvcrt, pyperclip
|
||||||
import requests, pyperclip, win32file
|
import win32gui, win32api, win32con, win32file
|
||||||
import win32gui, win32api, win32con
|
from PYAS_Engine import YRScan, DLScan
|
||||||
from PYAS_Engine import ListSimHash
|
|
||||||
from PYAS_Suffixes import slist, alist
|
from PYAS_Suffixes import slist, alist
|
||||||
from PYAS_Language import translate_dict
|
from PYAS_Language import translate_dict
|
||||||
from PYAS_Interface import Ui_MainWindow
|
from PYAS_Interface import Ui_MainWindow
|
||||||
from PYAS_Extension import ExtenRules
|
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from PyQt5.QtWidgets import *
|
from PyQt5.QtWidgets import *
|
||||||
from PyQt5.QtCore import *
|
from PyQt5.QtCore import *
|
||||||
@@ -15,25 +13,14 @@ from subprocess import *
|
|||||||
|
|
||||||
class MainWindow_Controller(QMainWindow):
|
class MainWindow_Controller(QMainWindow):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# init program window
|
|
||||||
super(MainWindow_Controller, self).__init__()
|
super(MainWindow_Controller, self).__init__()
|
||||||
self.setAttribute(Qt.WA_TranslucentBackground)
|
self.setAttribute(Qt.WA_TranslucentBackground)
|
||||||
self.setWindowFlags(Qt.FramelessWindowHint)
|
self.setWindowFlags(Qt.FramelessWindowHint)
|
||||||
|
|
||||||
# get self program path
|
|
||||||
self.pyas = sys.argv[0].replace("\\", "/")
|
self.pyas = sys.argv[0].replace("\\", "/")
|
||||||
self.dir = os.path.dirname(self.pyas)
|
self.dir = os.path.dirname(self.pyas)
|
||||||
exdir = os.path.join(self.dir, "Exten")
|
self.pyae_version = "AI Engine"
|
||||||
self.exdir = exdir.replace("\\", "/")
|
self.pyas_version = "3.2.1"
|
||||||
|
|
||||||
# init self program version
|
|
||||||
self.pyae_version = "Fusion Engine"
|
|
||||||
self.pyas_version = "3.1.5"
|
|
||||||
|
|
||||||
# startup ui config
|
|
||||||
self.first_startup = True
|
self.first_startup = True
|
||||||
|
|
||||||
# init program config
|
|
||||||
self.init_data_base()
|
self.init_data_base()
|
||||||
self.init_tray_icon()
|
self.init_tray_icon()
|
||||||
self.init_config_qtui()
|
self.init_config_qtui()
|
||||||
@@ -44,18 +31,14 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
self.init_startup()
|
self.init_startup()
|
||||||
|
|
||||||
def init_threads(self):
|
def init_threads(self):
|
||||||
# init protect thread
|
|
||||||
self.protect_proc_init()
|
self.protect_proc_init()
|
||||||
self.protect_file_init()
|
self.protect_file_init()
|
||||||
self.protect_sys_init()
|
self.protect_sys_init()
|
||||||
self.protect_drv_init()
|
self.protect_drv_init()
|
||||||
self.protect_net_init()
|
self.protect_net_init()
|
||||||
|
|
||||||
# init tools thread
|
|
||||||
self.block_window_init()
|
self.block_window_init()
|
||||||
|
|
||||||
def init_tray_icon(self):
|
def init_tray_icon(self):
|
||||||
# init taskbar tray and icon
|
|
||||||
self.tray_icon = QSystemTrayIcon(self)
|
self.tray_icon = QSystemTrayIcon(self)
|
||||||
self.tray_icon.activated.connect(self.init_show_pyas)
|
self.tray_icon.activated.connect(self.init_show_pyas)
|
||||||
self.tray_icon.setIcon(QFileIconProvider().icon(QFileInfo(self.pyas)))
|
self.tray_icon.setIcon(QFileIconProvider().icon(QFileInfo(self.pyas)))
|
||||||
@@ -63,70 +46,45 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
|
|
||||||
def init_startup(self):
|
def init_startup(self):
|
||||||
try:
|
try:
|
||||||
# check startup ui args
|
|
||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
param = sys.argv[1]
|
param = sys.argv[1]
|
||||||
if "h" not in param:
|
if "h" not in param:
|
||||||
self.init_show_pyas()
|
self.init_show_pyas()
|
||||||
elif len(sys.argv) <= 1:
|
elif len(sys.argv) <= 1:
|
||||||
self.init_show_pyas()
|
self.init_show_pyas()
|
||||||
|
|
||||||
# startup ui complete
|
|
||||||
self.first_startup = False
|
self.first_startup = False
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def init_data_base(self):
|
def init_data_base(self):
|
||||||
try:
|
try:
|
||||||
# init exten path ./Exten/* (from import)
|
self.model = DLScan()
|
||||||
self.exten = ExtenRules()
|
data_path = os.path.join(self.dir, "Model")
|
||||||
|
|
||||||
# init model path ./Model/* (from import)
|
|
||||||
self.model = ListSimHash()
|
|
||||||
data_path = os.path.join(self.dir, "Model")
|
|
||||||
for root, dirs, files in os.walk(data_path):
|
for root, dirs, files in os.walk(data_path):
|
||||||
for file in files:
|
for file in files:
|
||||||
file_path = os.path.join(root, file)
|
file_path = os.path.join(root, file)
|
||||||
ftype = str(f".{file.split('.')[-1]}").lower()
|
self.model.load_model(file_path)
|
||||||
if ftype in [".json",".txt"]:
|
self.rules = YRScan()
|
||||||
# SimHash model json file
|
|
||||||
self.model.load_model(file_path)
|
|
||||||
|
|
||||||
# init yara path ./Rules/* (from import)
|
|
||||||
self.rules = {}
|
|
||||||
data_path = os.path.join(self.dir, "Rules")
|
data_path = os.path.join(self.dir, "Rules")
|
||||||
for root, dirs, files in os.walk(data_path):
|
for root, dirs, files in os.walk(data_path):
|
||||||
for file in files:
|
for file in files:
|
||||||
file_path = os.path.join(root, file)
|
file_path = os.path.join(root, file)
|
||||||
ftype = str(f".{file.split('.')[-1]}").lower()
|
self.rules.load_rules(file_path)
|
||||||
if ftype in [".yara", ".yar"]:
|
|
||||||
# not compile yara rules
|
|
||||||
rules = yara.compile(file_path)
|
|
||||||
elif ftype in [".yc", ".yrc"]:
|
|
||||||
# compiled yara rules
|
|
||||||
rules = yara.load(file_path)
|
|
||||||
self.rules[file_path] = rules
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.bug_event(e)
|
self.bug_event(e)
|
||||||
|
|
||||||
def init_config_boot(self):
|
def init_config_boot(self):
|
||||||
try:
|
try:
|
||||||
# init read system boot
|
|
||||||
with open(r"\\.\PhysicalDrive0", "r+b") as f:
|
with open(r"\\.\PhysicalDrive0", "r+b") as f:
|
||||||
# backup system mbr value
|
|
||||||
self.mbr_value = f.read(512)
|
self.mbr_value = f.read(512)
|
||||||
|
|
||||||
# check if mbr is available
|
|
||||||
if self.mbr_value[510:512] != b'\x55\xAA':
|
if self.mbr_value[510:512] != b'\x55\xAA':
|
||||||
self.mbr_value = False
|
self.mbr_value = False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# possible permission denied
|
|
||||||
self.mbr_value = False
|
self.mbr_value = False
|
||||||
self.bug_event(self.trans(f"引導防護錯誤: ")+str(e))
|
self.bug_event(self.trans(f"引導防護錯誤: ")+str(e))
|
||||||
|
|
||||||
def write_config(self, config):
|
def write_config(self, config):
|
||||||
try:
|
try:
|
||||||
# write json configs in ProgramData
|
|
||||||
with open("C:/ProgramData/PYAS/PYAS.json", "w") as f:
|
with open("C:/ProgramData/PYAS/PYAS.json", "w") as f:
|
||||||
f.write(json.dumps(config, indent=4, ensure_ascii=False))
|
f.write(json.dumps(config, indent=4, ensure_ascii=False))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -134,57 +92,42 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
|
|
||||||
def init_config_read(self):
|
def init_config_read(self):
|
||||||
try:
|
try:
|
||||||
# init check exist process
|
|
||||||
self.track_proc = None
|
self.track_proc = None
|
||||||
self.exist_process = set()
|
self.exist_process = set()
|
||||||
for p in psutil.process_iter():
|
for p in psutil.process_iter():
|
||||||
self.exist_process.add(p.pid)
|
self.exist_process.add(p.pid)
|
||||||
|
|
||||||
# check config path exists
|
|
||||||
if not os.path.exists("C:/ProgramData/PYAS"):
|
if not os.path.exists("C:/ProgramData/PYAS"):
|
||||||
os.makedirs("C:/ProgramData/PYAS")
|
os.makedirs("C:/ProgramData/PYAS")
|
||||||
|
|
||||||
# check config file exists
|
|
||||||
if not os.path.exists("C:/ProgramData/PYAS/PYAS.json"):
|
if not os.path.exists("C:/ProgramData/PYAS/PYAS.json"):
|
||||||
self.write_config({"language":"en_US","theme_color":"White",
|
self.write_config({"language":"en_US","theme_color":"White",
|
||||||
"high_sensitive":0,"extension_kits":0,"cloud_services":"None"})
|
"high_sensitive":0,"extension_kits":0,"cloud_services":"None"})
|
||||||
try:
|
try:
|
||||||
# read config json data
|
|
||||||
with open("C:/ProgramData/PYAS/PYAS.json", "r") as f:
|
with open("C:/ProgramData/PYAS/PYAS.json", "r") as f:
|
||||||
self.json = json.load(f)
|
self.json = json.load(f)
|
||||||
except:
|
except:
|
||||||
self.json = {"language":"en_US","theme_color":"White",
|
self.json = {"language":"en_US","theme_color":"White",
|
||||||
"high_sensitive":0,"extension_kits":0,"cloud_services":"None"}
|
"high_sensitive":0,"extension_kits":0,"cloud_services":"None"}
|
||||||
|
|
||||||
# default json config
|
|
||||||
self.json["language"] = self.json.get("language", "en_US")
|
self.json["language"] = self.json.get("language", "en_US")
|
||||||
self.json["theme_color"] = self.json.get("theme_color", "White")
|
self.json["theme_color"] = self.json.get("theme_color", "White")
|
||||||
self.json["high_sensitive"] = self.json.get("high_sensitive", 0)
|
self.json["high_sensitive"] = self.json.get("high_sensitive", 0)
|
||||||
self.json["extension_kits"] = self.json.get("extension_kits", 0)
|
self.json["extension_kits"] = self.json.get("extension_kits", 0)
|
||||||
self.json["cloud_services"] = self.json.get("cloud_services", "None")
|
self.json["cloud_services"] = self.json.get("cloud_services", "None")
|
||||||
|
|
||||||
# reflash high_sensitive ui text
|
|
||||||
if self.json["high_sensitive"] == 1:
|
if self.json["high_sensitive"] == 1:
|
||||||
self.ui.high_sensitivity_switch_Button.setText(self.trans("已開啟"))
|
self.ui.high_sensitivity_switch_Button.setText(self.trans("已開啟"))
|
||||||
self.ui.high_sensitivity_switch_Button.setStyleSheet("""
|
self.ui.high_sensitivity_switch_Button.setStyleSheet("""
|
||||||
QPushButton{border:none;background-color:rgb(200, 250, 200);border-radius: 10px;}
|
QPushButton{border:none;background-color:rgb(200, 250, 200);border-radius: 10px;}
|
||||||
QPushButton:hover{background-color:rgb(210, 250, 210);}""")
|
QPushButton:hover{background-color:rgb(210, 250, 210);}""")
|
||||||
|
|
||||||
if self.json["extension_kits"] == 1:
|
if self.json["extension_kits"] == 1:
|
||||||
self.ui.extension_kit_switch_Button.setText(self.trans("已開啟"))
|
self.ui.extension_kit_switch_Button.setText(self.trans("已開啟"))
|
||||||
self.ui.extension_kit_switch_Button.setStyleSheet("""
|
self.ui.extension_kit_switch_Button.setStyleSheet("""
|
||||||
QPushButton{border:none;background-color:rgb(200, 250, 200);border-radius: 10px;}
|
QPushButton{border:none;background-color:rgb(200, 250, 200);border-radius: 10px;}
|
||||||
QPushButton:hover{background-color:rgb(210, 250, 210);}""")
|
QPushButton:hover{background-color:rgb(210, 250, 210);}""")
|
||||||
|
|
||||||
# reflash language ui setChecked
|
|
||||||
if self.json["language"] == "zh_TW":
|
if self.json["language"] == "zh_TW":
|
||||||
self.ui.Language_Traditional_Chinese.setChecked(True)
|
self.ui.Language_Traditional_Chinese.setChecked(True)
|
||||||
elif self.json["language"] == "zh_CN":
|
elif self.json["language"] == "zh_CN":
|
||||||
self.ui.Language_Simplified_Chinese.setChecked(True)
|
self.ui.Language_Simplified_Chinese.setChecked(True)
|
||||||
elif self.json["language"] == "en_US":
|
elif self.json["language"] == "en_US":
|
||||||
self.ui.Language_English.setChecked(True)
|
self.ui.Language_English.setChecked(True)
|
||||||
|
|
||||||
# reflash theme_color ui setChecked
|
|
||||||
if self.json["theme_color"] == "White":
|
if self.json["theme_color"] == "White":
|
||||||
self.ui.Theme_White.setChecked(True)
|
self.ui.Theme_White.setChecked(True)
|
||||||
elif self.json["theme_color"] == "Red":
|
elif self.json["theme_color"] == "Red":
|
||||||
@@ -197,14 +140,10 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
self.ui.Theme_Blue.setChecked(True)
|
self.ui.Theme_Blue.setChecked(True)
|
||||||
elif os.path.exists(self.json["theme_color"]):
|
elif os.path.exists(self.json["theme_color"]):
|
||||||
self.ui.Theme_Customize.setChecked(True)
|
self.ui.Theme_Customize.setChecked(True)
|
||||||
|
|
||||||
# read whitelist lines from ProgramData
|
|
||||||
self.whitelist = []
|
self.whitelist = []
|
||||||
if os.path.exists("C:/ProgramData/PYAS/Whitelist.ini"):
|
if os.path.exists("C:/ProgramData/PYAS/Whitelist.ini"):
|
||||||
with open("C:/ProgramData/PYAS/Whitelist.ini", "r") as f:
|
with open("C:/ProgramData/PYAS/Whitelist.ini", "r") as f:
|
||||||
self.whitelist = [l.strip() for l in f.readlines()]
|
self.whitelist = [l.strip() for l in f.readlines()]
|
||||||
|
|
||||||
# read blocklist lines from ProgramData
|
|
||||||
self.blocklist = []
|
self.blocklist = []
|
||||||
if os.path.exists("C:/ProgramData/PYAS/Blocklist.ini"):
|
if os.path.exists("C:/ProgramData/PYAS/Blocklist.ini"):
|
||||||
with open("C:/ProgramData/PYAS/Blocklist.ini", "r") as f:
|
with open("C:/ProgramData/PYAS/Blocklist.ini", "r") as f:
|
||||||
@@ -213,7 +152,6 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
self.bug_event(e)
|
self.bug_event(e)
|
||||||
|
|
||||||
def init_control(self):
|
def init_control(self):
|
||||||
# connect main ui and function control
|
|
||||||
self.ui.Close_Button.clicked.connect(self.close)
|
self.ui.Close_Button.clicked.connect(self.close)
|
||||||
self.ui.Minimize_Button.clicked.connect(self.showMinimized)
|
self.ui.Minimize_Button.clicked.connect(self.showMinimized)
|
||||||
self.ui.Menu_Button.clicked.connect(self.show_menu)
|
self.ui.Menu_Button.clicked.connect(self.show_menu)
|
||||||
@@ -221,8 +159,6 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
self.ui.Tools_Button.clicked.connect(self.change_tools_widget)
|
self.ui.Tools_Button.clicked.connect(self.change_tools_widget)
|
||||||
self.ui.Virus_Scan_Button.clicked.connect(self.change_scan_widget)
|
self.ui.Virus_Scan_Button.clicked.connect(self.change_scan_widget)
|
||||||
self.ui.Protection_Button.clicked.connect(self.change_protect_widget)
|
self.ui.Protection_Button.clicked.connect(self.change_protect_widget)
|
||||||
|
|
||||||
# connect scan ui and function control
|
|
||||||
self.ui.Virus_Scan_output.setContextMenuPolicy(Qt.CustomContextMenu)
|
self.ui.Virus_Scan_output.setContextMenuPolicy(Qt.CustomContextMenu)
|
||||||
self.ui.Virus_Scan_output.customContextMenuRequested.connect(self.Virus_Scan_output_menu)
|
self.ui.Virus_Scan_output.customContextMenuRequested.connect(self.Virus_Scan_output_menu)
|
||||||
self.ui.Virus_Scan_Solve_Button.clicked.connect(self.virus_solve)
|
self.ui.Virus_Scan_Solve_Button.clicked.connect(self.virus_solve)
|
||||||
@@ -231,8 +167,6 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
self.ui.File_Scan_Button.clicked.connect(self.file_scan)
|
self.ui.File_Scan_Button.clicked.connect(self.file_scan)
|
||||||
self.ui.Path_Scan_Button.clicked.connect(self.path_scan)
|
self.ui.Path_Scan_Button.clicked.connect(self.path_scan)
|
||||||
self.ui.Disk_Scan_Button.clicked.connect(self.disk_scan)
|
self.ui.Disk_Scan_Button.clicked.connect(self.disk_scan)
|
||||||
|
|
||||||
# connect tools ui and function control
|
|
||||||
self.ui.System_Process_Manage_Button.clicked.connect(lambda:self.change_tools(self.ui.Process_widget))
|
self.ui.System_Process_Manage_Button.clicked.connect(lambda:self.change_tools(self.ui.Process_widget))
|
||||||
self.ui.Process_Tools_Back.clicked.connect(lambda:self.back_to_tools(self.ui.Process_widget))
|
self.ui.Process_Tools_Back.clicked.connect(lambda:self.back_to_tools(self.ui.Process_widget))
|
||||||
self.ui.Repair_System_Files_Button.clicked.connect(self.repair_system)
|
self.ui.Repair_System_Files_Button.clicked.connect(self.repair_system)
|
||||||
@@ -243,15 +177,11 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
self.ui.Process_list.customContextMenuRequested.connect(self.process_list_menu)
|
self.ui.Process_list.customContextMenuRequested.connect(self.process_list_menu)
|
||||||
self.ui.About_Back.clicked.connect(self.ui.About_widget.hide)
|
self.ui.About_Back.clicked.connect(self.ui.About_widget.hide)
|
||||||
self.ui.Setting_Back.clicked.connect(self.setting_back)
|
self.ui.Setting_Back.clicked.connect(self.setting_back)
|
||||||
|
|
||||||
# connect protect ui and function control
|
|
||||||
self.ui.Protection_switch_Button.clicked.connect(self.protect_proc_init)
|
self.ui.Protection_switch_Button.clicked.connect(self.protect_proc_init)
|
||||||
self.ui.Protection_switch_Button_2.clicked.connect(self.protect_file_init)
|
self.ui.Protection_switch_Button_2.clicked.connect(self.protect_file_init)
|
||||||
self.ui.Protection_switch_Button_3.clicked.connect(self.protect_sys_init)
|
self.ui.Protection_switch_Button_3.clicked.connect(self.protect_sys_init)
|
||||||
self.ui.Protection_switch_Button_4.clicked.connect(self.protect_drv_init)
|
self.ui.Protection_switch_Button_4.clicked.connect(self.protect_drv_init)
|
||||||
self.ui.Protection_switch_Button_5.clicked.connect(self.protect_net_init)
|
self.ui.Protection_switch_Button_5.clicked.connect(self.protect_net_init)
|
||||||
|
|
||||||
# connect settings ui and function control
|
|
||||||
self.ui.high_sensitivity_switch_Button.clicked.connect(self.change_sensitive)
|
self.ui.high_sensitivity_switch_Button.clicked.connect(self.change_sensitive)
|
||||||
self.ui.extension_kit_switch_Button.clicked.connect(self.extension_kit)
|
self.ui.extension_kit_switch_Button.clicked.connect(self.extension_kit)
|
||||||
self.ui.Add_White_list_Button.clicked.connect(self.add_white_list)
|
self.ui.Add_White_list_Button.clicked.connect(self.add_white_list)
|
||||||
@@ -266,20 +196,13 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
self.ui.Theme_Red.clicked.connect(self.init_theme_color)
|
self.ui.Theme_Red.clicked.connect(self.init_theme_color)
|
||||||
|
|
||||||
def init_config_qtui(self):
|
def init_config_qtui(self):
|
||||||
# connect ui and variable control
|
|
||||||
self.ui = Ui_MainWindow()
|
self.ui = Ui_MainWindow()
|
||||||
self.ui.setupUi(self)
|
self.ui.setupUi(self)
|
||||||
|
|
||||||
# init virus scan list
|
|
||||||
self.virus_lock = {}
|
self.virus_lock = {}
|
||||||
self.virus_list = []
|
self.virus_list = []
|
||||||
self.virus_list_ui = []
|
self.virus_list_ui = []
|
||||||
|
|
||||||
# init process tools list
|
|
||||||
self.Process_quantity = []
|
self.Process_quantity = []
|
||||||
self.Process_list_all_pid = []
|
self.Process_list_all_pid = []
|
||||||
|
|
||||||
# connect effect ui and variable
|
|
||||||
self.Process_sim = QStringListModel()
|
self.Process_sim = QStringListModel()
|
||||||
self.Process_Timer = QTimer()
|
self.Process_Timer = QTimer()
|
||||||
self.Process_Timer.timeout.connect(self.process_list)
|
self.Process_Timer.timeout.connect(self.process_list)
|
||||||
@@ -313,34 +236,27 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
self.ui.About_widget.hide()
|
self.ui.About_widget.hide()
|
||||||
self.ui.State_output.style().polish(self.ui.State_output.verticalScrollBar())
|
self.ui.State_output.style().polish(self.ui.State_output.verticalScrollBar())
|
||||||
self.ui.Virus_Scan_output.style().polish(self.ui.Virus_Scan_output.verticalScrollBar())
|
self.ui.Virus_Scan_output.style().polish(self.ui.Virus_Scan_output.verticalScrollBar())
|
||||||
|
|
||||||
# PYAS License_terms
|
|
||||||
self.ui.License_terms.setText('''Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.''')
|
self.ui.License_terms.setText('''Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.''')
|
||||||
|
|
||||||
def init_change_lang(self):
|
def init_change_lang(self):
|
||||||
try:
|
try:
|
||||||
# change lang function with init or clicked
|
|
||||||
if self.ui.Language_Traditional_Chinese.isChecked():
|
if self.ui.Language_Traditional_Chinese.isChecked():
|
||||||
self.json["language"] = "zh_TW"
|
self.json["language"] = "zh_TW"
|
||||||
elif self.ui.Language_Simplified_Chinese.isChecked():
|
elif self.ui.Language_Simplified_Chinese.isChecked():
|
||||||
self.json["language"] = "zh_CN"
|
self.json["language"] = "zh_CN"
|
||||||
elif self.ui.Language_English.isChecked():
|
elif self.ui.Language_English.isChecked():
|
||||||
self.json["language"] = "en_US"
|
self.json["language"] = "en_US"
|
||||||
|
|
||||||
# write lang config and set lang text
|
|
||||||
self.write_config(self.json)
|
self.write_config(self.json)
|
||||||
self.init_lang_text()
|
self.init_lang_text()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.bug_event(e)
|
self.bug_event(e)
|
||||||
|
|
||||||
def trans(self, text):
|
def trans(self, text):
|
||||||
# from PYAS_Language import translate_dict
|
|
||||||
for k, v in translate_dict.get(self.json["language"], translate_dict).items():
|
for k, v in translate_dict.get(self.json["language"], translate_dict).items():
|
||||||
text = text.replace(str(k), str(v))
|
text = text.replace(str(k), str(v))
|
||||||
return text
|
return text
|
||||||
|
|
||||||
def init_lang_text(self):
|
def init_lang_text(self):
|
||||||
# original init language "zh_TW"
|
|
||||||
self.ui.State_title.setText(self.trans("此裝置已受到防護"))
|
self.ui.State_title.setText(self.trans("此裝置已受到防護"))
|
||||||
self.ui.Window_title.setText(self.trans(f"PYAS Security"))
|
self.ui.Window_title.setText(self.trans(f"PYAS Security"))
|
||||||
self.ui.PYAS_CopyRight.setText(self.trans(f"Copyright© 2020-{max(int(time.strftime('%Y')), 2020)} PYAS Security"))
|
self.ui.PYAS_CopyRight.setText(self.trans(f"Copyright© 2020-{max(int(time.strftime('%Y')), 2020)} PYAS Security"))
|
||||||
@@ -381,7 +297,7 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
self.ui.Window_Block_Button.setText(self.trans("軟體彈窗攔截"))
|
self.ui.Window_Block_Button.setText(self.trans("軟體彈窗攔截"))
|
||||||
self.ui.Repair_System_Network_Button.setText(self.trans("系統網路修復"))
|
self.ui.Repair_System_Network_Button.setText(self.trans("系統網路修復"))
|
||||||
self.ui.About_Back.setText(self.trans("返回"))
|
self.ui.About_Back.setText(self.trans("返回"))
|
||||||
self.ui.PYAS_Version.setText(self.trans(f"PYAS V{self.pyas_version} ({self.pyae_version})"))
|
self.ui.PYAS_Version.setText(self.trans(f"PYAS Security V{self.pyas_version} ({self.pyae_version})"))
|
||||||
self.ui.GUI_Made_title.setText(self.trans("介面製作:"))
|
self.ui.GUI_Made_title.setText(self.trans("介面製作:"))
|
||||||
self.ui.GUI_Made_Name.setText(self.trans("mtkiao"))
|
self.ui.GUI_Made_Name.setText(self.trans("mtkiao"))
|
||||||
self.ui.Core_Made_title.setText(self.trans("核心製作:"))
|
self.ui.Core_Made_title.setText(self.trans("核心製作:"))
|
||||||
@@ -415,7 +331,6 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
|
|
||||||
def init_theme_color(self):
|
def init_theme_color(self):
|
||||||
try:
|
try:
|
||||||
# set theme color (Maybe it can be further optimized?)
|
|
||||||
if self.ui.Theme_White.isChecked():
|
if self.ui.Theme_White.isChecked():
|
||||||
self.json["theme_color"] = "White"
|
self.json["theme_color"] = "White"
|
||||||
self.ui.State_icon.setPixmap(QPixmap(":/icon/Check.png"))
|
self.ui.State_icon.setPixmap(QPixmap(":/icon/Check.png"))
|
||||||
@@ -442,7 +357,6 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
self.ui.Window_widget.setStyleSheet("QWidget#Window_widget {background-color:rgb(250,250,230);}")
|
self.ui.Window_widget.setStyleSheet("QWidget#Window_widget {background-color:rgb(250,250,230);}")
|
||||||
self.ui.Navigation_Bar.setStyleSheet("QWidget#Navigation_Bar {background-color:rgb(250,250,220);}")
|
self.ui.Navigation_Bar.setStyleSheet("QWidget#Navigation_Bar {background-color:rgb(250,250,220);}")
|
||||||
elif self.ui.Theme_Customize.isChecked():
|
elif self.ui.Theme_Customize.isChecked():
|
||||||
# check customize theme config
|
|
||||||
if not os.path.exists(os.path.join(self.json["theme_color"],"Color.ini")):
|
if not os.path.exists(os.path.join(self.json["theme_color"],"Color.ini")):
|
||||||
path = str(QFileDialog.getExistingDirectory(self,self.trans("自定主題"),"C:/"))
|
path = str(QFileDialog.getExistingDirectory(self,self.trans("自定主題"),"C:/"))
|
||||||
if path and os.path.exists(os.path.join(path,"Color.ini")):
|
if path and os.path.exists(os.path.join(path,"Color.ini")):
|
||||||
@@ -453,10 +367,8 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
self.ui.Navigation_Bar.setStyleSheet(self.themecolor[1])
|
self.ui.Navigation_Bar.setStyleSheet(self.themecolor[1])
|
||||||
file = os.path.join(self.json["theme_color"],"Check.png")
|
file = os.path.join(self.json["theme_color"],"Check.png")
|
||||||
self.ui.State_icon.setPixmap(QPixmap(file))
|
self.ui.State_icon.setPixmap(QPixmap(file))
|
||||||
# write theme color config
|
|
||||||
self.write_config(self.json)
|
self.write_config(self.json)
|
||||||
except:
|
except:
|
||||||
# set default theme color when error
|
|
||||||
self.ui.Theme_White.setChecked(True)
|
self.ui.Theme_White.setChecked(True)
|
||||||
self.json["theme_color"] = "White"
|
self.json["theme_color"] = "White"
|
||||||
self.ui.State_icon.setPixmap(QPixmap(":/icon/Check.png"))
|
self.ui.State_icon.setPixmap(QPixmap(":/icon/Check.png"))
|
||||||
@@ -464,7 +376,6 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
self.ui.Navigation_Bar.setStyleSheet("QWidget#Navigation_Bar {background-color:rgb(230,230,230);}")
|
self.ui.Navigation_Bar.setStyleSheet("QWidget#Navigation_Bar {background-color:rgb(230,230,230);}")
|
||||||
|
|
||||||
def change_animation(self,widget):
|
def change_animation(self,widget):
|
||||||
# animation for widget
|
|
||||||
x, y = 170, widget.pos().y()
|
x, y = 170, widget.pos().y()
|
||||||
self.anim = QPropertyAnimation(widget, b"geometry")
|
self.anim = QPropertyAnimation(widget, b"geometry")
|
||||||
widget.setGeometry(QRect(x - 100,y, 671, 481))
|
widget.setGeometry(QRect(x - 100,y, 671, 481))
|
||||||
@@ -475,7 +386,6 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
self.anim.start()
|
self.anim.start()
|
||||||
|
|
||||||
def change_animation_2(self,nx,ny):
|
def change_animation_2(self,nx,ny):
|
||||||
# animation for scroll bar
|
|
||||||
x, y = self.ui.label.pos().x(), self.ui.label.pos().y()
|
x, y = self.ui.label.pos().x(), self.ui.label.pos().y()
|
||||||
self.anim2 = QPropertyAnimation(self.ui.label, b"geometry")
|
self.anim2 = QPropertyAnimation(self.ui.label, b"geometry")
|
||||||
if y > ny:
|
if y > ny:
|
||||||
@@ -495,7 +405,6 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
self.anim2.start()
|
self.anim2.start()
|
||||||
|
|
||||||
def change_animation_3(self,widget,time):
|
def change_animation_3(self,widget,time):
|
||||||
# animation for OpacityEffect
|
|
||||||
self.opacity = QGraphicsOpacityEffect()
|
self.opacity = QGraphicsOpacityEffect()
|
||||||
self.opacity.setOpacity(0)
|
self.opacity.setOpacity(0)
|
||||||
self.opacity.i = self.opacity.opacity()
|
self.opacity.i = self.opacity.opacity()
|
||||||
@@ -737,18 +646,20 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
# question event message
|
# question event message
|
||||||
print(f"[Quest] > {text}")
|
print(f"[Quest] > {text}")
|
||||||
if self.first_startup != True:
|
if self.first_startup != True:
|
||||||
return QMessageBox.question(self, "Quest", self.trans(str(text)),QMessageBox.Yes|QMessageBox.No) == 16384
|
return QMessageBox.question(self, "Quest",
|
||||||
|
self.trans(str(text)),QMessageBox.Yes|QMessageBox.No) == 16384
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def send_notify(self, text):
|
def send_notify(self, text, notify_bar=True):
|
||||||
try:
|
try:
|
||||||
# send system notification
|
# send system notification
|
||||||
now_time = time.strftime('%Y-%m-%d %H:%M:%S')
|
now_time = time.strftime('%Y-%m-%d %H:%M:%S')
|
||||||
print(f"[Notify] > [{now_time}] {text}")
|
print(f"[Notify] > [{now_time}] {text}")
|
||||||
if self.first_startup != True:
|
QMetaObject.invokeMethod(self.ui.State_output, "append",
|
||||||
|
Qt.QueuedConnection, Q_ARG(str, f"[{now_time}] {text}"))
|
||||||
|
if self.first_startup == False and notify_bar == True:
|
||||||
self.tray_icon.showMessage(now_time, text, 5000)
|
self.tray_icon.showMessage(now_time, text, 5000)
|
||||||
QMetaObject.invokeMethod(self.ui.State_output, "append", Qt.QueuedConnection, Q_ARG(str, f"[{now_time}] {text}"))
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -824,23 +735,6 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
QPushButton:hover{background-color:rgb(210,250,210);}""")
|
QPushButton:hover{background-color:rgb(210,250,210);}""")
|
||||||
self.write_config(self.json)
|
self.write_config(self.json)
|
||||||
|
|
||||||
def cloud_service(self):
|
|
||||||
try:
|
|
||||||
# cloud services config /ProgramData/PYAS.json
|
|
||||||
if self.json["cloud_services"] != "None":
|
|
||||||
# upload file cloud services
|
|
||||||
file = str(QFileDialog.getOpenFileName(self,self.trans("上報雲端分析"),"C:/")[0]).replace("\\", "/")
|
|
||||||
if file and self.question_event("您確定要上報雲端分析嗎?"):
|
|
||||||
response = requests.post(self.json["cloud_services"], files={'file': open(file, 'rb')})
|
|
||||||
if response.status_code == 200:
|
|
||||||
self.info_event(f"成功上報雲端分析: "+file)
|
|
||||||
else:
|
|
||||||
self.bug_event(response.status_code)
|
|
||||||
else:
|
|
||||||
self.bug_event(self.trans("未選擇雲端服務網站"))
|
|
||||||
except Exception as e:
|
|
||||||
self.bug_event(e)
|
|
||||||
|
|
||||||
def init_scan(self):
|
def init_scan(self):
|
||||||
try:
|
try:
|
||||||
self.ui.Virus_Scan_text.setText(self.trans("正在初始化中"))
|
self.ui.Virus_Scan_text.setText(self.trans("正在初始化中"))
|
||||||
@@ -896,18 +790,23 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
try:
|
try:
|
||||||
# delete file
|
# delete file
|
||||||
if self.ui.Virus_Scan_output.findItems(file, Qt.MatchContains)[0].checkState() == Qt.Checked:
|
if self.ui.Virus_Scan_output.findItems(file, Qt.MatchContains)[0].checkState() == Qt.Checked:
|
||||||
self.ui.Virus_Scan_title.setText(self.trans("正在刪除"))
|
QMetaObject.invokeMethod(self.ui.Virus_Scan_title, "setText",
|
||||||
self.ui.Virus_Scan_text.setText(file)
|
Qt.QueuedConnection, Q_ARG(str, self.trans("正在刪除")))
|
||||||
|
QMetaObject.invokeMethod(self.ui.Virus_Scan_text, "setText",
|
||||||
|
Qt.QueuedConnection, Q_ARG(str, file))
|
||||||
QApplication.processEvents()
|
QApplication.processEvents()
|
||||||
self.lock_file(file, False)
|
self.lock_file(file, False)
|
||||||
|
self.ransom_counts = 0
|
||||||
os.remove(file)
|
os.remove(file)
|
||||||
else:
|
else:
|
||||||
self.lock_file(file, False)
|
self.lock_file(file, False)
|
||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
self.ui.Virus_Scan_output.clear()
|
self.ui.Virus_Scan_output.clear()
|
||||||
self.ui.Virus_Scan_title.setText(self.trans("病毒掃描"))
|
QMetaObject.invokeMethod(self.ui.Virus_Scan_title, "setText",
|
||||||
self.ui.Virus_Scan_text.setText(self.trans("刪除成功"))
|
Qt.QueuedConnection, Q_ARG(str, self.trans("病毒掃描")))
|
||||||
|
QMetaObject.invokeMethod(self.ui.Virus_Scan_text, "setText",
|
||||||
|
Qt.QueuedConnection, Q_ARG(str, self.trans("刪除成功")))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.bug_event(e)
|
self.bug_event(e)
|
||||||
|
|
||||||
@@ -927,7 +826,8 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
|
|
||||||
def answer_scan(self):
|
def answer_scan(self):
|
||||||
try:
|
try:
|
||||||
self.ui.Virus_Scan_title.setText(self.trans("病毒掃描"))
|
QMetaObject.invokeMethod(self.ui.Virus_Scan_title, "setText",
|
||||||
|
Qt.QueuedConnection, Q_ARG(str, self.trans("病毒掃描")))
|
||||||
if self.virus_list:
|
if self.virus_list:
|
||||||
self.ui.Virus_Scan_Solve_Button.show()
|
self.ui.Virus_Scan_Solve_Button.show()
|
||||||
self.ui.Virus_Scan_Break_Button.hide()
|
self.ui.Virus_Scan_Break_Button.hide()
|
||||||
@@ -937,7 +837,8 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
self.virus_scan_break()
|
self.virus_scan_break()
|
||||||
text = self.trans("當前未發現病毒")
|
text = self.trans("當前未發現病毒")
|
||||||
self.scan_thread.join()
|
self.scan_thread.join()
|
||||||
self.ui.Virus_Scan_text.setText(text)
|
QMetaObject.invokeMethod(self.ui.Virus_Scan_text, "setText",
|
||||||
|
Qt.QueuedConnection, Q_ARG(str, text))
|
||||||
self.send_notify(text)
|
self.send_notify(text)
|
||||||
gc.collect()
|
gc.collect()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -947,8 +848,10 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
self.scan_file = False
|
self.scan_file = False
|
||||||
self.ui.Virus_Scan_Break_Button.hide()
|
self.ui.Virus_Scan_Break_Button.hide()
|
||||||
self.ui.Virus_Scan_choose_Button.show()
|
self.ui.Virus_Scan_choose_Button.show()
|
||||||
self.ui.Virus_Scan_text.setText(self.trans("請選擇掃描方式"))
|
QMetaObject.invokeMethod(self.ui.Virus_Scan_title, "setText",
|
||||||
self.ui.Virus_Scan_title.setText(self.trans("病毒掃描"))
|
Qt.QueuedConnection, Q_ARG(str, self.trans("病毒掃描")))
|
||||||
|
QMetaObject.invokeMethod(self.ui.Virus_Scan_text, "setText",
|
||||||
|
Qt.QueuedConnection, Q_ARG(str, self.trans("請選擇掃描方式")))
|
||||||
|
|
||||||
def virus_scan_menu(self):
|
def virus_scan_menu(self):
|
||||||
if self.ui.Virus_Scan_choose_widget.isHidden():
|
if self.ui.Virus_Scan_choose_widget.isHidden():
|
||||||
@@ -962,7 +865,8 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
file = str(QFileDialog.getOpenFileName(self,self.trans("病毒掃描"),"C:/")[0])
|
file = str(QFileDialog.getOpenFileName(self,self.trans("病毒掃描"),"C:/")[0])
|
||||||
if file and file not in self.whitelist and file != self.pyas:
|
if file and file not in self.whitelist and file != self.pyas:
|
||||||
self.init_scan()
|
self.init_scan()
|
||||||
self.scan_thread = Thread(target=self.write_scan, args=(self.start_scan(file),file,), daemon=True)
|
self.scan_thread = Thread(target=self.write_scan,
|
||||||
|
args=(self.start_scan(file),file,), daemon=True)
|
||||||
self.scan_thread.start()
|
self.scan_thread.start()
|
||||||
while self.scan_thread.is_alive():
|
while self.scan_thread.is_alive():
|
||||||
QApplication.processEvents()
|
QApplication.processEvents()
|
||||||
@@ -1008,8 +912,10 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
elif os.path.isdir(file):
|
elif os.path.isdir(file):
|
||||||
self.traverse_path(file)
|
self.traverse_path(file)
|
||||||
elif file != self.pyas and file not in self.whitelist:
|
elif file != self.pyas and file not in self.whitelist:
|
||||||
self.ui.Virus_Scan_title.setText(self.trans("正在掃描"))
|
QMetaObject.invokeMethod(self.ui.Virus_Scan_title, "setText",
|
||||||
self.ui.Virus_Scan_text.setText(file)
|
Qt.QueuedConnection, Q_ARG(str, self.trans("正在掃描")))
|
||||||
|
QMetaObject.invokeMethod(self.ui.Virus_Scan_text, "setText",
|
||||||
|
Qt.QueuedConnection, Q_ARG(str, file))
|
||||||
self.write_scan(self.start_scan(file),file)
|
self.write_scan(self.start_scan(file),file)
|
||||||
gc.collect()
|
gc.collect()
|
||||||
except:
|
except:
|
||||||
@@ -1017,62 +923,19 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
|
|
||||||
def start_scan(self, file):
|
def start_scan(self, file):
|
||||||
try:
|
try:
|
||||||
ftype = str(f".{file.split('.')[-1]}").lower()
|
if isinstance(file, dict):
|
||||||
label, level = self.pe_scan(file)
|
match_data = file
|
||||||
if label and "Unknown" == label:
|
elif os.path.exists(file):
|
||||||
if self.rule_scan(file):
|
match_data = self.model.get_type(file)
|
||||||
return "Rules"
|
for ftype, data in match_data.items():
|
||||||
elif label and "White" != label:
|
label, level = self.model.dl_scan(data)
|
||||||
if self.json["high_sensitive"]:
|
if label and label in self.model.detect:
|
||||||
return label
|
if self.json["high_sensitive"]:
|
||||||
elif level and level >= 1.0:
|
return label
|
||||||
return label
|
elif level >= self.model.values:
|
||||||
elif self.rule_scan(file):
|
return label
|
||||||
return "Rules"
|
|
||||||
elif not label and ftype in slist:
|
|
||||||
if self.rule_scan(file):
|
|
||||||
return "Rules"
|
|
||||||
if self.json["extension_kits"]:
|
if self.json["extension_kits"]:
|
||||||
if self.exten.bdc_scan(file):
|
return self.rules.yr_scan(file)[0]
|
||||||
return "Exten"
|
|
||||||
return False
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def pe_scan(self, file):
|
|
||||||
try:
|
|
||||||
fn = []
|
|
||||||
with pefile.PE(file, fast_load=True) as pe:
|
|
||||||
pe.parse_data_directories(directories=[pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_IMPORT']])
|
|
||||||
for entry in pe.DIRECTORY_ENTRY_IMPORT:
|
|
||||||
for func in entry.imports:
|
|
||||||
if func.name:
|
|
||||||
try:
|
|
||||||
fn.append(str(func.name, "utf-8"))
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
if fn:
|
|
||||||
QApplication.processEvents()
|
|
||||||
return self.model.predict(fn)
|
|
||||||
return False, False
|
|
||||||
except:
|
|
||||||
return False, False
|
|
||||||
|
|
||||||
def sign_scan(self, file):
|
|
||||||
try:
|
|
||||||
with pefile.PE(file, fast_load=True) as pe:
|
|
||||||
return pe.OPTIONAL_HEADER.DATA_DIRECTORY[pefile.DIRECTORY_ENTRY["IMAGE_DIRECTORY_ENTRY_SECURITY"]].VirtualAddress == 0
|
|
||||||
except:
|
|
||||||
return True
|
|
||||||
|
|
||||||
def rule_scan(self, file):
|
|
||||||
try:
|
|
||||||
with open(file, "rb") as f:
|
|
||||||
data = f.read()
|
|
||||||
for name, rules in self.rules.items():
|
|
||||||
QApplication.processEvents()
|
|
||||||
if rules.match(data=data):
|
|
||||||
return True
|
|
||||||
return False
|
return False
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
@@ -1216,6 +1079,7 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
self.traverse_temp(file)
|
self.traverse_temp(file)
|
||||||
else:
|
else:
|
||||||
file_size = os.path.getsize(file)
|
file_size = os.path.getsize(file)
|
||||||
|
self.ransom_counts = 0
|
||||||
os.remove(file)
|
os.remove(file)
|
||||||
self.total_deleted_size += file_size
|
self.total_deleted_size += file_size
|
||||||
except:
|
except:
|
||||||
@@ -1244,8 +1108,8 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
self.block_window = False
|
self.block_window = False
|
||||||
if self.question_event("請選擇要攔截的軟體彈窗"):
|
if self.question_event("請選擇要攔截的軟體彈窗"):
|
||||||
while not self.block_window:
|
while not self.block_window:
|
||||||
window_name = str(win32gui.GetWindowText(win32gui.GetForegroundWindow()))
|
|
||||||
QApplication.processEvents()
|
QApplication.processEvents()
|
||||||
|
window_name = str(win32gui.GetWindowText(win32gui.GetForegroundWindow()))
|
||||||
if window_name not in ["","PYAS",self.trans("警告")]:
|
if window_name not in ["","PYAS",self.trans("警告")]:
|
||||||
if window_name not in self.blocklist:
|
if window_name not in self.blocklist:
|
||||||
if self.question_event(f"您確定要攔截 {window_name} 嗎?"):
|
if self.question_event(f"您確定要攔截 {window_name} 嗎?"):
|
||||||
@@ -1446,6 +1310,7 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
for pid in new_process - self.exist_process:
|
for pid in new_process - self.exist_process:
|
||||||
try:
|
try:
|
||||||
p = psutil.Process(pid)
|
p = psutil.Process(pid)
|
||||||
|
self.lock_process(p, True)
|
||||||
self.handle_new_process(p)
|
self.handle_new_process(p)
|
||||||
self.lock_process(p, False)
|
self.lock_process(p, False)
|
||||||
gc.collect()
|
gc.collect()
|
||||||
@@ -1453,47 +1318,87 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
pass
|
pass
|
||||||
self.exist_process = new_process
|
self.exist_process = new_process
|
||||||
if self.ui.Protection_switch_Button.text() == self.trans("已開啟"):
|
if self.ui.Protection_switch_Button.text() == self.trans("已開啟"):
|
||||||
self.send_notify(self.trans(f"竄改警告: self.proc_protect"))
|
self.send_notify(self.trans(f"竄改警告: self.proc_protect"), False)
|
||||||
|
|
||||||
def handle_new_process(self, p):
|
def handle_new_process(self, p):
|
||||||
try:
|
try:
|
||||||
name, file, cmd = p.name(), p.exe().replace("\\", "/"), p.cmdline()
|
name, file, cmd = p.name(), p.exe().replace("\\", "/"), p.cmdline()
|
||||||
if file != self.pyas and self.exdir not in file and file not in self.whitelist:
|
if file != self.pyas and file not in self.whitelist:
|
||||||
self.lock_process(p, True)
|
|
||||||
if "powershell" in name:
|
if "powershell" in name:
|
||||||
target = str(cmd[-1].split("'")[-2]).replace("\\", "/")
|
file = str(cmd[-1].split("'")[-2]).replace("\\", "/")
|
||||||
if os.path.exists(target) and self.start_scan(target):
|
|
||||||
self.kill_process("腳本攔截", p, target, False)
|
|
||||||
elif os.path.exists(target) and ":/Windows" not in target:
|
|
||||||
self.track_proc = p, target, True
|
|
||||||
elif "cmd.exe" in name:
|
elif "cmd.exe" in name:
|
||||||
target = str(" ".join(cmd[2:])).replace("\\", "/")
|
file = str(" ".join(cmd[2:])).replace("\\", "/")
|
||||||
if os.path.exists(target) and self.start_scan(target):
|
|
||||||
self.kill_process("腳本攔截", p, target, False)
|
|
||||||
elif os.path.exists(target) and ":/Windows" not in target:
|
|
||||||
self.track_proc = p, target, True
|
|
||||||
elif ":/Windows" in file:
|
elif ":/Windows" in file:
|
||||||
target = str(cmd[-1]).replace("\\", "/")
|
file = str(cmd[-1]).replace("\\", "/")
|
||||||
if os.path.exists(target) and self.start_scan(target):
|
if self.start_scan(file):
|
||||||
self.kill_process("鏈式攔截", p, target, False)
|
self.kill_process("病毒攔截", p, file, False)
|
||||||
elif ":/Windows" not in file:
|
elif self.load_scan(p):
|
||||||
if os.path.exists(file) and self.start_scan(file):
|
self.kill_process("加載攔截", p, file, False)
|
||||||
self.kill_process("進程攔截", p, file, False)
|
elif self.memory_scan(p):
|
||||||
elif self.json["extension_kits"] and self.exten.pe_sieve(p):
|
self.kill_process("記憶體攔截", p, file, False)
|
||||||
self.kill_process("記憶體攔截", p, file, False)
|
elif ":/Windows" not in file and ":/Program" not in file:
|
||||||
elif ":/Program" not in file and not self.load_scan(p):
|
ftype = str(f".{file.split('.')[-1]}").lower()
|
||||||
|
if os.path.exists(file) and ftype in slist:
|
||||||
self.track_proc = p, file, True
|
self.track_proc = p, file, True
|
||||||
self.lock_process(p, False)
|
|
||||||
except:
|
except:
|
||||||
self.lock_process(p, False)
|
pass
|
||||||
|
|
||||||
def load_scan(self, p):
|
def load_scan(self, p):
|
||||||
try:
|
try:
|
||||||
for entry in p.memory_maps():
|
for entry in p.memory_maps(grouped=True):
|
||||||
target = str(entry.path).replace("\\", "/")
|
file = str(entry.path).replace("\\", "/")
|
||||||
if ":/Windows" not in target and self.start_scan(target):
|
if ":/Windows" not in file and file not in self.whitelist:
|
||||||
self.kill_process("加載攔截", p, target, False)
|
ftype = str(f".{file.split('.')[-1]}").lower()
|
||||||
return True
|
if ftype not in [".exe"] and self.start_scan(file):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_module_base(self, p):
|
||||||
|
try:
|
||||||
|
for entry in p.memory_maps(grouped=False):
|
||||||
|
file = str(entry.path).replace("\\", "/")
|
||||||
|
ftype = str(f".{file.split('.')[-1]}").lower()
|
||||||
|
if ftype in [".exe"] and file not in self.whitelist:
|
||||||
|
return int(entry.addr, 16)
|
||||||
|
return False
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def memory_scan(self, p):
|
||||||
|
try:
|
||||||
|
match_data = {}
|
||||||
|
kernel32 = ctypes.windll.kernel32
|
||||||
|
base_address = self.get_module_base(p)
|
||||||
|
process_handle = kernel32.OpenProcess(0x1F0FFF, False, p.pid)
|
||||||
|
dos_header = ctypes.create_string_buffer(64)
|
||||||
|
kernel32.ReadProcessMemory(process_handle, ctypes.c_void_p(base_address), dos_header, 64, None)
|
||||||
|
nt_headers_offset = struct.unpack("<I", dos_header[0x3C:0x3C + 4])[0]
|
||||||
|
nt_headers = ctypes.create_string_buffer(248)
|
||||||
|
kernel32.ReadProcessMemory(process_handle,
|
||||||
|
ctypes.c_void_p(base_address + nt_headers_offset), nt_headers, 248, None)
|
||||||
|
number_of_sections = struct.unpack("<H", nt_headers[6:8])[0]
|
||||||
|
optional_header_size = struct.unpack("<H", nt_headers[20:22])[0]
|
||||||
|
section_headers_offset = nt_headers_offset + 24 + optional_header_size
|
||||||
|
for i in range(number_of_sections):
|
||||||
|
section_header = ctypes.create_string_buffer(40)
|
||||||
|
section_address = base_address + section_headers_offset + i * 40
|
||||||
|
kernel32.ReadProcessMemory(process_handle,
|
||||||
|
ctypes.c_void_p(section_address), section_header, 40, None)
|
||||||
|
section_name = section_header[:8].rstrip(b'\x00').decode('latin1')
|
||||||
|
virtual_size = struct.unpack("<I", section_header[8:12])[0]
|
||||||
|
virtual_address = struct.unpack("<I", section_header[12:16])[0]
|
||||||
|
characteristics = struct.unpack("<I", section_header[36:40])[0]
|
||||||
|
text_address = base_address + virtual_address
|
||||||
|
buffer = ctypes.create_string_buffer(virtual_size)
|
||||||
|
if kernel32.ReadProcessMemory(process_handle, ctypes.c_void_p(text_address), buffer,
|
||||||
|
virtual_size, ctypes.byref(ctypes.c_size_t(0))) and characteristics & 0x00000020:
|
||||||
|
if not any(shell in section_name.lower() for shell in self.model.shells):
|
||||||
|
match_data[section_name] = buffer.raw
|
||||||
|
kernel32.CloseHandle(process_handle)
|
||||||
|
if self.start_scan(match_data):
|
||||||
|
return True
|
||||||
return False
|
return False
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
@@ -1504,9 +1409,9 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
else:
|
else:
|
||||||
p.resume()
|
p.resume()
|
||||||
|
|
||||||
def kill_process(self, info, p, target, relation=False):
|
def kill_process(self, info, p, target, relation):
|
||||||
try:
|
try:
|
||||||
target = target.replace("/", "\\")
|
target = target.replace("\\", "/")
|
||||||
if relation == False:
|
if relation == False:
|
||||||
p.kill()
|
p.kill()
|
||||||
elif relation == True:
|
elif relation == True:
|
||||||
@@ -1517,13 +1422,13 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
file = str(cmd[-1].split("'")[-2])
|
file = str(cmd[-1].split("'")[-2])
|
||||||
elif "cmd.exe" in name:
|
elif "cmd.exe" in name:
|
||||||
file = str(" ".join(cmd[2:]))
|
file = str(" ".join(cmd[2:]))
|
||||||
elif ":/Windows" in file:
|
elif ":/Windows" in file.replace("\\", "/"):
|
||||||
file = str(cmd[-1])
|
file = str(cmd[-1])
|
||||||
if target == file.replace("\\", "/"):
|
if target == file.replace("\\", "/"):
|
||||||
p.kill()
|
p.kill()
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
self.send_notify(self.trans(f"{info}: ")+target)
|
self.send_notify(self.trans(f"{info}: ")+target, True)
|
||||||
self.track_proc = None
|
self.track_proc = None
|
||||||
except:
|
except:
|
||||||
self.track_proc = None
|
self.track_proc = None
|
||||||
@@ -1549,13 +1454,15 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
self.ransom_counts += 1
|
self.ransom_counts += 1
|
||||||
elif action == 4 and ftype in alist:
|
elif action == 4 and ftype in alist:
|
||||||
self.ransom_counts += 1
|
self.ransom_counts += 1
|
||||||
if action == 3 and ftype in slist and self.start_scan(fpath):
|
if ":/Windows" not in fpath and ftype in slist:
|
||||||
os.remove(fpath)
|
if action == 3 and self.start_scan(fpath):
|
||||||
self.send_notify(self.trans("病毒刪除: ")+fpath)
|
self.ransom_counts = 0
|
||||||
|
os.remove(fpath)
|
||||||
|
self.send_notify(self.trans("病毒刪除: ")+fpath, True)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
if self.ui.Protection_switch_Button_2.text() == self.trans("已開啟"):
|
if self.ui.Protection_switch_Button_2.text() == self.trans("已開啟"):
|
||||||
self.send_notify(self.trans(f"竄改警告: self.file_protect"))
|
self.send_notify(self.trans(f"竄改警告: self.file_protect"), False)
|
||||||
|
|
||||||
def protect_boot_thread(self):
|
def protect_boot_thread(self):
|
||||||
while self.sys_protect and self.mbr_value:
|
while self.sys_protect and self.mbr_value:
|
||||||
@@ -1571,7 +1478,7 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
except:
|
except:
|
||||||
self.kill_process("引導攔截", *self.track_proc)
|
self.kill_process("引導攔截", *self.track_proc)
|
||||||
if self.ui.Protection_switch_Button_3.text() == self.trans("已開啟"):
|
if self.ui.Protection_switch_Button_3.text() == self.trans("已開啟"):
|
||||||
self.send_notify(self.trans(f"竄改警告: self.sys_protect (boot)"))
|
self.send_notify(self.trans(f"竄改警告: self.sys_protect (boot)"), False)
|
||||||
|
|
||||||
def protect_reg_thread(self):
|
def protect_reg_thread(self):
|
||||||
while self.sys_protect:
|
while self.sys_protect:
|
||||||
@@ -1584,21 +1491,19 @@ class MainWindow_Controller(QMainWindow):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
if self.ui.Protection_switch_Button_3.text() == self.trans("已開啟"):
|
if self.ui.Protection_switch_Button_3.text() == self.trans("已開啟"):
|
||||||
self.send_notify(self.trans(f"竄改警告: self.sys_protect (reg)"))
|
self.send_notify(self.trans(f"竄改警告: self.sys_protect (reg)"), False)
|
||||||
|
|
||||||
def protect_net_thread(self):
|
def protect_net_thread(self):
|
||||||
while self.net_protect:
|
while self.net_protect:
|
||||||
try:
|
try:
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
local = socket.gethostbyname(socket.gethostname())
|
for conn in self.track_proc[0].connections(kind='inet'):
|
||||||
for conn in self.track_proc.connections():
|
if conn.raddr.ip in self.rules.network:
|
||||||
if ":/Windows" not in file and ":/Program" not in file:
|
self.kill_process("網路攔截", *self.track_proc)
|
||||||
if conn.laddr.ip == local:
|
|
||||||
self.kill_process("網路攔截", *self.track_proc)
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
if self.ui.Protection_switch_Button_5.text() == self.trans("已開啟"):
|
if self.ui.Protection_switch_Button_5.text() == self.trans("已開啟"):
|
||||||
self.send_notify(self.trans(f"竄改警告: self.net_protect"))
|
self.send_notify(self.trans(f"竄改警告: self.net_protect"), False)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
|
QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
|
||||||
|
|||||||
+102
-76
@@ -1,85 +1,111 @@
|
|||||||
import time, json, hashlib, numpy
|
import os, io, sys, time, json, yara
|
||||||
|
import numpy, pefile, onnxruntime
|
||||||
|
from PIL import Image, ImageShow
|
||||||
|
|
||||||
class ListSimHash:
|
class YRScan:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.model = {}
|
self.rules = {}
|
||||||
|
self.network = []
|
||||||
|
|
||||||
def save_model(self, file_name):
|
def load_rules(self, file_path):
|
||||||
with open(file_name, 'w') as f:
|
try:
|
||||||
json.dump(self.model, f)
|
ftype = str(f".{file_path.split('.')[-1]}").lower()
|
||||||
print(f"\nModel Is Saved In {file_name}")
|
if ftype in [".yara", ".yar"]:
|
||||||
|
self.rules[file_path] = yara.compile(file_path)
|
||||||
|
elif ftype in [".yc", ".yrc"]:
|
||||||
|
self.rules[file_path] = yara.load(file_path)
|
||||||
|
elif ftype in [".ip", ".ips"]:
|
||||||
|
with open(file_path, "r") as f:
|
||||||
|
self.network += [l.strip() for l in f.readlines()]
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
def load_model(self, model_data):
|
def yr_scan(self, file_path):
|
||||||
if isinstance(model_data, str):
|
try:
|
||||||
with open(model_data, 'r') as f:
|
if isinstance(file_path, str):
|
||||||
model_data = json.load(f)
|
with open(file_path, "rb") as f:
|
||||||
self.model = model_data
|
file_path = f.read()
|
||||||
|
for name, rules in self.rules.items():
|
||||||
|
matchs_rules = rules.match(data=file_path)
|
||||||
|
if matchs_rules:
|
||||||
|
return "Virus/Rules", matchs_rules
|
||||||
|
return False, False
|
||||||
|
except:
|
||||||
|
return False, False
|
||||||
|
|
||||||
def get_model(self, label):
|
class DLScan:
|
||||||
return self.model[label]
|
def __init__(self):
|
||||||
|
self.models = {}
|
||||||
|
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']
|
||||||
|
|
||||||
def train_model(self, label, data, batch_size=10000):
|
def load_model(self, file_path):
|
||||||
start = time.time()
|
try:
|
||||||
print(f"Convert {label}")
|
ftype = str(f".{file_path.split('.')[-1]}").lower()
|
||||||
if label not in self.model:
|
if ftype in [".json", ".txt"]:
|
||||||
self.model[label] = []
|
with open(file_path, 'r') as f:
|
||||||
for i, x in enumerate(data, 1):
|
self.class_names = json.load(f)
|
||||||
build_text = self.build_text(x, batch_size)
|
elif ftype in [".onnx"]:
|
||||||
self.model[label].append(build_text)
|
self.models[file_path] = onnxruntime.InferenceSession(file_path)
|
||||||
used = "{0:.2f}".format(time.time()-start)
|
self.labels = self.class_names['Labels']
|
||||||
prefix, suffix = f'{i}/{len(data)}:', f'{used}s'
|
self.detect = self.class_names['Detect']
|
||||||
self.progress_bar(i, len(data), prefix, suffix)
|
self.pixels = self.class_names['Pixels']
|
||||||
|
self.values = self.class_names['Values']
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
|
||||||
def build_text(self, content, batch_size):
|
def dl_scan(self, file_data):
|
||||||
sums, batch, count = [], [], {}
|
try:
|
||||||
for index, char in enumerate(content):
|
target_size, sim = tuple(self.pixels), {}
|
||||||
count[char] = count.setdefault(char, 0) + 1
|
image = self.preprocess_image(file_data, target_size)
|
||||||
combined_input = f"{count[char]}_{char}"
|
image_array = numpy.array(image).astype('float32') / 255.0
|
||||||
hashes = hashlib.sha256(combined_input.encode('utf-8'))
|
image_expand = numpy.expand_dims(image_array, axis=0)
|
||||||
batch.append(hashes.digest())
|
for model_name, model in self.models.items():
|
||||||
if len(batch) >= batch_size:
|
input_name = model.get_inputs()[0].name
|
||||||
sums.append(self.sum_hashes(batch))
|
pre_answer = model.run(None, {input_name: image_expand})[0][0]
|
||||||
batch = []
|
number = numpy.argmax(pre_answer)
|
||||||
if batch:
|
label = self.labels[number].replace("\n", "")
|
||||||
sums.append(self.sum_hashes(batch))
|
sim[label] = sim.setdefault(label, 0) + pre_answer[number]
|
||||||
combined_sums = numpy.sum(sums, 0) > len(content) / 2
|
for local_label, sim_sum in sim.items():
|
||||||
v = numpy.packbits(combined_sums).tobytes()
|
if sim_sum > len(self.models) / 2:
|
||||||
return int.from_bytes(v, 'big')
|
local_level = sim_sum / len(self.models)
|
||||||
|
print(local_label, local_level * 100)
|
||||||
|
return local_label, local_level * 100
|
||||||
|
return False, False
|
||||||
|
except Exception as e:
|
||||||
|
return False, False
|
||||||
|
|
||||||
def sum_hashes(self, digests):
|
def get_type(self, file_path):
|
||||||
bitarray = numpy.unpackbits(numpy.frombuffer(b''.join(digests), dtype='>B'))
|
try:
|
||||||
return numpy.sum(numpy.reshape(bitarray, (-1, 256)), 0)
|
match_data = {}
|
||||||
|
ftype = str(f".{file_path.split('.')[-1]}").lower()
|
||||||
|
if ftype in [".exe", ".dll", ".sys", ".scr", ".com"]:
|
||||||
|
with pefile.PE(file_path, fast_load=True) as pe:
|
||||||
|
for section in pe.sections:
|
||||||
|
section_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()
|
||||||
|
elif ftype in [".bat", ".vbs", ".ps1", ".cmd", ".js"]:
|
||||||
|
with open(file_path, 'rb') as file:
|
||||||
|
match_data[ftype] = file.read()
|
||||||
|
return match_data
|
||||||
|
except:
|
||||||
|
return {}
|
||||||
|
|
||||||
def progress_bar(self, items, total, prefix='', suffix='', length=50, fill='█'):
|
def preprocess_image(self, file_data, target_size):
|
||||||
percent = min(100.0, max(0.0, 100 * (items / float(total))))
|
file_data = numpy.frombuffer(file_data, dtype=numpy.uint8)
|
||||||
end_char = '\n' if percent >= 100 else '\r'
|
data_count = len(file_data)
|
||||||
percent_string = "{0:.2f}".format(percent)
|
wah = int(numpy.ceil(numpy.sqrt((data_count + 2) // 3)))
|
||||||
filled_length = int(length * items // total)
|
image_array = numpy.zeros((wah * wah * 3,), dtype=numpy.uint8)
|
||||||
bar = fill * filled_length + ' ' * (length - filled_length)
|
image_array[:data_count] = file_data
|
||||||
print(f'\r{prefix: <15} |{bar}| {percent_string}% {suffix}', end=end_char)
|
image_array = image_array.reshape((wah, wah, 3))
|
||||||
|
image = Image.fromarray(image_array)
|
||||||
def predict_all(self, query, batch_size=10000):
|
return image.resize(target_size, Image.Resampling.LANCZOS)
|
||||||
label_similarities = {}
|
|
||||||
query_hash = self.build_text(query, batch_size)
|
|
||||||
for label in self.model:
|
|
||||||
max_similarity = 0
|
|
||||||
for data_point in self.model[label]:
|
|
||||||
similarity = self.similar(data_point, query_hash)
|
|
||||||
if similarity > max_similarity:
|
|
||||||
max_similarity = similarity
|
|
||||||
label_similarities[label] = max_similarity
|
|
||||||
return label_similarities
|
|
||||||
|
|
||||||
def predict(self, query, batch_size=10000):
|
|
||||||
max_similarity, max_label = 0, None
|
|
||||||
query_hash = self.build_text(query, batch_size)
|
|
||||||
for label in self.model:
|
|
||||||
for data_point in self.model[label]:
|
|
||||||
similarity = self.similar(data_point, query_hash)
|
|
||||||
if similarity > max_similarity:
|
|
||||||
max_similarity, max_label = similarity, label
|
|
||||||
return max_label, max_similarity
|
|
||||||
|
|
||||||
def similar(self, x, y):
|
|
||||||
hamming_distance = bin(x ^ y).count('1')
|
|
||||||
return 1 - hamming_distance / 256
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
from subprocess import Popen, PIPE
|
|
||||||
import os, re, sys
|
|
||||||
|
|
||||||
class ExtenRules:
|
|
||||||
def __init__(self):
|
|
||||||
self.pyas = sys.argv[0].replace("\\", "/")
|
|
||||||
self.dir = os.path.dirname(self.pyas)
|
|
||||||
self.exten = os.path.join(self.dir, "Exten")
|
|
||||||
|
|
||||||
def bdc_scan(self, file):
|
|
||||||
try:
|
|
||||||
check_file = file.replace("\\", "/")
|
|
||||||
if ":/Windows" not in check_file and ":/Program" not in check_file:
|
|
||||||
cmd = f'"{self.exten}\\bitdefender\\bdc.exe" "{file}"'
|
|
||||||
p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True, universal_newlines=True).wait()
|
|
||||||
for match in re.finditer(r'(?P<filename>[^\s]+)\s+infected:\s+(?P<virusname>.+)', p.communicate()[0]):
|
|
||||||
return match.groupdict()
|
|
||||||
return False
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def hollows_hunter(self, p):
|
|
||||||
try:
|
|
||||||
check_file = p.exe().replace("\\", "/")
|
|
||||||
if ":/Windows" not in check_file and ":/Program" not in check_file:
|
|
||||||
cmd = f'"{self.exten}\\hollows_hunter\\hollows_hunter.exe" /ofilter 2 /pid "{p.pid}"'
|
|
||||||
p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True, universal_newlines=True).wait()
|
|
||||||
return 'Detected' in p.communicate()[0]
|
|
||||||
return False
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def pe_sieve(self, p):
|
|
||||||
try:
|
|
||||||
check_file = p.exe().replace("\\", "/")
|
|
||||||
if ":/Windows" not in check_file and ":/Program" not in check_file:
|
|
||||||
cmd = f'"{self.exten}\\pe_sieve\\pe_sieve.exe" /ofilter 2 /pid "{p.pid}"'
|
|
||||||
p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True, universal_newlines=True).wait()
|
|
||||||
output = p.communicate()[0]
|
|
||||||
for match in re.finditer(r'(\d+)', output):
|
|
||||||
line = output[:match.start()].split('\n')[-1].strip().replace(':', '')
|
|
||||||
if line in ["Implanted shc", "Replaced", "IAT Hooks"] and int(match.group(1)) > 0:
|
|
||||||
return line
|
|
||||||
return False
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
+7
-6
@@ -16,14 +16,15 @@ translate_dict = {
|
|||||||
"綠":"绿","態":"态","務":"务","連":"连","檢":"检","測":"测","關":"关",
|
"綠":"绿","態":"态","務":"务","連":"连","檢":"检","測":"测","關":"关",
|
||||||
"強":"强","驅":"驱","為":"为","腳":"脚","單":"单","開":"开","擴":"扩",
|
"強":"强","驅":"驱","為":"为","腳":"脚","單":"单","開":"开","擴":"扩",
|
||||||
"惡":"恶","據":"据","庫":"库","經":"经","敗":"败","謝":"谢","別":"别",
|
"惡":"恶","據":"据","庫":"库","經":"经","敗":"败","謝":"谢","別":"别",
|
||||||
"載":"载","誤":"误","報":"报","鏈":"链","竄":"窜","記憶體":"内存",},
|
"載":"载","誤":"误","報":"报","鏈":"链","竄":"窜","蹤":"踪","記憶體":"内存",},
|
||||||
"en_US": {"已開啟":"On","已關閉":"Off","已开启":"On","已关闭":"Off",",":", ",
|
"en_US": {"已開啟":"On","已關閉":"Off","已开启":"On","已关闭":"Off",",":", ",
|
||||||
"立即刪除":"Delete Now","安全模式":"Safe Mode","官方網站":"Website ",
|
"立即刪除":"Delete Now","安全模式":"Safe Mode","官方網站":"Website ",
|
||||||
"腳本":"Script ","鏈式":"Chain ","記憶體":"Memory ","加載":"Load ",
|
"腳本":"Script ","鏈式":"Chain ","記憶體":"Memory ","加載":"Load ",
|
||||||
"行為":"Behavior ","可疑":"Suspicious ","勒索":"Ransom ",
|
"行為":"Behavior ","可疑":"Suspicious ","勒索":"Ransom ",
|
||||||
"許可條款":"License Terms ","惡意":"Malicious","可疑":"Suspicious",
|
"許可條款":"License Terms ","惡意":"Malicious","可疑":"Suspicious",
|
||||||
"啟用":"Enable ","禁用":"Disable ","正在初始化中":"Initializing ",
|
"啟用":"Enable ","禁用":"Disable ","正在初始化中":"Initializing ",
|
||||||
"正在掃描":"Scanning ","正在刪除":"Deleting ","最小化到":"Minimize To ",
|
"正在掃描":"Scanning ","正在刪除":"Deleting ","正在追蹤":"Tracking ",
|
||||||
|
"最小化到":"Minimize To ","靈敏度":"Sensitivity ","正在檢查":"Checking ",
|
||||||
"確定要":"Sure Want To ","引擎靈敏度":"Sensitivity ","更新":"Update ",
|
"確定要":"Sure Want To ","引擎靈敏度":"Sensitivity ","更新":"Update ",
|
||||||
"白色主題":"White","黃色主題":"Yellow","紅色主題":"Red","語言":"Language ",
|
"白色主題":"White","黃色主題":"Yellow","紅色主題":"Red","語言":"Language ",
|
||||||
"藍色主題":"Blue","綠色主題":"Green","自定主題":"Custom","最新":"Latest ",
|
"藍色主題":"Blue","綠色主題":"Green","自定主題":"Custom","最新":"Latest ",
|
||||||
@@ -45,7 +46,7 @@ translate_dict = {
|
|||||||
"風險":"Risk ","介面":"GUI ","核心":"Core ","服務":"Services ",
|
"風險":"Risk ","介面":"GUI ","核心":"Core ","服務":"Services ",
|
||||||
"管理":"Manage","所有":"All ","您":"You ","取消":"Cancel ","未":"Not ",
|
"管理":"Manage","所有":"All ","您":"You ","取消":"Cancel ","未":"Not ",
|
||||||
"垃圾":"Junk ","位元":"byte ","本機":"Computer ","停止":"Stop ",
|
"垃圾":"Junk ","位元":"byte ","本機":"Computer ","停止":"Stop ",
|
||||||
"增加到":"Add To ","白名單":"White List ","軟體":"Software ","正在":"Start ",
|
"增加到":"Add To ","白名單":"White List ","軟體":"Software ","正在":"",
|
||||||
"增加":"Add ","移除":"Delete","項目":"Items ","生成":"Create ","稱":"",
|
"增加":"Add ","移除":"Delete","項目":"Items ","生成":"Create ","稱":"",
|
||||||
"複製":"Copy ","開啟":"Open ","此":"This ","並":"And ","全盤":"Full ",
|
"複製":"Copy ","開啟":"Open ","此":"This ","並":"And ","全盤":"Full ",
|
||||||
"已經在":"Already ","數據庫":"Database ","誤報":"False Positive ",
|
"已經在":"Already ","數據庫":"Database ","誤報":"False Positive ",
|
||||||
@@ -53,7 +54,7 @@ translate_dict = {
|
|||||||
"日誌":"Log","已":"Has ","彈窗":"Window ","要":"To ","驅動":"Driver ",
|
"日誌":"Log","已":"Has ","彈窗":"Window ","要":"To ","驅動":"Driver ",
|
||||||
"的":"","顯示":"","個":"","嗎":"","中":"","了":"","行":"","立即":"",
|
"的":"","顯示":"","個":"","嗎":"","中":"","了":"","行":"","立即":"",
|
||||||
"密鑰":"Key ","檢測":"Detect ","製作":"Maker ","運行":"Running",
|
"密鑰":"Key ","檢測":"Detect ","製作":"Maker ","運行":"Running",
|
||||||
"擴展":"Extension ","套件":"Kit ","自動":"Auto ","上報":"Report ","與":"With ",
|
"擴展":"Extension ","套件":"Kit ","自動":"Auto ","上報":"Report ",
|
||||||
"分析":"Analysis ","自身":"Self ","其他":"Other ","配置":"Config ",
|
"分析":"Analysis ","自身":"Self ","其他":"Other ","配置":"Config ",
|
||||||
"丟失":"Lost ","網站":"Website ","不兼容":"Not Compatible ","追蹤":"Tracking ",
|
"丟失":"Lost ","網站":"Website ","不兼容":"Not Compatible ",
|
||||||
"竄改":"Tamper ","靈敏度":"Sensitivity ","第三方":"Other "," ":" "}}
|
"竄改":"Tamper ","第三方":"Other ","與":"With "," ":" "}}
|
||||||
+4
-3
@@ -1,7 +1,8 @@
|
|||||||
slist = [".exe",".dll",".com",".msi",".scr",
|
slist = [".exe",".dll",".sys",".com",".scr",
|
||||||
".js",".bat",".cmd",".ps1",".vbs"]
|
".bat",".ps1",".vbs",".cmd",".js"]
|
||||||
|
|
||||||
alist = [".exe",".dll",".zip",".7z",".rar",
|
alist = [".exe",".dll",".sys",".com",".scr",
|
||||||
|
".zip",".7z",".rar",".tar",".gz",
|
||||||
".js",".bat",".cmd",".ps1",".vbs",
|
".js",".bat",".cmd",".ps1",".vbs",
|
||||||
".ppt",".pptx",".wps",".txt",".rtf",
|
".ppt",".pptx",".wps",".txt",".rtf",
|
||||||
".pdf",".xls",".xlsx",".doc",".docx",
|
".pdf",".xls",".xlsx",".doc",".docx",
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@ import pyinstaller_versionfile
|
|||||||
|
|
||||||
pyinstaller_versionfile.create_versionfile(
|
pyinstaller_versionfile.create_versionfile(
|
||||||
output_file="versionfile.txt",
|
output_file="versionfile.txt",
|
||||||
version='3.1.5',
|
version='3.2.1',
|
||||||
company_name="PYAS Security",
|
company_name="PYAS Security",
|
||||||
file_description="Python Antivirus Software",
|
file_description="Python Antivirus Software",
|
||||||
internal_name="PYAS",
|
internal_name="PYAS",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# PYAS (Python Antivirus Software)
|
# PYAS (Python Antivirus Software)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Readme Language
|
## Readme Language
|
||||||
|
|
||||||
@@ -11,12 +11,16 @@
|
|||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
```
|
```
|
||||||
psutil==5.9.5
|
pip install psutil==5.9.5
|
||||||
pefile==2023.2.7
|
pip install pefile==2023.2.7
|
||||||
requests==2.31.0
|
pip install requests==2.31.0
|
||||||
pyperclip==1.8.2
|
pip install pyperclip==1.8.2
|
||||||
pywin32==306
|
pip install pywin32==306
|
||||||
PyQt5==5.15.9
|
pip install PyQt5==5.15.9
|
||||||
|
pip install yara-python==4.5.1
|
||||||
|
pip install numpy==2.1.1
|
||||||
|
pip install onnxruntime==1.18.1
|
||||||
|
pip install pillow==10.4.0
|
||||||
```
|
```
|
||||||
|
|
||||||
## File Information
|
## File Information
|
||||||
@@ -24,12 +28,7 @@ PyQt5==5.15.9
|
|||||||
```
|
```
|
||||||
PYAS/
|
PYAS/
|
||||||
├── Driver/
|
├── Driver/
|
||||||
│ ├── PYAS_Driver.sys -------> Extension Kit (self protection driver for pyas by 0sha0)
|
│ ├── PYAS_Driver.sys -------> Driver Protect (self protection driver for pyas by 0sha0)
|
||||||
│ └── ...
|
|
||||||
│
|
|
||||||
├── Exten/
|
|
||||||
│ ├── bitdefender/ ----------> Extension Kit (bitdefender windows console scan engine)
|
|
||||||
│ ├── pe_sieve/ -------------> Extension Kit (pe sieve windows console memory engine)
|
|
||||||
│ └── ...
|
│ └── ...
|
||||||
│
|
│
|
||||||
├── Model/
|
├── Model/
|
||||||
@@ -41,10 +40,9 @@ PYAS/
|
|||||||
│ ├── Yara_Rules.yrc ---------> Compile Rules (yara rules in compiled format)
|
│ ├── Yara_Rules.yrc ---------> Compile Rules (yara rules in compiled format)
|
||||||
│ └── ...
|
│ └── ...
|
||||||
│
|
│
|
||||||
├── PYAS.* ---------------------> Main PYAS Program (including animation, scan, protect functions, ...)
|
├── PYAS.py ---------------------> Main PYAS Program (including animation, scan, protect functions, ...)
|
||||||
├── PYAS_Engine.py -------------> Conversion Database (used to transform profiles and forecast data)
|
├── PYAS_Engine.py -------------> Conversion Database (used to transform profiles and forecast data)
|
||||||
├── PYAS_Suffixes.py -----------> File Suffixes (including scanned file suffixes and common suffixes)
|
├── PYAS_Suffixes.py -----------> File Suffixes (including scanned file suffixes and common suffixes)
|
||||||
├── PYAS_Extension.py ----------> Extension Kit (extension scanners developed by other developers)
|
|
||||||
├── PYAS_Interface.py ----------> PyQt5 Interface (use QT designer, must be matched with the main program)
|
├── PYAS_Interface.py ----------> PyQt5 Interface (use QT designer, must be matched with the main program)
|
||||||
├── PYAS_Resource.py -----------> PyQt5 Resource (status pictures, icon packages, button icons, ...)
|
├── PYAS_Resource.py -----------> PyQt5 Resource (status pictures, icon packages, button icons, ...)
|
||||||
├── PYAS_Language.py -----------> Translate Dict (Traditional Chinese, Simplified Chinese, English)
|
├── PYAS_Language.py -----------> Translate Dict (Traditional Chinese, Simplified Chinese, English)
|
||||||
@@ -58,6 +56,10 @@ https://pyantivirus.wixsite.com/pyas
|
|||||||
|
|
||||||
https://github.com/87owo/PYAS
|
https://github.com/87owo/PYAS
|
||||||
|
|
||||||
|
## Microsoft Runtime
|
||||||
|
|
||||||
|
https://github.com/87owo/Microsoft_Runtime/releases
|
||||||
|
|
||||||
## PYAS Driver
|
## PYAS Driver
|
||||||
|
|
||||||
https://github.com/0sha0/PYAS_Protection
|
https://github.com/0sha0/PYAS_Protection
|
||||||
|
|||||||
+19
-17
@@ -1,16 +1,20 @@
|
|||||||
# PYAS (Python 杀毒软件)
|
# PYAS (Python 杀毒软件)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## 安装要求
|
## 安装要求
|
||||||
|
|
||||||
```
|
```
|
||||||
psutil==5.9.5
|
pip install psutil==5.9.5
|
||||||
pefile==2023.2.7
|
pip install pefile==2023.2.7
|
||||||
requests==2.31.0
|
pip install requests==2.31.0
|
||||||
pyperclip==1.8.2
|
pip install pyperclip==1.8.2
|
||||||
pywin32==306
|
pip install pywin32==306
|
||||||
PyQt5==5.15.9
|
pip install PyQt5==5.15.9
|
||||||
|
pip install yara-python==4.5.1
|
||||||
|
pip install numpy==2.1.1
|
||||||
|
pip install onnxruntime==1.18.1
|
||||||
|
pip install pillow==10.4.0
|
||||||
```
|
```
|
||||||
|
|
||||||
## 文件信息
|
## 文件信息
|
||||||
@@ -21,11 +25,6 @@ PYAS/
|
|||||||
│ ├── PYAS_Driver.sys -------> 驱动程序 (0sha0 为 pyas 提供的自我保护驱动程序)
|
│ ├── PYAS_Driver.sys -------> 驱动程序 (0sha0 为 pyas 提供的自我保护驱动程序)
|
||||||
│ └── ...
|
│ └── ...
|
||||||
│
|
│
|
||||||
├── Exten/
|
|
||||||
│ ├── bitdefender/ ----------> 扩展套件 (bitdefender windows 控制台扫描引擎)
|
|
||||||
│ ├── pe_sieve/ -------------> 扩展套件 (pe sieve windows 控制台内存引擎)
|
|
||||||
│ └── ...
|
|
||||||
│
|
|
||||||
├── Model/
|
├── Model/
|
||||||
│ ├── PYAS_Model.json -------> 病毒数据库 (数据库必须位于指定目录中)
|
│ ├── PYAS_Model.json -------> 病毒数据库 (数据库必须位于指定目录中)
|
||||||
│ └── ...
|
│ └── ...
|
||||||
@@ -35,14 +34,13 @@ PYAS/
|
|||||||
│ ├── Yara_Rules.yrc ---------> 编译规则 (编译格式的 yara 规则)
|
│ ├── Yara_Rules.yrc ---------> 编译规则 (编译格式的 yara 规则)
|
||||||
│ └── ...
|
│ └── ...
|
||||||
│
|
│
|
||||||
├── PYAS.* ---------------------> PYAS主程序(包含动画、扫描、保护等功能...)
|
├── PYAS.py ---------------------> PYAS主程序(包含动画、扫描、保护等功能...)
|
||||||
├── PYAS_Engine.py -------------> 转换数据库(用于转换剖面图和预报数据)
|
├── PYAS_Engine.py -------------> 转换数据库(用于转换剖面图和预报数据)
|
||||||
├── PYAS_Suffixes.py -----------> 文件后缀(包含扫描文件后缀和常用后缀)
|
├── PYAS_Suffixes.py -----------> 文件后缀(包含扫描文件后缀和常用后缀)
|
||||||
├── PYAS_Extension.py ----------> 扩展工具包(其他开发者开发的扩展扫描器)
|
|
||||||
├── PYAS_Interface.py ----------> PyQt5界面(使用QT设计器,需与主程序搭配使用)
|
├── PYAS_Interface.py ----------> PyQt5界面(使用QT设计器,需与主程序搭配使用)
|
||||||
├── PYAS_Resource.py -----------> PyQt5资源(状态图片、图标包、按钮图标...)
|
├── PYAS_Resource.py -----------> PyQt5资源(状态图片、图标包、按钮图标...)
|
||||||
├── PYAS_Language.py -----------> 翻译词典(繁体中文、简体中文、英文)
|
├── PYAS_Language.py -----------> 翻译词典(繁体中文、简体中文、英文)
|
||||||
├── PYAS_Version.py ------------> 安裝信息(文件信息、版本信息、原名,...)
|
├── PYAS_Version.py ------------> 安裝信息(文件信息、版本信息、原名...)
|
||||||
└── ...
|
└── ...
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -52,14 +50,18 @@ https://pyantivirus.wixsite.com/pyas
|
|||||||
|
|
||||||
https://github.com/87owo/PYAS
|
https://github.com/87owo/PYAS
|
||||||
|
|
||||||
## 开源协议
|
## 微软运行库
|
||||||
|
|
||||||
https://github.com/87owo/PYAS/blob/main/LICENSE.md
|
https://github.com/87owo/Microsoft_Runtime/releases
|
||||||
|
|
||||||
## 驱动程序
|
## 驱动程序
|
||||||
|
|
||||||
https://github.com/0sha0/PYAS_Protection
|
https://github.com/0sha0/PYAS_Protection
|
||||||
|
|
||||||
|
## 开源协议
|
||||||
|
|
||||||
|
https://github.com/87owo/PYAS/blob/main/LICENSE.md
|
||||||
|
|
||||||
## 支援系统
|
## 支援系统
|
||||||
|
|
||||||
Windows 8.1, 10, 11 (64-bit), 内存 500MB, 存储 200MB 或更高
|
Windows 8.1, 10, 11 (64-bit), 内存 500MB, 存储 200MB 或更高
|
||||||
|
|||||||
+19
-17
@@ -1,16 +1,20 @@
|
|||||||
# PYAS (Python 防毒軟體)
|
# PYAS (Python 防毒軟體)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## 安裝要求
|
## 安裝要求
|
||||||
|
|
||||||
```
|
```
|
||||||
psutil==5.9.5
|
pip install psutil==5.9.5
|
||||||
pefile==2023.2.7
|
pip install pefile==2023.2.7
|
||||||
requests==2.31.0
|
pip install requests==2.31.0
|
||||||
pyperclip==1.8.2
|
pip install pyperclip==1.8.2
|
||||||
pywin32==306
|
pip install pywin32==306
|
||||||
PyQt5==5.15.9
|
pip install PyQt5==5.15.9
|
||||||
|
pip install yara-python==4.5.1
|
||||||
|
pip install numpy==2.1.1
|
||||||
|
pip install onnxruntime==1.18.1
|
||||||
|
pip install pillow==10.4.0
|
||||||
```
|
```
|
||||||
|
|
||||||
## 檔案資訊
|
## 檔案資訊
|
||||||
@@ -21,11 +25,6 @@ PYAS/
|
|||||||
│ ├── PYAS_Driver.sys -------> 驅動程式 (0sha0 為 pyas 提供的自我保護驅動程式)
|
│ ├── PYAS_Driver.sys -------> 驅動程式 (0sha0 為 pyas 提供的自我保護驅動程式)
|
||||||
│ └── ...
|
│ └── ...
|
||||||
│
|
│
|
||||||
├── Exten/
|
|
||||||
│ ├── bitdefender/ ----------> 擴充套件 (bitdefender windows 控制台掃描引擎)
|
|
||||||
│ ├── pe_sieve/ -------------> 擴充套件 (pe sieve windows 控制台記憶體引擎)
|
|
||||||
│ └── ...
|
|
||||||
│
|
|
||||||
├── Model/
|
├── Model/
|
||||||
│ ├── PYAS_Model.json -------> 病毒資料庫 (資料庫必須位於指定目錄)
|
│ ├── PYAS_Model.json -------> 病毒資料庫 (資料庫必須位於指定目錄)
|
||||||
│ └── ...
|
│ └── ...
|
||||||
@@ -35,14 +34,13 @@ PYAS/
|
|||||||
│ ├── Yara_Rules.yrc ---------> 編譯規則 (編譯格式的 yara 規則)
|
│ ├── Yara_Rules.yrc ---------> 編譯規則 (編譯格式的 yara 規則)
|
||||||
│ └── ...
|
│ └── ...
|
||||||
│
|
│
|
||||||
├── PYAS.* ---------------------> PYAS主程式(包含動畫、掃描、保護等功能...)
|
├── PYAS.py ---------------------> PYAS主程式(包含動畫、掃描、保護等功能...)
|
||||||
├── PYAS_Engine.py -------------> 轉換資料庫(用於轉換剖面圖和預報資料)
|
├── PYAS_Engine.py -------------> 轉換資料庫(用於轉換剖面圖和預報資料)
|
||||||
├── PYAS_Suffixes.py -----------> 文件後綴(包含掃描文件後綴和常用後綴)
|
├── PYAS_Suffixes.py -----------> 文件後綴(包含掃描文件後綴和常用後綴)
|
||||||
├── PYAS_Extension.py ----------> 擴充工具包(其他開發者開發的擴充掃描器)
|
|
||||||
├── PYAS_Interface.py ----------> PyQt5介面(使用QT設計器,需與主程式搭配使用)
|
├── PYAS_Interface.py ----------> PyQt5介面(使用QT設計器,需與主程式搭配使用)
|
||||||
├── PYAS_Resource.py -----------> PyQt5資源(狀態圖片、圖示包、按鈕圖示...)
|
├── PYAS_Resource.py -----------> PyQt5資源(狀態圖片、圖示包、按鈕圖示...)
|
||||||
├── PYAS_Language.py -----------> 翻譯字典(繁體中文、簡體中文、英文)
|
├── PYAS_Language.py -----------> 翻譯字典(繁體中文、簡體中文、英文)
|
||||||
├── PYAS_Version.py ------------> 安裝資訊(檔案資訊、版本資訊、原名,...)
|
├── PYAS_Version.py ------------> 安裝資訊(檔案資訊、版本資訊、原名...)
|
||||||
└── ...
|
└── ...
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -52,14 +50,18 @@ https://pyantivirus.wixsite.com/pyas
|
|||||||
|
|
||||||
https://github.com/87owo/PYAS
|
https://github.com/87owo/PYAS
|
||||||
|
|
||||||
## 開源協議
|
## 微軟運行庫
|
||||||
|
|
||||||
https://github.com/87owo/PYAS/blob/main/LICENSE.md
|
https://github.com/87owo/Microsoft_Runtime/releases
|
||||||
|
|
||||||
## 驅動程式
|
## 驅動程式
|
||||||
|
|
||||||
https://github.com/0sha0/PYAS_Protection
|
https://github.com/0sha0/PYAS_Protection
|
||||||
|
|
||||||
|
## 開源協議
|
||||||
|
|
||||||
|
https://github.com/87owo/PYAS/blob/main/LICENSE.md
|
||||||
|
|
||||||
## 支援系統
|
## 支援系統
|
||||||
|
|
||||||
Windows 8.1, 10, 11 (64-bit),記憶體 500MB, 磁碟容量 200MB 或更高
|
Windows 8.1, 10, 11 (64-bit),記憶體 500MB, 磁碟容量 200MB 或更高
|
||||||
|
|||||||
+256387
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user