Compare commits

...
45 Commits
Author SHA1 Message Date
PYDT 316882bcd0 Add files via upload 2024-10-03 02:27:09 +08:00
PYDT b204e52297 Update README_zh_CN.md 2024-10-02 21:58:55 +08:00
PYDT f82a63f4c8 Update README_zh_TW.md 2024-10-02 21:58:40 +08:00
PYDT cb0f2108a4 Update README.md 2024-10-02 21:58:12 +08:00
PYDT 300b7a7a68 Add files via upload 2024-10-02 12:30:44 +08:00
PYDT c3852ca60d Add files via upload 2024-10-02 12:00:37 +08:00
PYDT a5fb735c93 Add files via upload 2024-09-28 11:15:53 +08:00
PYDT d0b04ba84f Add files via upload 2024-09-28 11:14:54 +08:00
PYDT 9552742a39 Add files via upload 2024-09-21 22:51:13 +08:00
PYDT 8e9bdf6c0c Add files via upload 2024-09-21 22:50:02 +08:00
PYDT 818cc48502 Add files via upload 2024-09-20 00:36:42 +08:00
PYDT adc4e28eb8 Add files via upload 2024-09-20 00:31:25 +08:00
PYDT 2e3a4d3bf1 Add files via upload 2024-09-14 15:41:49 +08:00
PYDT d9bcac78e7 Add files via upload 2024-09-14 15:12:14 +08:00
PYDT 2342947849 Add files via upload 2024-09-14 15:11:36 +08:00
PYDT 19204dee8d Add files via upload 2024-09-12 16:17:50 +08:00
PYDT 863fa90b80 Add files via upload 2024-09-12 16:08:26 +08:00
PYDT 6fdef4a8f1 Add files via upload 2024-09-12 16:08:10 +08:00
PYDT 9469ceaa02 Add files via upload 2024-09-12 15:25:07 +08:00
PYDT 857f184409 Add files via upload 2024-09-11 01:05:58 +08:00
PYDT a2f4a725f5 Add files via upload 2024-09-10 14:34:02 +08:00
PYDT d12449bbb9 Add files via upload 2024-09-10 13:35:57 +08:00
PYDT a41f4711dd Add files via upload 2024-09-10 13:34:16 +08:00
PYDT 3c2b018d49 Add files via upload 2024-09-07 10:49:46 +08:00
PYDT e221a09709 Add files via upload 2024-09-07 10:48:43 +08:00
PYDT 26ff4bd843 Update README_zh_TW.md 2024-08-26 07:42:37 +08:00
PYDT d8e28f384a Update README_zh_CN.md 2024-08-26 07:42:17 +08:00
PYDT 65e68c3cc4 Update README.md 2024-08-26 07:41:44 +08:00
PYDT 7b76ab2a59 Update README.md 2024-08-26 07:41:18 +08:00
PYDT ae2a01b463 Update README_zh_TW.md 2024-08-26 07:29:15 +08:00
PYDT cda022a9f4 Update README_zh_CN.md 2024-08-26 07:28:10 +08:00
PYDT 672e48c5f8 Update README.md 2024-08-26 07:26:34 +08:00
PYDT 6fbdb1354f Update README.md 2024-08-26 07:22:09 +08:00
PYDT 79bc7fd443 Update README_zh_TW.md 2024-08-20 10:57:17 +08:00
PYDT 5578dd3339 Update README_zh_CN.md 2024-08-20 10:57:03 +08:00
PYDT 0232dbd196 Update README.md 2024-08-20 10:56:46 +08:00
PYDT d44e192eaa Update README_zh_CN.md 2024-08-20 10:53:34 +08:00
PYDT 4f12b19cf8 Update README_zh_TW.md 2024-08-20 10:52:57 +08:00
PYDT 392ac1b1c7 Update README_zh_TW.md 2024-08-20 10:52:37 +08:00
PYDT 8ad175aca3 Update README.md 2024-08-20 10:51:48 +08:00
PYDT 6afa58c42b Delete PYAS_Extension.py 2024-08-18 12:48:43 +08:00
PYDT 8be03cf232 Add files via upload 2024-08-18 12:48:16 +08:00
PYDT 23ea53d3ff Add files via upload 2024-08-18 12:46:52 +08:00
PYDT 294f40e7ac Add files via upload 2024-08-18 12:46:11 +08:00
PYDT 4f5f706ee5 Delete Exten directory 2024-08-18 12:45:44 +08:00
13 changed files with 256706 additions and 429 deletions

No files matched your search

-11
View File
@@ -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
+9 -1
View File
@@ -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.
+141 -236
View File
@@ -1,12 +1,10 @@
import os, gc, sys, time, json, yara
import pefile, socket, msvcrt, psutil
import requests, pyperclip, win32file
import win32gui, win32api, win32con
from PYAS_Engine import ListSimHash
import os, gc, sys, time, json, psutil
import ctypes, struct, msvcrt, pyperclip
import win32gui, win32api, win32con, win32file
from PYAS_Engine import YRScan, DLScan
from PYAS_Suffixes import slist, alist
from PYAS_Language import translate_dict
from PYAS_Interface import Ui_MainWindow
from PYAS_Extension import ExtenRules
from threading import Thread
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
@@ -15,25 +13,14 @@ from subprocess import *
class MainWindow_Controller(QMainWindow):
def __init__(self):
# init program window
super(MainWindow_Controller, self).__init__()
self.setAttribute(Qt.WA_TranslucentBackground)
self.setWindowFlags(Qt.FramelessWindowHint)
# get self program path
self.pyas = sys.argv[0].replace("\\", "/")
self.dir = os.path.dirname(self.pyas)
exdir = os.path.join(self.dir, "Exten")
self.exdir = exdir.replace("\\", "/")
# init self program version
self.pyae_version = "Fusion Engine"
self.pyas_version = "3.1.5"
# startup ui config
self.pyae_version = "AI Engine"
self.pyas_version = "3.2.1"
self.first_startup = True
# init program config
self.init_data_base()
self.init_tray_icon()
self.init_config_qtui()
@@ -44,18 +31,14 @@ class MainWindow_Controller(QMainWindow):
self.init_startup()
def init_threads(self):
# init protect thread
self.protect_proc_init()
self.protect_file_init()
self.protect_sys_init()
self.protect_drv_init()
self.protect_net_init()
# init tools thread
self.block_window_init()
def init_tray_icon(self):
# init taskbar tray and icon
self.tray_icon = QSystemTrayIcon(self)
self.tray_icon.activated.connect(self.init_show_pyas)
self.tray_icon.setIcon(QFileIconProvider().icon(QFileInfo(self.pyas)))
@@ -63,70 +46,45 @@ class MainWindow_Controller(QMainWindow):
def init_startup(self):
try:
# check startup ui args
if len(sys.argv) > 1:
param = sys.argv[1]
if "h" not in param:
self.init_show_pyas()
elif len(sys.argv) <= 1:
self.init_show_pyas()
# startup ui complete
self.first_startup = False
except:
pass
def init_data_base(self):
try:
# init exten path ./Exten/* (from import)
self.exten = ExtenRules()
# init model path ./Model/* (from import)
self.model = ListSimHash()
data_path = os.path.join(self.dir, "Model")
self.model = DLScan()
data_path = os.path.join(self.dir, "Model")
for root, dirs, files in os.walk(data_path):
for file in files:
file_path = os.path.join(root, file)
ftype = str(f".{file.split('.')[-1]}").lower()
if ftype in [".json",".txt"]:
# SimHash model json file
self.model.load_model(file_path)
# init yara path ./Rules/* (from import)
self.rules = {}
self.model.load_model(file_path)
self.rules = YRScan()
data_path = os.path.join(self.dir, "Rules")
for root, dirs, files in os.walk(data_path):
for file in files:
file_path = os.path.join(root, file)
ftype = str(f".{file.split('.')[-1]}").lower()
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
self.rules.load_rules(file_path)
except Exception as e:
self.bug_event(e)
def init_config_boot(self):
try:
# init read system boot
with open(r"\\.\PhysicalDrive0", "r+b") as f:
# backup system mbr value
self.mbr_value = f.read(512)
# check if mbr is available
if self.mbr_value[510:512] != b'\x55\xAA':
self.mbr_value = False
except Exception as e:
# possible permission denied
self.mbr_value = False
self.bug_event(self.trans(f"引導防護錯誤: ")+str(e))
def write_config(self, config):
try:
# write json configs in ProgramData
with open("C:/ProgramData/PYAS/PYAS.json", "w") as f:
f.write(json.dumps(config, indent=4, ensure_ascii=False))
except Exception as e:
@@ -134,57 +92,42 @@ class MainWindow_Controller(QMainWindow):
def init_config_read(self):
try:
# init check exist process
self.track_proc = None
self.exist_process = set()
for p in psutil.process_iter():
self.exist_process.add(p.pid)
# check config path exists
if not os.path.exists("C:/ProgramData/PYAS"):
os.makedirs("C:/ProgramData/PYAS")
# check config file exists
if not os.path.exists("C:/ProgramData/PYAS/PYAS.json"):
self.write_config({"language":"en_US","theme_color":"White",
"high_sensitive":0,"extension_kits":0,"cloud_services":"None"})
try:
# read config json data
with open("C:/ProgramData/PYAS/PYAS.json", "r") as f:
self.json = json.load(f)
except:
self.json = {"language":"en_US","theme_color":"White",
"high_sensitive":0,"extension_kits":0,"cloud_services":"None"}
# default json config
self.json["language"] = self.json.get("language", "en_US")
self.json["theme_color"] = self.json.get("theme_color", "White")
self.json["high_sensitive"] = self.json.get("high_sensitive", 0)
self.json["extension_kits"] = self.json.get("extension_kits", 0)
self.json["cloud_services"] = self.json.get("cloud_services", "None")
# reflash high_sensitive ui text
if self.json["high_sensitive"] == 1:
self.ui.high_sensitivity_switch_Button.setText(self.trans("已開啟"))
self.ui.high_sensitivity_switch_Button.setStyleSheet("""
QPushButton{border:none;background-color:rgb(200, 250, 200);border-radius: 10px;}
QPushButton:hover{background-color:rgb(210, 250, 210);}""")
if self.json["extension_kits"] == 1:
self.ui.extension_kit_switch_Button.setText(self.trans("已開啟"))
self.ui.extension_kit_switch_Button.setStyleSheet("""
QPushButton{border:none;background-color:rgb(200, 250, 200);border-radius: 10px;}
QPushButton:hover{background-color:rgb(210, 250, 210);}""")
# reflash language ui setChecked
if self.json["language"] == "zh_TW":
self.ui.Language_Traditional_Chinese.setChecked(True)
elif self.json["language"] == "zh_CN":
self.ui.Language_Simplified_Chinese.setChecked(True)
elif self.json["language"] == "en_US":
self.ui.Language_English.setChecked(True)
# reflash theme_color ui setChecked
if self.json["theme_color"] == "White":
self.ui.Theme_White.setChecked(True)
elif self.json["theme_color"] == "Red":
@@ -197,14 +140,10 @@ class MainWindow_Controller(QMainWindow):
self.ui.Theme_Blue.setChecked(True)
elif os.path.exists(self.json["theme_color"]):
self.ui.Theme_Customize.setChecked(True)
# read whitelist lines from ProgramData
self.whitelist = []
if os.path.exists("C:/ProgramData/PYAS/Whitelist.ini"):
with open("C:/ProgramData/PYAS/Whitelist.ini", "r") as f:
self.whitelist = [l.strip() for l in f.readlines()]
# read blocklist lines from ProgramData
self.blocklist = []
if os.path.exists("C:/ProgramData/PYAS/Blocklist.ini"):
with open("C:/ProgramData/PYAS/Blocklist.ini", "r") as f:
@@ -213,7 +152,6 @@ class MainWindow_Controller(QMainWindow):
self.bug_event(e)
def init_control(self):
# connect main ui and function control
self.ui.Close_Button.clicked.connect(self.close)
self.ui.Minimize_Button.clicked.connect(self.showMinimized)
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.Virus_Scan_Button.clicked.connect(self.change_scan_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.customContextMenuRequested.connect(self.Virus_Scan_output_menu)
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.Path_Scan_Button.clicked.connect(self.path_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.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)
@@ -243,15 +177,11 @@ class MainWindow_Controller(QMainWindow):
self.ui.Process_list.customContextMenuRequested.connect(self.process_list_menu)
self.ui.About_Back.clicked.connect(self.ui.About_widget.hide)
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_2.clicked.connect(self.protect_file_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_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.extension_kit_switch_Button.clicked.connect(self.extension_kit)
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)
def init_config_qtui(self):
# connect ui and variable control
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
# init virus scan list
self.virus_lock = {}
self.virus_list = []
self.virus_list_ui = []
# init process tools list
self.Process_quantity = []
self.Process_list_all_pid = []
# connect effect ui and variable
self.Process_sim = QStringListModel()
self.Process_Timer = QTimer()
self.Process_Timer.timeout.connect(self.process_list)
@@ -313,34 +236,27 @@ class MainWindow_Controller(QMainWindow):
self.ui.About_widget.hide()
self.ui.State_output.style().polish(self.ui.State_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.''')
def init_change_lang(self):
try:
# change lang function with init or clicked
if self.ui.Language_Traditional_Chinese.isChecked():
self.json["language"] = "zh_TW"
elif self.ui.Language_Simplified_Chinese.isChecked():
self.json["language"] = "zh_CN"
elif self.ui.Language_English.isChecked():
self.json["language"] = "en_US"
# write lang config and set lang text
self.write_config(self.json)
self.init_lang_text()
except Exception as e:
self.bug_event(e)
def trans(self, text):
# from PYAS_Language import translate_dict
for k, v in translate_dict.get(self.json["language"], translate_dict).items():
text = text.replace(str(k), str(v))
return text
def init_lang_text(self):
# original init language "zh_TW"
self.ui.State_title.setText(self.trans("此裝置已受到防護"))
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"))
@@ -381,7 +297,7 @@ class MainWindow_Controller(QMainWindow):
self.ui.Window_Block_Button.setText(self.trans("軟體彈窗攔截"))
self.ui.Repair_System_Network_Button.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_Name.setText(self.trans("mtkiao"))
self.ui.Core_Made_title.setText(self.trans("核心製作:"))
@@ -415,7 +331,6 @@ class MainWindow_Controller(QMainWindow):
def init_theme_color(self):
try:
# set theme color (Maybe it can be further optimized?)
if self.ui.Theme_White.isChecked():
self.json["theme_color"] = "White"
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.Navigation_Bar.setStyleSheet("QWidget#Navigation_Bar {background-color:rgb(250,250,220);}")
elif self.ui.Theme_Customize.isChecked():
# check customize theme config
if not os.path.exists(os.path.join(self.json["theme_color"],"Color.ini")):
path = str(QFileDialog.getExistingDirectory(self,self.trans("自定主題"),"C:/"))
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])
file = os.path.join(self.json["theme_color"],"Check.png")
self.ui.State_icon.setPixmap(QPixmap(file))
# write theme color config
self.write_config(self.json)
except:
# set default theme color when error
self.ui.Theme_White.setChecked(True)
self.json["theme_color"] = "White"
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);}")
def change_animation(self,widget):
# animation for widget
x, y = 170, widget.pos().y()
self.anim = QPropertyAnimation(widget, b"geometry")
widget.setGeometry(QRect(x - 100,y, 671, 481))
@@ -475,7 +386,6 @@ class MainWindow_Controller(QMainWindow):
self.anim.start()
def change_animation_2(self,nx,ny):
# animation for scroll bar
x, y = self.ui.label.pos().x(), self.ui.label.pos().y()
self.anim2 = QPropertyAnimation(self.ui.label, b"geometry")
if y > ny:
@@ -495,7 +405,6 @@ class MainWindow_Controller(QMainWindow):
self.anim2.start()
def change_animation_3(self,widget,time):
# animation for OpacityEffect
self.opacity = QGraphicsOpacityEffect()
self.opacity.setOpacity(0)
self.opacity.i = self.opacity.opacity()
@@ -737,18 +646,20 @@ class MainWindow_Controller(QMainWindow):
# question event message
print(f"[Quest] > {text}")
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:
return False
def send_notify(self, text):
def send_notify(self, text, notify_bar=True):
try:
# send system notification
now_time = time.strftime('%Y-%m-%d %H:%M:%S')
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)
QMetaObject.invokeMethod(self.ui.State_output, "append", Qt.QueuedConnection, Q_ARG(str, f"[{now_time}] {text}"))
except:
pass
@@ -824,23 +735,6 @@ class MainWindow_Controller(QMainWindow):
QPushButton:hover{background-color:rgb(210,250,210);}""")
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):
try:
self.ui.Virus_Scan_text.setText(self.trans("正在初始化中"))
@@ -896,18 +790,23 @@ class MainWindow_Controller(QMainWindow):
try:
# delete file
if self.ui.Virus_Scan_output.findItems(file, Qt.MatchContains)[0].checkState() == Qt.Checked:
self.ui.Virus_Scan_title.setText(self.trans("正在刪除"))
self.ui.Virus_Scan_text.setText(file)
QMetaObject.invokeMethod(self.ui.Virus_Scan_title, "setText",
Qt.QueuedConnection, Q_ARG(str, self.trans("正在刪除")))
QMetaObject.invokeMethod(self.ui.Virus_Scan_text, "setText",
Qt.QueuedConnection, Q_ARG(str, file))
QApplication.processEvents()
self.lock_file(file, False)
self.ransom_counts = 0
os.remove(file)
else:
self.lock_file(file, False)
except:
continue
self.ui.Virus_Scan_output.clear()
self.ui.Virus_Scan_title.setText(self.trans("病毒掃描"))
self.ui.Virus_Scan_text.setText(self.trans("刪除成功"))
QMetaObject.invokeMethod(self.ui.Virus_Scan_title, "setText",
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:
self.bug_event(e)
@@ -927,7 +826,8 @@ class MainWindow_Controller(QMainWindow):
def answer_scan(self):
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:
self.ui.Virus_Scan_Solve_Button.show()
self.ui.Virus_Scan_Break_Button.hide()
@@ -937,7 +837,8 @@ class MainWindow_Controller(QMainWindow):
self.virus_scan_break()
text = self.trans("當前未發現病毒")
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)
gc.collect()
except Exception as e:
@@ -947,8 +848,10 @@ class MainWindow_Controller(QMainWindow):
self.scan_file = False
self.ui.Virus_Scan_Break_Button.hide()
self.ui.Virus_Scan_choose_Button.show()
self.ui.Virus_Scan_text.setText(self.trans("請選擇掃描方式"))
self.ui.Virus_Scan_title.setText(self.trans("病毒掃描"))
QMetaObject.invokeMethod(self.ui.Virus_Scan_title, "setText",
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):
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])
if file and file not in self.whitelist and file != self.pyas:
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()
while self.scan_thread.is_alive():
QApplication.processEvents()
@@ -1008,8 +912,10 @@ class MainWindow_Controller(QMainWindow):
elif os.path.isdir(file):
self.traverse_path(file)
elif file != self.pyas and file not in self.whitelist:
self.ui.Virus_Scan_title.setText(self.trans("正在掃描"))
self.ui.Virus_Scan_text.setText(file)
QMetaObject.invokeMethod(self.ui.Virus_Scan_title, "setText",
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)
gc.collect()
except:
@@ -1017,62 +923,19 @@ class MainWindow_Controller(QMainWindow):
def start_scan(self, file):
try:
ftype = str(f".{file.split('.')[-1]}").lower()
label, level = self.pe_scan(file)
if label and "Unknown" == label:
if self.rule_scan(file):
return "Rules"
elif label and "White" != label:
if self.json["high_sensitive"]:
return label
elif level and level >= 1.0:
return label
elif self.rule_scan(file):
return "Rules"
elif not label and ftype in slist:
if self.rule_scan(file):
return "Rules"
if isinstance(file, dict):
match_data = file
elif os.path.exists(file):
match_data = self.model.get_type(file)
for ftype, data in match_data.items():
label, level = self.model.dl_scan(data)
if label and label in self.model.detect:
if self.json["high_sensitive"]:
return label
elif level >= self.model.values:
return label
if self.json["extension_kits"]:
if self.exten.bdc_scan(file):
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 self.rules.yr_scan(file)[0]
return False
except:
return False
@@ -1216,6 +1079,7 @@ class MainWindow_Controller(QMainWindow):
self.traverse_temp(file)
else:
file_size = os.path.getsize(file)
self.ransom_counts = 0
os.remove(file)
self.total_deleted_size += file_size
except:
@@ -1244,8 +1108,8 @@ class MainWindow_Controller(QMainWindow):
self.block_window = False
if self.question_event("請選擇要攔截的軟體彈窗"):
while not self.block_window:
window_name = str(win32gui.GetWindowText(win32gui.GetForegroundWindow()))
QApplication.processEvents()
window_name = str(win32gui.GetWindowText(win32gui.GetForegroundWindow()))
if window_name not in ["","PYAS",self.trans("警告")]:
if window_name not in self.blocklist:
if self.question_event(f"您確定要攔截 {window_name} 嗎?"):
@@ -1446,6 +1310,7 @@ class MainWindow_Controller(QMainWindow):
for pid in new_process - self.exist_process:
try:
p = psutil.Process(pid)
self.lock_process(p, True)
self.handle_new_process(p)
self.lock_process(p, False)
gc.collect()
@@ -1453,47 +1318,87 @@ class MainWindow_Controller(QMainWindow):
pass
self.exist_process = new_process
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):
try:
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:
self.lock_process(p, True)
if file != self.pyas and file not in self.whitelist:
if "powershell" in name:
target = 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
file = str(cmd[-1].split("'")[-2]).replace("\\", "/")
elif "cmd.exe" in name:
target = 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
file = str(" ".join(cmd[2:])).replace("\\", "/")
elif ":/Windows" in file:
target = str(cmd[-1]).replace("\\", "/")
if os.path.exists(target) and self.start_scan(target):
self.kill_process("鏈式攔截", p, target, False)
elif ":/Windows" not in file:
if os.path.exists(file) and self.start_scan(file):
self.kill_process("進程攔截", p, file, False)
elif self.json["extension_kits"] and self.exten.pe_sieve(p):
self.kill_process("記憶體攔截", p, file, False)
elif ":/Program" not in file and not self.load_scan(p):
file = str(cmd[-1]).replace("\\", "/")
if self.start_scan(file):
self.kill_process("病毒攔截", p, file, False)
elif self.load_scan(p):
self.kill_process("加載攔截", p, file, False)
elif self.memory_scan(p):
self.kill_process("記憶體攔截", p, file, False)
elif ":/Windows" not in file and ":/Program" not in file:
ftype = str(f".{file.split('.')[-1]}").lower()
if os.path.exists(file) and ftype in slist:
self.track_proc = p, file, True
self.lock_process(p, False)
except:
self.lock_process(p, False)
pass
def load_scan(self, p):
try:
for entry in p.memory_maps():
target = str(entry.path).replace("\\", "/")
if ":/Windows" not in target and self.start_scan(target):
self.kill_process("加載攔截", p, target, False)
return True
for entry in p.memory_maps(grouped=True):
file = str(entry.path).replace("\\", "/")
if ":/Windows" not in file and file not in self.whitelist:
ftype = str(f".{file.split('.')[-1]}").lower()
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
except:
return False
@@ -1504,9 +1409,9 @@ class MainWindow_Controller(QMainWindow):
else:
p.resume()
def kill_process(self, info, p, target, relation=False):
def kill_process(self, info, p, target, relation):
try:
target = target.replace("/", "\\")
target = target.replace("\\", "/")
if relation == False:
p.kill()
elif relation == True:
@@ -1517,13 +1422,13 @@ class MainWindow_Controller(QMainWindow):
file = str(cmd[-1].split("'")[-2])
elif "cmd.exe" in name:
file = str(" ".join(cmd[2:]))
elif ":/Windows" in file:
elif ":/Windows" in file.replace("\\", "/"):
file = str(cmd[-1])
if target == file.replace("\\", "/"):
p.kill()
except:
pass
self.send_notify(self.trans(f"{info}: ")+target)
self.send_notify(self.trans(f"{info}: ")+target, True)
self.track_proc = None
except:
self.track_proc = None
@@ -1549,13 +1454,15 @@ class MainWindow_Controller(QMainWindow):
self.ransom_counts += 1
elif action == 4 and ftype in alist:
self.ransom_counts += 1
if action == 3 and ftype in slist and self.start_scan(fpath):
os.remove(fpath)
self.send_notify(self.trans("病毒刪除: ")+fpath)
if ":/Windows" not in fpath and ftype in slist:
if action == 3 and self.start_scan(fpath):
self.ransom_counts = 0
os.remove(fpath)
self.send_notify(self.trans("病毒刪除: ")+fpath, True)
except:
pass
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):
while self.sys_protect and self.mbr_value:
@@ -1571,7 +1478,7 @@ class MainWindow_Controller(QMainWindow):
except:
self.kill_process("引導攔截", *self.track_proc)
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):
while self.sys_protect:
@@ -1584,21 +1491,19 @@ class MainWindow_Controller(QMainWindow):
except:
pass
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):
while self.net_protect:
try:
time.sleep(0.2)
local = socket.gethostbyname(socket.gethostname())
for conn in self.track_proc.connections():
if ":/Windows" not in file and ":/Program" not in file:
if conn.laddr.ip == local:
self.kill_process("網路攔截", *self.track_proc)
for conn in self.track_proc[0].connections(kind='inet'):
if conn.raddr.ip in self.rules.network:
self.kill_process("網路攔截", *self.track_proc)
except:
pass
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__':
QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
+102 -76
View File
@@ -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):
self.model = {}
self.rules = {}
self.network = []
def save_model(self, file_name):
with open(file_name, 'w') as f:
json.dump(self.model, f)
print(f"\nModel Is Saved In {file_name}")
def load_rules(self, file_path):
try:
ftype = str(f".{file_path.split('.')[-1]}").lower()
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):
if isinstance(model_data, str):
with open(model_data, 'r') as f:
model_data = json.load(f)
self.model = model_data
def yr_scan(self, file_path):
try:
if isinstance(file_path, str):
with open(file_path, "rb") as f:
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):
return self.model[label]
class DLScan:
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):
start = time.time()
print(f"Convert {label}")
if label not in self.model:
self.model[label] = []
for i, x in enumerate(data, 1):
build_text = self.build_text(x, batch_size)
self.model[label].append(build_text)
used = "{0:.2f}".format(time.time()-start)
prefix, suffix = f'{i}/{len(data)}:', f'{used}s'
self.progress_bar(i, len(data), prefix, suffix)
def load_model(self, file_path):
try:
ftype = str(f".{file_path.split('.')[-1]}").lower()
if ftype in [".json", ".txt"]:
with open(file_path, 'r') as f:
self.class_names = json.load(f)
elif ftype in [".onnx"]:
self.models[file_path] = onnxruntime.InferenceSession(file_path)
self.labels = self.class_names['Labels']
self.detect = self.class_names['Detect']
self.pixels = self.class_names['Pixels']
self.values = self.class_names['Values']
except Exception as e:
pass
def build_text(self, content, batch_size):
sums, batch, count = [], [], {}
for index, char in enumerate(content):
count[char] = count.setdefault(char, 0) + 1
combined_input = f"{count[char]}_{char}"
hashes = hashlib.sha256(combined_input.encode('utf-8'))
batch.append(hashes.digest())
if len(batch) >= batch_size:
sums.append(self.sum_hashes(batch))
batch = []
if batch:
sums.append(self.sum_hashes(batch))
combined_sums = numpy.sum(sums, 0) > len(content) / 2
v = numpy.packbits(combined_sums).tobytes()
return int.from_bytes(v, 'big')
def dl_scan(self, file_data):
try:
target_size, sim = tuple(self.pixels), {}
image = self.preprocess_image(file_data, target_size)
image_array = numpy.array(image).astype('float32') / 255.0
image_expand = numpy.expand_dims(image_array, axis=0)
for model_name, model in self.models.items():
input_name = model.get_inputs()[0].name
pre_answer = model.run(None, {input_name: image_expand})[0][0]
number = numpy.argmax(pre_answer)
label = self.labels[number].replace("\n", "")
sim[label] = sim.setdefault(label, 0) + pre_answer[number]
for local_label, sim_sum in sim.items():
if sim_sum > len(self.models) / 2:
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):
bitarray = numpy.unpackbits(numpy.frombuffer(b''.join(digests), dtype='>B'))
return numpy.sum(numpy.reshape(bitarray, (-1, 256)), 0)
def get_type(self, file_path):
try:
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='█'):
percent = min(100.0, max(0.0, 100 * (items / float(total))))
end_char = '\n' if percent >= 100 else '\r'
percent_string = "{0:.2f}".format(percent)
filled_length = int(length * items // total)
bar = fill * filled_length + ' ' * (length - filled_length)
print(f'\r{prefix: <15} |{bar}| {percent_string}% {suffix}', end=end_char)
def predict_all(self, query, batch_size=10000):
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
def preprocess_image(self, file_data, target_size):
file_data = numpy.frombuffer(file_data, dtype=numpy.uint8)
data_count = len(file_data)
wah = int(numpy.ceil(numpy.sqrt((data_count + 2) // 3)))
image_array = numpy.zeros((wah * wah * 3,), dtype=numpy.uint8)
image_array[:data_count] = file_data
image_array = image_array.reshape((wah, wah, 3))
image = Image.fromarray(image_array)
return image.resize(target_size, Image.Resampling.LANCZOS)
-46
View File
@@ -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
View File
@@ -16,14 +16,15 @@ translate_dict = {
"綠":"绿","態":"态","務":"务","連":"连","檢":"检","測":"测","關":"关",
"強":"强","驅":"驱","為":"为","腳":"脚","單":"单","開":"开","擴":"扩",
"惡":"恶","據":"据","庫":"库","經":"经","敗":"败","謝":"谢","別":"别",
"載":"载","誤":"误","報":"报","鏈":"链","竄":"窜","記憶體":"内存",},
"載":"载","誤":"误","報":"报","鏈":"链","竄":"窜","蹤":"踪","記憶體":"内存",},
"en_US": {"已開啟":"On","已關閉":"Off","已开启":"On","已关闭":"Off",",":", ",
"立即刪除":"Delete Now","安全模式":"Safe Mode","官方網站":"Website ",
"腳本":"Script ","鏈式":"Chain ","記憶體":"Memory ","加載":"Load ",
"行為":"Behavior ","可疑":"Suspicious ","勒索":"Ransom ",
"許可條款":"License Terms ","惡意":"Malicious","可疑":"Suspicious",
"啟用":"Enable ","禁用":"Disable ","正在初始化中":"Initializing ",
"正在掃描":"Scanning ","正在刪除":"Deleting ","最小化到":"Minimize To ",
"正在掃描":"Scanning ","正在刪除":"Deleting ","正在追蹤":"Tracking ",
"最小化到":"Minimize To ","靈敏度":"Sensitivity ","正在檢查":"Checking ",
"確定要":"Sure Want To ","引擎靈敏度":"Sensitivity ","更新":"Update ",
"白色主題":"White","黃色主題":"Yellow","紅色主題":"Red","語言":"Language ",
"藍色主題":"Blue","綠色主題":"Green","自定主題":"Custom","最新":"Latest ",
@@ -45,7 +46,7 @@ translate_dict = {
"風險":"Risk ","介面":"GUI ","核心":"Core ","服務":"Services ",
"管理":"Manage","所有":"All ","您":"You ","取消":"Cancel ","未":"Not ",
"垃圾":"Junk ","位元":"byte ","本機":"Computer ","停止":"Stop ",
"增加到":"Add To ","白名單":"White List ","軟體":"Software ","正在":"Start ",
"增加到":"Add To ","白名單":"White List ","軟體":"Software ","正在":"",
"增加":"Add ","移除":"Delete","項目":"Items ","生成":"Create ","稱":"",
"複製":"Copy ","開啟":"Open ","此":"This ","並":"And ","全盤":"Full ",
"已經在":"Already ","數據庫":"Database ","誤報":"False Positive ",
@@ -53,7 +54,7 @@ translate_dict = {
"日誌":"Log","已":"Has ","彈窗":"Window ","要":"To ","驅動":"Driver ",
"的":"","顯示":"","個":"","嗎":"","中":"","了":"","行":"","立即":"",
"密鑰":"Key ","檢測":"Detect ","製作":"Maker ","運行":"Running",
"擴展":"Extension ","套件":"Kit ","自動":"Auto ","上報":"Report ","與":"With ",
"擴展":"Extension ","套件":"Kit ","自動":"Auto ","上報":"Report ",
"分析":"Analysis ","自身":"Self ","其他":"Other ","配置":"Config ",
"丟失":"Lost ","網站":"Website ","不兼容":"Not Compatible ","追蹤":"Tracking ",
"竄改":"Tamper ","靈敏度":"Sensitivity ","第三方":"Other "," ":" "}}
"丟失":"Lost ","網站":"Website ","不兼容":"Not Compatible ",
"竄改":"Tamper ","第三方":"Other ","與":"With "," ":" "}}
+4 -3
View File
@@ -1,7 +1,8 @@
slist = [".exe",".dll",".com",".msi",".scr",
".js",".bat",".cmd",".ps1",".vbs"]
slist = [".exe",".dll",".sys",".com",".scr",
".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",
".ppt",".pptx",".wps",".txt",".rtf",
".pdf",".xls",".xlsx",".doc",".docx",
+1 -1
View File
@@ -2,7 +2,7 @@ import pyinstaller_versionfile
pyinstaller_versionfile.create_versionfile(
output_file="versionfile.txt",
version='3.1.5',
version='3.2.1',
company_name="PYAS Security",
file_description="Python Antivirus Software",
internal_name="PYAS",
+17 -15
View File
@@ -1,6 +1,6 @@
# PYAS (Python Antivirus Software)
![PYAS](https://github.com/87owo/PYAS/assets/85057800/8136aaca-d388-4321-bedb-abc4fcecfa8b)
![PYAS](https://github.com/user-attachments/assets/39c273b9-c467-480a-a8b3-31714a6df3ef)
## Readme Language
@@ -11,12 +11,16 @@
## Requirements
```
psutil==5.9.5
pefile==2023.2.7
requests==2.31.0
pyperclip==1.8.2
pywin32==306
PyQt5==5.15.9
pip install psutil==5.9.5
pip install pefile==2023.2.7
pip install requests==2.31.0
pip install pyperclip==1.8.2
pip install pywin32==306
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
@@ -24,12 +28,7 @@ PyQt5==5.15.9
```
PYAS/
├── Driver/
│ ├── PYAS_Driver.sys -------> Extension Kit (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)
│ ├── PYAS_Driver.sys -------> Driver Protect (self protection driver for pyas by 0sha0)
│ └── ...
│
├── Model/
@@ -41,10 +40,9 @@ PYAS/
│ ├── 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_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_Resource.py -----------> PyQt5 Resource (status pictures, icon packages, button icons, ...)
├── PYAS_Language.py -----------> Translate Dict (Traditional Chinese, Simplified Chinese, English)
@@ -58,6 +56,10 @@ https://pyantivirus.wixsite.com/pyas
https://github.com/87owo/PYAS
## Microsoft Runtime
https://github.com/87owo/Microsoft_Runtime/releases
## PYAS Driver
https://github.com/0sha0/PYAS_Protection
+19 -17
View File
@@ -1,16 +1,20 @@
# PYAS (Python 杀毒软件)
![PYAS](https://github.com/87owo/PYAS/assets/85057800/8136aaca-d388-4321-bedb-abc4fcecfa8b)
![PYAS](https://github.com/user-attachments/assets/39c273b9-c467-480a-a8b3-31714a6df3ef)
## 安装要求
```
psutil==5.9.5
pefile==2023.2.7
requests==2.31.0
pyperclip==1.8.2
pywin32==306
PyQt5==5.15.9
pip install psutil==5.9.5
pip install pefile==2023.2.7
pip install requests==2.31.0
pip install pyperclip==1.8.2
pip install pywin32==306
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 提供的自我保护驱动程序)
│ └── ...
│
├── Exten/
│ ├── bitdefender/ ----------> 扩展套件 (bitdefender windows 控制台扫描引擎)
│ ├── pe_sieve/ -------------> 扩展套件 (pe sieve windows 控制台内存引擎)
│ └── ...
│
├── Model/
│ ├── PYAS_Model.json -------> 病毒数据库 (数据库必须位于指定目录中)
│ └── ...
@@ -35,14 +34,13 @@ PYAS/
│ ├── Yara_Rules.yrc ---------> 编译规则 (编译格式的 yara 规则)
│ └── ...
│
├── PYAS.* ---------------------> PYAS主程序(包含动画、扫描、保护等功能...)
├── PYAS.py ---------------------> PYAS主程序(包含动画、扫描、保护等功能...)
├── PYAS_Engine.py -------------> 转换数据库(用于转换剖面图和预报数据)
├── PYAS_Suffixes.py -----------> 文件后缀(包含扫描文件后缀和常用后缀)
├── PYAS_Extension.py ----------> 扩展工具包(其他开发者开发的扩展扫描器)
├── PYAS_Interface.py ----------> PyQt5界面(使用QT设计器,需与主程序搭配使用)
├── PYAS_Resource.py -----------> PyQt5资源(状态图片、图标包、按钮图标...)
├── 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/blob/main/LICENSE.md
https://github.com/87owo/Microsoft_Runtime/releases
## 驱动程序
https://github.com/0sha0/PYAS_Protection
## 开源协议
https://github.com/87owo/PYAS/blob/main/LICENSE.md
## 支援系统
Windows 8.1, 10, 11 (64-bit), 内存 500MB, 存储 200MB 或更高
+19 -17
View File
@@ -1,16 +1,20 @@
# PYAS (Python 防毒軟體)
![PYAS](https://github.com/87owo/PYAS/assets/85057800/8136aaca-d388-4321-bedb-abc4fcecfa8b)
![PYAS](https://github.com/user-attachments/assets/39c273b9-c467-480a-a8b3-31714a6df3ef)
## 安裝要求
```
psutil==5.9.5
pefile==2023.2.7
requests==2.31.0
pyperclip==1.8.2
pywin32==306
PyQt5==5.15.9
pip install psutil==5.9.5
pip install pefile==2023.2.7
pip install requests==2.31.0
pip install pyperclip==1.8.2
pip install pywin32==306
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 提供的自我保護驅動程式)
│ └── ...
│
├── Exten/
│ ├── bitdefender/ ----------> 擴充套件 (bitdefender windows 控制台掃描引擎)
│ ├── pe_sieve/ -------------> 擴充套件 (pe sieve windows 控制台記憶體引擎)
│ └── ...
│
├── Model/
│ ├── PYAS_Model.json -------> 病毒資料庫 (資料庫必須位於指定目錄)
│ └── ...
@@ -35,14 +34,13 @@ PYAS/
│ ├── Yara_Rules.yrc ---------> 編譯規則 (編譯格式的 yara 規則)
│ └── ...
│
├── PYAS.* ---------------------> PYAS主程式(包含動畫、掃描、保護等功能...)
├── PYAS.py ---------------------> PYAS主程式(包含動畫、掃描、保護等功能...)
├── PYAS_Engine.py -------------> 轉換資料庫(用於轉換剖面圖和預報資料)
├── PYAS_Suffixes.py -----------> 文件後綴(包含掃描文件後綴和常用後綴)
├── PYAS_Extension.py ----------> 擴充工具包(其他開發者開發的擴充掃描器)
├── PYAS_Interface.py ----------> PyQt5介面(使用QT設計器,需與主程式搭配使用)
├── PYAS_Resource.py -----------> PyQt5資源(狀態圖片、圖示包、按鈕圖示...)
├── 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/blob/main/LICENSE.md
https://github.com/87owo/Microsoft_Runtime/releases
## 驅動程式
https://github.com/0sha0/PYAS_Protection
## 開源協議
https://github.com/87owo/PYAS/blob/main/LICENSE.md
## 支援系統
Windows 8.1, 10, 11 (64-bit),記憶體 500MB, 磁碟容量 200MB 或更高
+256387
View File
File diff suppressed because it is too large. Load diff