Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5700039d42 | ||
|
|
22445c79d4 | ||
|
|
2be05ac76c | ||
|
|
84e397aeed | ||
|
|
bb513b9115 | ||
|
|
01b680e278 | ||
|
|
ef7c1cba2e | ||
|
|
40bbc57c82 | ||
|
|
457e5bebbb | ||
|
|
99abc56177 | ||
|
|
9eeb0b6376 | ||
|
|
0b2da187ee | ||
|
|
06f5410a4d | ||
|
|
2551ada3b7 | ||
|
|
56df08879e | ||
|
|
d41685c86e | ||
|
|
14b942970e | ||
|
|
b6103c845d | ||
|
|
7927f12e84 | ||
|
|
7774ff77b2 | ||
|
|
aaa2ed7eef | ||
|
|
b83674e9b7 | ||
|
|
017356780c | ||
|
|
45916004d2 | ||
|
|
388c8b615e | ||
|
|
4219473632 | ||
|
|
f2283cdb7f | ||
|
|
72ce9cfd6b | ||
|
|
b26375d25a | ||
|
|
a2a823f358 | ||
|
|
62164cf628 | ||
|
|
0b5fc22181 | ||
|
|
0df905f777 | ||
|
|
a539a948f6 | ||
|
|
6bd8364b5f | ||
|
|
70b70bc3e7 | ||
|
|
ac50f8917e | ||
|
|
f935b2c0b6 | ||
|
|
245c9d1119 | ||
|
|
9476313725 | ||
|
|
2d27a74278 | ||
|
|
823a5115eb | ||
|
|
33ab1e1f5e | ||
|
|
8db984d1fd | ||
|
|
a00415657a | ||
|
|
527837cc56 | ||
|
|
ac9ddff8b1 | ||
|
|
4ebae2a167 | ||
|
|
11f1685f42 | ||
|
|
8199101891 | ||
|
|
4f3ce323ae | ||
|
|
76befc7c70 | ||
|
|
8b0ad06676 | ||
|
|
d7f091a3a9 | ||
|
|
679b00229c | ||
|
|
0cfc636fb6 | ||
|
|
bd3c31e150 | ||
|
|
8e9547b75a | ||
|
|
d38ecc0f96 | ||
|
|
85834497e0 | ||
|
|
0d8997db02 | ||
|
|
cb53450ca5 | ||
|
|
f38ae36eb6 | ||
|
|
8218b0c8a6 | ||
|
|
ea036d2d53 | ||
|
|
b163eb2cdb | ||
|
|
ba3568f312 | ||
|
|
80c9976832 | ||
|
|
b6326c25b9 | ||
|
|
35f591cf49 | ||
|
|
67e437bbd7 | ||
|
|
194dae8ce1 | ||
|
|
a89442ceb0 | ||
|
|
24debf6062 | ||
|
|
ff98846c99 | ||
|
|
e3f5a0bca1 | ||
|
|
7278e4f051 | ||
|
|
709a511c1d | ||
|
|
452027f085 | ||
|
|
8574802428 | ||
|
|
79fb044921 | ||
|
|
13ac634fea | ||
|
|
04a68bc262 | ||
|
|
47de15ab68 | ||
|
|
512af24a05 | ||
|
|
e5ff46d3bb | ||
|
|
c7a0979140 | ||
|
|
7fd7245df2 | ||
|
|
026301b011 | ||
|
|
5cc77f90ae | ||
|
|
0d4568ac8a | ||
|
|
a6ed491a39 | ||
|
|
90dfc3f1ae | ||
|
|
36388fb0d7 | ||
|
|
043166d0c8 | ||
|
|
b92d488851 | ||
|
|
d841a04a89 | ||
|
|
d8553baa78 | ||
|
|
8521d5aee3 | ||
|
|
ebe21d9c7f | ||
|
|
3b83abdbd3 | ||
|
|
aead2463c9 | ||
|
|
5cc5676672 | ||
|
|
ecc32ca18d | ||
|
|
661640de79 | ||
|
|
96dfdab7ed | ||
|
|
56bed5fd3b | ||
|
|
3fd3b18406 | ||
|
|
45bac97a16 | ||
|
|
2c6eca4a92 | ||
|
|
8109d59655 | ||
|
|
8a15571cd2 | ||
|
|
a15c8f2e60 | ||
|
|
cec3d6c04d | ||
|
|
d872604855 | ||
|
|
2b6fb933a4 | ||
|
|
1da892e863 | ||
|
|
19bfedd1a3 | ||
|
|
cb87392d9d | ||
|
|
7cd5bc9ec3 | ||
|
|
edcc1a30ab |
No files matched your search
@@ -0,0 +1,34 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
:: Check for permissions
|
||||
>nul 2>&1 "%SYSTEMROOT%\system32\icacls.exe" "%SYSTEMROOT%\system32\config\system"
|
||||
|
||||
if %errorlevel% NEQ 0 goto NoAdmin
|
||||
goto gotAdmin
|
||||
|
||||
:NoAdmin
|
||||
echo You do not have administrator rights, please run this script as administrator.
|
||||
pause
|
||||
exit /B
|
||||
|
||||
:gotAdmin
|
||||
if exist "%temp%\getadmin.vbs" del "%temp%\getadmin.vbs"
|
||||
|
||||
set "script_dir=%~dp0"
|
||||
set "script_dir=%script_dir:~0,-1%"
|
||||
|
||||
bcdedit -debug on
|
||||
bcdedit /set testsigning on
|
||||
bcdedit /deletevalue {current} safeboot
|
||||
|
||||
powershell.exe -ExecutionPolicy Bypass -Command ^
|
||||
"$endDate = (Get-Date).AddYears(100); ^
|
||||
$cert = New-SelfSignedCertificate -DnsName PYAS -CertStoreLocation cert:\LocalMachine\My -Type CodeSigning -NotAfter $endDate; ^
|
||||
$pwd = ConvertTo-SecureString -String 'PYAS' -Force -AsPlainText; ^
|
||||
Export-PfxCertificate -Cert $cert -FilePath '%script_dir%\PYAS.pfx' -Password $pwd;"
|
||||
"%script_dir%\signtool.exe" sign /f "%script_dir%\PYAS.pfx" /p PYAS "%script_dir%\PYAS_Driver.sys"
|
||||
sc create PYAS_Driver type= kernel start= demand binPath= "%script_dir%\PYAS_Driver.sys"
|
||||
|
||||
shutdown -r -t 0
|
||||
endlocal
|
||||
Whitespace-only changes.
Binary file not shown.
@@ -0,0 +1,25 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
:: Check for permissions
|
||||
>nul 2>&1 "%SYSTEMROOT%\system32\icacls.exe" "%SYSTEMROOT%\system32\config\system"
|
||||
|
||||
if %errorlevel% NEQ 0 goto NoAdmin
|
||||
goto gotAdmin
|
||||
|
||||
:NoAdmin
|
||||
echo You do not have administrator rights, please run this script as administrator.
|
||||
pause
|
||||
exit /B
|
||||
|
||||
:gotAdmin
|
||||
if exist "%temp%\getadmin.vbs" del "%temp%\getadmin.vbs"
|
||||
|
||||
sc stop PYAS_Driver
|
||||
sc delete PYAS_Driver
|
||||
|
||||
bcdedit /set testsigning off
|
||||
bcdedit -debug off
|
||||
|
||||
shutdown -r -t 0
|
||||
endlocal
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
{"Unknown": [38413146381396798812836662586219087594480760119241756145287379993031670453973, 96759775057307603829199050115151442660431386536877578909394799687553144825391], "White": [92860071170291586757870565976957954052649178883790647665503983139114277816413, 50625869624179221836524636484722091669820057030729734765256925026245308185143, 79303266820014134748061006437377483029320717142203104125806969476209010566146, 50391760446499089493384482654016917630509060287507523223191455177998253781572, 34733894651460458125941968926483828168477919119649839915356573816494375383659, 16447578251589668808184123721615810667991570306415913809506896532563163557975, 18668853151306203943053249777678854424409647574074706653144503993068509738028, 16447129799599854768187525514242197965987640167415805965954293039200573272151, 42965648781535883376480003940402366467478625051031283341289116138472520399484, 45637511530246203537935382208327538642024163565740899790237852717178844340385, 100662025713257198141308144602569453810226448934776598411982222249289646045820, 2813878798545665948450767843887867208740292941021073849284371582085785669685, 54695748401254225125045716155327877471149349614359435230254611073117412307518, 27428665293760567560050957450577436769403462770366418052177943137905489504373, 32018095881556959863902669246154132691484124511748151111295836576906027842532, 82735669648112373508385530969898006750362429118827185652448450648454052106395, 27853809242729492000984914092533936796891917926358854729439436487683423285261, 20030429995379197455160031864140436552884002299333955332088108013764717533796, 82338140557728967648601024370995428985866052631101882076231147335348455671038, 71339449324799277130427957011381342555145697382104653874846579353871764366968, 2432232479351500614611699169184443988440809841079862157291791071419485606436, 9463527399566410848087352636323112952591923803840644609432039785310381355253, 17287926889345790925003722717807755244540044472850272987265624141065166747251, 31507509644511868166890345905396462199402122513677304280568315890707028374136, 92802443753971611323223428952970105040389824130209263287070763891097867755624, 60491018752293550079699763462944244393253888103551546202593483014975813742967, 45133408084728538869955951560598604064861024543940290379768365214821771604584, 6759146298068049614085390992799666053918974602489525613718797088468975708017, 43161770374046173333870752071317153674965637163816017117315179871715332666383, 55200886519442939000007636174371797768786544863806926514781108850256791225983, 102124766481586899841647737641698083212305154684644839980199278690335383712492, 52992286898317605666180786036367620316269750824654214415314225077986227890804, 96307454545313440124283308270263825589093792315386382296096934270155352236733, 36073459579994433898643313577597321150634749356791285363958792075031385371364, 5354562433688861244299028006341553420425390015040147574513776499404802540118, 2671602537216404752611755689384448521170725107261295121211275163689399347529, 31174448189678483951801405655647041557287598300853213718404097030076935043252, 817984956081990458969224676381868506770627801582748844000835755782736667191, 6997953573828232905847825866256444005094471443450029313008738013465446666864, 41288968033780608769032189481784193916730262129846893330891418484950645535282, 56724589038911745751056508177185337741291265472470897077742981563488398484126, 3353938097938067320481103667469354721822387389147415219233498938990215839034, 21195721951654457114265478558602466514207347021822959737607658828495062116920, 2916561284514958799877078174216081002558870786437593202464334407456915288119, 93137488384582768487662730765406914258099784103320160609442537879778117334700, 21195721951654457114265478558602377311225888285332501136798116331518898022972, 85036278951571446667616241901438186945472743486751871120301019617002115253240, 14623491695050192413097067629676318500123044497134202517578785087180871258165, 2022308710750553104057453378681448926020203033444470910346149752954363011822, 16435447118324352510213480738895714506136417806014749563314727656196027207884, 20110908101408861236178371339075650317185505287106087252378028881915405550816, 97262306467112548995108413358594977802790545321935863056096364390382492643957, 96614497885586867524036482497010189662872359368622249290846422070379022959337, 1895288773648887609359329471072769468085207279473521707976899919066265183340, 2651591106060448314208209841614702280337184080195391257416359882876000875095, 114619913163036058498985801603082782363327281628924544162718017899237779173997, 2481883953883130814217575190747389944608730963897863224598923997640828351014, 45000300637061336566799421885334051647634671537987073940268834014403441552901, 79047998258892679051555952202178856054614923426747250310189496005785954516966, 92887093185298651693450115442544102614083847612212241647641096093293220418098, 7140769773119319253009453104401896171570019200295580355390762162793695491644, 17012496707Line truncated
|
||||
@@ -1,6 +1,5 @@
|
||||
import os, gc, sys, time, json, psutil
|
||||
import hashlib, pefile, socket, msvcrt
|
||||
import xml.etree.ElementTree as xmlet
|
||||
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
|
||||
@@ -11,6 +10,7 @@ from threading import Thread
|
||||
from PyQt5.QtWidgets import *
|
||||
from PyQt5.QtCore import *
|
||||
from PyQt5.QtGui import *
|
||||
from subprocess import *
|
||||
|
||||
class MainWindow_Controller(QMainWindow):
|
||||
def __init__(self):
|
||||
@@ -19,11 +19,12 @@ class MainWindow_Controller(QMainWindow):
|
||||
self.setWindowFlags(Qt.FramelessWindowHint)
|
||||
self.pyas = sys.argv[0].replace("\\", "/")
|
||||
self.dir = os.path.dirname(self.pyas)
|
||||
self.pyae_version = "SimHash Engine"
|
||||
self.pyas_version = "3.0.7"
|
||||
self.pyae_version = "Fusion Engine"
|
||||
self.pyas_version = "3.1.3"
|
||||
self.ui = Ui_MainWindow()
|
||||
self.ui.setupUi(self)
|
||||
self.init_show_pyas()
|
||||
self.init_sys_drive()
|
||||
self.init_rule_dict()
|
||||
self.init_data_base()
|
||||
self.init_read_json()
|
||||
self.init_tray_icon()
|
||||
@@ -31,10 +32,9 @@ class MainWindow_Controller(QMainWindow):
|
||||
self.init_config_json()
|
||||
self.init_config_list()
|
||||
self.init_config_qtui()
|
||||
self.init_change_lang()
|
||||
self.init_theme_color()
|
||||
self.init_control()
|
||||
self.init_threads()
|
||||
self.init_startup()
|
||||
|
||||
def init_threads(self):
|
||||
self.protect_proc_init()
|
||||
@@ -50,12 +50,53 @@ class MainWindow_Controller(QMainWindow):
|
||||
self.tray_icon.activated.connect(self.init_show_pyas)
|
||||
self.tray_icon.show()
|
||||
|
||||
def init_startup(self):
|
||||
try:
|
||||
if len(sys.argv) > 1:
|
||||
param = sys.argv[1]
|
||||
if "h" in param or "hid" in param:
|
||||
pass
|
||||
else:
|
||||
self.init_show_pyas()
|
||||
elif len(sys.argv) <= 1:
|
||||
self.init_show_pyas()
|
||||
except Exception as e:
|
||||
self.bug_event(e)
|
||||
|
||||
def init_sys_drive(self):
|
||||
try:
|
||||
file_path = os.path.join(self.dir, "Driver")
|
||||
if os.path.exists(file_path):
|
||||
Popen("sc start PYAS_Driver", shell=True, stdout=PIPE, stderr=PIPE).wait()
|
||||
except Exception as e:
|
||||
self.bug_event(e)
|
||||
|
||||
def init_data_base(self):
|
||||
try:
|
||||
file_path = os.path.join(self.dir, "PYAS_Model.json")
|
||||
if os.path.exists(file_path):
|
||||
self.pe = ListSimHash()
|
||||
self.pe.load_model(file_path)
|
||||
file_path = os.path.join(self.dir, "Model")
|
||||
for root, dirs, files in os.walk(file_path):
|
||||
for file in files:
|
||||
model_path = os.path.join(root, file)
|
||||
ftype = str(f".{file.split('.')[-1]}").lower()
|
||||
if ftype in [".json", ".txt"]:
|
||||
self.pe = ListSimHash()
|
||||
self.pe.load_model(model_path)
|
||||
except Exception as e:
|
||||
self.bug_event(e)
|
||||
|
||||
def init_rule_dict(self):
|
||||
try:
|
||||
self.compiled_rules = {}
|
||||
file_path = os.path.join(self.dir, "Rules")
|
||||
for root, dirs, files in os.walk(file_path):
|
||||
for file in files:
|
||||
yara_path = os.path.join(root, file)
|
||||
ftype = str(f".{file.split('.')[-1]}").lower()
|
||||
if ftype in [".yara", ".yar"]:
|
||||
rules = yara.compile(yara_path)
|
||||
elif ftype in [".yc", ".yrc"]:
|
||||
rules = yara.load(yara_path)
|
||||
self.compiled_rules[yara_path] = rules
|
||||
except Exception as e:
|
||||
self.bug_event(e)
|
||||
|
||||
@@ -93,32 +134,26 @@ class MainWindow_Controller(QMainWindow):
|
||||
if not os.path.exists("C:/ProgramData/PYAS"):
|
||||
os.makedirs("C:/ProgramData/PYAS")
|
||||
if not os.path.exists("C:/ProgramData/PYAS/PYAS.json"):
|
||||
self.write_config({"high_sensitive":0,"cloud_services":1,
|
||||
"language":"en_US","theme_color":"White","theme_custom":""})
|
||||
self.write_config({"language":"en_US","theme_color":"White",
|
||||
"high_sensitive":0,"cloud_services":"http://127.0.0.1/"})
|
||||
with open("C:/ProgramData/PYAS/PYAS.json", "r") as f:
|
||||
self.json = json.load(f)
|
||||
except:
|
||||
self.write_config({"high_sensitive":0,"cloud_services":1,
|
||||
"language":"en_US","theme_color":"White","theme_custom":""})
|
||||
self.write_config({"language":"en_US","theme_color":"White",
|
||||
"high_sensitive":0,"cloud_services":"http://127.0.0.1/"})
|
||||
with open("C:/ProgramData/PYAS/PYAS.json", "r") as f:
|
||||
self.json = json.load(f)
|
||||
|
||||
def init_config_json(self):
|
||||
self.json["high_sensitive"] = self.json.get("high_sensitive", 0)
|
||||
self.json["cloud_services"] = self.json.get("cloud_services", 1)
|
||||
self.json["language"] = self.json.get("language", "en_US")
|
||||
self.json["theme_color"] = self.json.get("theme_color", "White")
|
||||
self.json["theme_custom"] = self.json.get("theme_custom", "")
|
||||
self.json["high_sensitive"] = self.json.get("high_sensitive", 0)
|
||||
self.json["cloud_services"] = self.json.get("cloud_services", "http://127.0.0.1/")
|
||||
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["cloud_services"] == 1:
|
||||
self.ui.cloud_services_switch_Button.setText(self.trans("已開啟"))
|
||||
self.ui.cloud_services_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["language"] == "zh_TW":
|
||||
self.ui.Language_Traditional_Chinese.setChecked(True)
|
||||
elif self.json["language"] == "zh_CN":
|
||||
@@ -135,7 +170,7 @@ class MainWindow_Controller(QMainWindow):
|
||||
self.ui.Theme_Yellow.setChecked(True)
|
||||
elif self.json["theme_color"] == "Blue":
|
||||
self.ui.Theme_Blue.setChecked(True)
|
||||
elif self.json["theme_color"] == "Custom":
|
||||
elif os.path.exists(self.json["theme_color"]):
|
||||
self.ui.Theme_Customize.setChecked(True)
|
||||
|
||||
def init_control(self):
|
||||
@@ -170,17 +205,17 @@ class MainWindow_Controller(QMainWindow):
|
||||
self.ui.Protection_switch_Button_4.clicked.connect(self.protect_reg_init)
|
||||
self.ui.Protection_switch_Button_5.clicked.connect(self.protect_net_init)
|
||||
self.ui.high_sensitivity_switch_Button.clicked.connect(self.change_sensitive)
|
||||
self.ui.cloud_services_switch_Button.clicked.connect(self.change_cloud_service)
|
||||
self.ui.cloud_services_switch_Button.clicked.connect(self.cloud_service)
|
||||
self.ui.Add_White_list_Button.clicked.connect(self.add_white_list)
|
||||
self.ui.Language_Traditional_Chinese.clicked.connect(self.init_change_lang)
|
||||
self.ui.Language_Simplified_Chinese.clicked.connect(self.init_change_lang)
|
||||
self.ui.Language_English.clicked.connect(self.init_change_lang)
|
||||
self.ui.Theme_White.clicked.connect(self.change_theme)
|
||||
self.ui.Theme_Customize.clicked.connect(self.change_theme)
|
||||
self.ui.Theme_Green.clicked.connect(self.change_theme)
|
||||
self.ui.Theme_Yellow.clicked.connect(self.change_theme)
|
||||
self.ui.Theme_Blue.clicked.connect(self.change_theme)
|
||||
self.ui.Theme_Red.clicked.connect(self.change_theme)
|
||||
self.ui.Theme_White.clicked.connect(self.init_theme_color)
|
||||
self.ui.Theme_Customize.clicked.connect(self.init_theme_color)
|
||||
self.ui.Theme_Green.clicked.connect(self.init_theme_color)
|
||||
self.ui.Theme_Yellow.clicked.connect(self.init_theme_color)
|
||||
self.ui.Theme_Blue.clicked.connect(self.init_theme_color)
|
||||
self.ui.Theme_Red.clicked.connect(self.init_theme_color)
|
||||
|
||||
def init_config_qtui(self):
|
||||
self.ui.widget_2.lower()
|
||||
@@ -285,16 +320,16 @@ class MainWindow_Controller(QMainWindow):
|
||||
self.ui.GUI_Made_Name.setText(self.trans("mtkiao"))
|
||||
self.ui.Core_Made_title.setText(self.trans("核心製作:"))
|
||||
self.ui.Core_Made_Name.setText(self.trans("87owo"))
|
||||
self.ui.Testers_title.setText(self.trans("測試人員:"))
|
||||
self.ui.Testers_Name.setText(self.trans("87owo"))
|
||||
self.ui.Testers_title.setText(self.trans("特別感謝:"))
|
||||
self.ui.Testers_Name.setText(self.trans("0sha0"))
|
||||
self.ui.PYAS_URL_title.setText(self.trans("官方網站:"))
|
||||
self.ui.PYAS_URL.setText(self.trans("<html><head/><body><p><a href=\"https://github.com/87owo/PYAS\"><span style=\" text-decoration: underline; color:#000000;\">https://github.com/87owo/PYAS</span></a></p></body></html>"))
|
||||
self.ui.high_sensitivity_title.setText(self.trans("高靈敏度模式"))
|
||||
self.ui.high_sensitivity_illustrate.setText(self.trans("啟用此選項可以提高引擎的靈敏度"))
|
||||
self.ui.high_sensitivity_switch_Button.setText(self.trans(self.ui.high_sensitivity_switch_Button.text()))
|
||||
self.ui.cloud_services_title.setText(self.trans("雲端掃描服務"))
|
||||
self.ui.cloud_services_illustrate.setText(self.trans("啟用此選項可以連接雲端掃描服務"))
|
||||
self.ui.cloud_services_switch_Button.setText(self.trans(self.ui.cloud_services_switch_Button.text()))
|
||||
self.ui.cloud_services_title.setText(self.trans("上報雲端分析"))
|
||||
self.ui.cloud_services_illustrate.setText(self.trans("此選項可以選擇檔案並上報雲端分析"))
|
||||
self.ui.cloud_services_switch_Button.setText(self.trans("選擇"))
|
||||
self.ui.Add_White_list_title.setText(self.trans("增加到白名單"))
|
||||
self.ui.Add_White_list_illustrate.setText(self.trans("此選項可以選擇檔案並增加到白名單"))
|
||||
self.ui.Add_White_list_Button.setText(self.trans(self.ui.Add_White_list_Button.text()))
|
||||
@@ -314,64 +349,50 @@ class MainWindow_Controller(QMainWindow):
|
||||
|
||||
def init_theme_color(self):
|
||||
try:
|
||||
if self.json["theme_color"] == "White":
|
||||
if self.ui.Theme_White.isChecked():
|
||||
self.json["theme_color"] = "White"
|
||||
self.ui.State_icon.setPixmap(QPixmap(":/icon/Check.png"))
|
||||
self.ui.Window_widget.setStyleSheet("QWidget#Window_widget {background-color:rgb(240,240,240);}")
|
||||
self.ui.Navigation_Bar.setStyleSheet("QWidget#Navigation_Bar {background-color:rgb(230,230,230);}")
|
||||
elif self.json["theme_color"] == "Red":
|
||||
elif self.ui.Theme_Red.isChecked():
|
||||
self.json["theme_color"] = "Red"
|
||||
self.ui.State_icon.setPixmap(QPixmap(":/icon/Check.png"))
|
||||
self.ui.Window_widget.setStyleSheet("QWidget#Window_widget {background-color:rgb(250,230,230);}")
|
||||
self.ui.Navigation_Bar.setStyleSheet("QWidget#Navigation_Bar {background-color:rgb(250,220,220);}")
|
||||
elif self.json["theme_color"] == "Yellow":
|
||||
self.ui.State_icon.setPixmap(QPixmap(":/icon/Check.png"))
|
||||
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.json["theme_color"] == "Green":
|
||||
elif self.ui.Theme_Green.isChecked():
|
||||
self.json["theme_color"] = "Green"
|
||||
self.ui.State_icon.setPixmap(QPixmap(":/icon/Check.png"))
|
||||
self.ui.Window_widget.setStyleSheet("QWidget#Window_widget {background-color:rgb(230,250,230);}")
|
||||
self.ui.Navigation_Bar.setStyleSheet("QWidget#Navigation_Bar {background-color:rgb(220,250,220);}")
|
||||
elif self.json["theme_color"] == "Blue":
|
||||
elif self.ui.Theme_Blue.isChecked():
|
||||
self.json["theme_color"] = "Blue"
|
||||
self.ui.State_icon.setPixmap(QPixmap(":/icon/Check.png"))
|
||||
self.ui.Window_widget.setStyleSheet("QWidget#Window_widget {background-color:rgb(230,250,250);}")
|
||||
self.ui.Navigation_Bar.setStyleSheet("QWidget#Navigation_Bar {background-color:rgb(220,250,250);}")
|
||||
elif self.json["theme_color"] == "Custom":
|
||||
with open(os.path.join(self.json["theme_custom"],"Color.ini"), "r") as f:
|
||||
elif self.ui.Theme_Yellow.isChecked():
|
||||
self.json["theme_color"] = "Yellow"
|
||||
self.ui.State_icon.setPixmap(QPixmap(":/icon/Check.png"))
|
||||
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():
|
||||
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")):
|
||||
self.json["theme_color"] = path
|
||||
with open(os.path.join(self.json["theme_color"],"Color.ini"), "r") as f:
|
||||
self.themecolor = [line.strip() for line in f.readlines()]
|
||||
self.ui.Window_widget.setStyleSheet(self.themecolor[0])
|
||||
self.ui.Navigation_Bar.setStyleSheet(self.themecolor[1])
|
||||
file = os.path.join(self.json["theme_custom"],"Check.png")
|
||||
file = os.path.join(self.json["theme_color"],"Check.png")
|
||||
self.ui.State_icon.setPixmap(QPixmap(file))
|
||||
self.write_config(self.json)
|
||||
except:
|
||||
self.ui.Theme_White.setChecked(True)
|
||||
self.json["theme_color"] = "White"
|
||||
self.ui.State_icon.setPixmap(QPixmap(":/icon/Check.png"))
|
||||
self.ui.Window_widget.setStyleSheet("QWidget#Window_widget {background-color:rgb(240,240,240);}")
|
||||
self.ui.Navigation_Bar.setStyleSheet("QWidget#Navigation_Bar {background-color:rgb(230,230,230);}")
|
||||
|
||||
def read_custom_theme(self):
|
||||
try:
|
||||
path = str(QFileDialog.getExistingDirectory(self,self.trans("自定主題"),"C:/"))
|
||||
if os.path.exists(os.path.join(path,"Color.ini")):
|
||||
self.json["theme_custom"] = path
|
||||
except:
|
||||
pass
|
||||
|
||||
def change_theme(self):
|
||||
if self.ui.Theme_White.isChecked():
|
||||
self.json["theme_color"] = "White"
|
||||
elif self.ui.Theme_Red.isChecked():
|
||||
self.json["theme_color"] = "Red"
|
||||
elif self.ui.Theme_Green.isChecked():
|
||||
self.json["theme_color"] = "Green"
|
||||
elif self.ui.Theme_Yellow.isChecked():
|
||||
self.json["theme_color"] = "Yellow"
|
||||
elif self.ui.Theme_Blue.isChecked():
|
||||
self.json["theme_color"] = "Blue"
|
||||
elif self.ui.Theme_Customize.isChecked():
|
||||
self.read_custom_theme()
|
||||
self.json["theme_color"] = "Custom"
|
||||
self.write_config(self.json)
|
||||
self.init_theme_color()
|
||||
|
||||
def change_animation(self,widget):
|
||||
x, y = 170, widget.pos().y()
|
||||
self.anim = QPropertyAnimation(widget, b"geometry")
|
||||
@@ -564,11 +585,13 @@ class MainWindow_Controller(QMainWindow):
|
||||
self.setWindowOpacity(self.pyas_opacity/100)
|
||||
else:
|
||||
self.timer.stop()
|
||||
self.show()
|
||||
self.pyas_opacity = 0
|
||||
self.show()
|
||||
self.timer = QTimer()
|
||||
self.timer.timeout.connect(update_opacity)
|
||||
self.timer.start(2)
|
||||
self.init_change_lang()
|
||||
self.init_theme_color()
|
||||
|
||||
def init_hide_pyas(self):
|
||||
def update_opacity():
|
||||
@@ -589,6 +612,13 @@ class MainWindow_Controller(QMainWindow):
|
||||
|
||||
def closeEvent(self, event):
|
||||
if self.question_event("您確定要退出 PYAS 和所有防護嗎?"):
|
||||
Popen("sc stop PYAS_Driver", shell=True, stdout=PIPE, stderr=PIPE).wait()
|
||||
self.block_window = False
|
||||
self.proc_protect = False
|
||||
self.file_protect = False
|
||||
self.mbr_protect = False
|
||||
self.reg_protect = False
|
||||
self.net_protect = False
|
||||
self.virus_scan_break()
|
||||
event.accept()
|
||||
else:
|
||||
@@ -627,8 +657,10 @@ class MainWindow_Controller(QMainWindow):
|
||||
def show_menu(self):
|
||||
self.WindowMenu = QMenu()
|
||||
Main_Settings = QAction(self.trans("設定"),self)
|
||||
#Main_Update = QAction(self.trans("更新"),self)
|
||||
Main_About = QAction(self.trans("關於"),self)
|
||||
self.WindowMenu.addAction(Main_Settings)
|
||||
#self.WindowMenu.addAction(Main_Update)
|
||||
self.WindowMenu.addAction(Main_About)
|
||||
Qusetion = self.WindowMenu.exec_(self.ui.Menu_Button.mapToGlobal(QPoint(0, 30)))
|
||||
if Qusetion == Main_About and self.ui.About_widget.isHidden():
|
||||
@@ -646,6 +678,15 @@ class MainWindow_Controller(QMainWindow):
|
||||
self.ui.Window_widget.raise_()
|
||||
self.change_animation_3(self.ui.Setting_widget,0.5)
|
||||
self.change_animation_5(self.ui.Setting_widget,10,50,831,481)
|
||||
#if Qusetion == Main_Update:
|
||||
#self.update_database()
|
||||
|
||||
def update_database(self):
|
||||
try:
|
||||
if self.question_event("您確定要更新數據庫嗎?"):
|
||||
pass
|
||||
except Exception as e:
|
||||
self.bug_event(e)
|
||||
|
||||
def change_sensitive(self):
|
||||
sw_state = self.ui.high_sensitivity_switch_Button.text()
|
||||
@@ -663,21 +704,17 @@ class MainWindow_Controller(QMainWindow):
|
||||
QPushButton:hover{background-color:rgb(210,250,210);}""")
|
||||
self.write_config(self.json)
|
||||
|
||||
def change_cloud_service(self):
|
||||
sw_state = self.ui.cloud_services_switch_Button.text()
|
||||
if sw_state == self.trans("已關閉"):
|
||||
self.json["cloud_services"] = 1
|
||||
self.ui.cloud_services_switch_Button.setText(self.trans("已開啟"))
|
||||
self.ui.cloud_services_switch_Button.setStyleSheet("""
|
||||
QPushButton{border:none;background-color:rgb(200,250,200);border-radius: 10px;}
|
||||
QPushButton:hover{background-color:rgb(210,250,210);}""")
|
||||
elif sw_state == self.trans("已開啟"):
|
||||
self.json["cloud_services"] = 0
|
||||
self.ui.cloud_services_switch_Button.setText(self.trans("已關閉"))
|
||||
self.ui.cloud_services_switch_Button.setStyleSheet("""
|
||||
QPushButton{border:none;background-color:rgb(230,230,230);border-radius: 10px;}
|
||||
QPushButton:hover{background-color:rgb(220,220,220);}""")
|
||||
self.write_config(self.json)
|
||||
def cloud_service(self):
|
||||
try:
|
||||
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)
|
||||
except Exception as e:
|
||||
self.bug_event(e)
|
||||
|
||||
def init_scan(self):
|
||||
try:
|
||||
@@ -716,9 +753,9 @@ class MainWindow_Controller(QMainWindow):
|
||||
try:
|
||||
if lock:
|
||||
self.virus_lock[file] = os.open(file, os.O_RDWR)
|
||||
msvcrt.locking(self.virus_lock[file], msvcrt.LK_NBLCK, 0)
|
||||
msvcrt.locking(self.virus_lock[file], msvcrt.LK_NBLCK, os.path.getsize(file))
|
||||
else:
|
||||
msvcrt.locking(self.virus_lock[file], msvcrt.LK_UNLCK, 0)
|
||||
msvcrt.locking(self.virus_lock[file], msvcrt.LK_UNLCK, os.path.getsize(file))
|
||||
os.close(self.virus_lock[file])
|
||||
except:
|
||||
pass
|
||||
@@ -729,7 +766,8 @@ class MainWindow_Controller(QMainWindow):
|
||||
for file in self.virus_list:
|
||||
try:
|
||||
if self.ui.Virus_Scan_output.findItems(file, Qt.MatchContains)[0].checkState() == Qt.Checked:
|
||||
self.ui.Virus_Scan_text.setText(self.trans("正在刪除: ")+file)
|
||||
self.ui.Virus_Scan_title.setText(self.trans("正在刪除"))
|
||||
self.ui.Virus_Scan_text.setText(file)
|
||||
QApplication.processEvents()
|
||||
self.lock_file(file, False)
|
||||
os.remove(file)
|
||||
@@ -741,7 +779,8 @@ class MainWindow_Controller(QMainWindow):
|
||||
self.virus_list = []
|
||||
self.virus_list_ui = []
|
||||
self.ui.Virus_Scan_output.clear()
|
||||
self.ui.Virus_Scan_text.setText(self.trans("成功: 刪除成功"))
|
||||
self.ui.Virus_Scan_title.setText(self.trans("病毒掃描"))
|
||||
self.ui.Virus_Scan_text.setText(self.trans("刪除成功"))
|
||||
except Exception as e:
|
||||
self.bug_event(e)
|
||||
|
||||
@@ -761,6 +800,7 @@ class MainWindow_Controller(QMainWindow):
|
||||
|
||||
def answer_scan(self):
|
||||
try:
|
||||
self.ui.Virus_Scan_title.setText(self.trans("病毒掃描"))
|
||||
if self.virus_list:
|
||||
self.ui.Virus_Scan_Solve_Button.show()
|
||||
self.ui.Virus_Scan_Break_Button.hide()
|
||||
@@ -780,6 +820,7 @@ class MainWindow_Controller(QMainWindow):
|
||||
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("病毒掃描"))
|
||||
|
||||
def virus_scan_menu(self):
|
||||
if self.ui.Virus_Scan_choose_widget.isHidden():
|
||||
@@ -791,7 +832,7 @@ class MainWindow_Controller(QMainWindow):
|
||||
def file_scan(self):
|
||||
try:
|
||||
file = str(QFileDialog.getOpenFileName(self,self.trans("病毒掃描"),"C:/")[0])
|
||||
if file and file not in self.whitelist:
|
||||
if file and file not in self.whitelist and file != self.pyas:
|
||||
self.init_scan()
|
||||
self.write_scan(self.start_scan(file),file)
|
||||
self.answer_scan()
|
||||
@@ -829,8 +870,9 @@ class MainWindow_Controller(QMainWindow):
|
||||
break
|
||||
elif os.path.isdir(file):
|
||||
self.traverse_path(file)
|
||||
elif file not in self.whitelist:
|
||||
self.ui.Virus_Scan_text.setText(self.trans(f"正在掃描: ")+file)
|
||||
elif file not in self.whitelist and file != self.pyas:
|
||||
self.ui.Virus_Scan_title.setText(self.trans("正在掃描"))
|
||||
self.ui.Virus_Scan_text.setText(file)
|
||||
QApplication.processEvents()
|
||||
self.write_scan(self.start_scan(file),file)
|
||||
gc.collect()
|
||||
@@ -839,36 +881,21 @@ class MainWindow_Controller(QMainWindow):
|
||||
|
||||
def start_scan(self, file):
|
||||
try:
|
||||
level = self.api_scan(file)
|
||||
if file != self.pyas and level > 50:
|
||||
return f"Cloud/Blacklist.{level}"
|
||||
elif file != self.pyas and level > 10:
|
||||
vl, wl = self.pe_scan(file)
|
||||
if vl > wl and vl == 100:
|
||||
return f"Pefile/Blacklist.{vl}"
|
||||
elif vl >= wl and self.json["high_sensitive"]:
|
||||
return f"Fusion/Predict.{vl}"
|
||||
elif file != self.pyas and not level:
|
||||
vl, wl = self.pe_scan(file)
|
||||
if vl > wl and vl == 100:
|
||||
return f"Pefile/Blacklist.{vl}"
|
||||
elif vl >= wl and self.json["high_sensitive"]:
|
||||
return f"Pefile/Predict.{vl}"
|
||||
return False
|
||||
except:
|
||||
return False
|
||||
|
||||
def api_scan(self, file):
|
||||
try:
|
||||
if self.json["cloud_services"]:
|
||||
with open(file, "rb") as f:
|
||||
text = str(hashlib.md5(f.read()).hexdigest())
|
||||
QApplication.processEvents()
|
||||
strBody = f'-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="md5s"\r\n\r\n{text}\r\n-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="format"\r\n\r\nXML\r\n-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="product"\r\n\r\n360zip\r\n-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="combo"\r\n\r\n360zip_main\r\n-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="v"\r\n\r\n2\r\n-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="osver"\r\n\r\n5.1\r\n-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="vk"\r\n\r\na03bc211\r\n-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="mid"\r\n\r\n8a40d9eff408a78fe9ec10a0e7e60f62\r\n-------------------------------7d83e2d7a141e--'
|
||||
response = requests.post('http://qup.f.360.cn/file_health_info.php', data=strBody, timeout=5)
|
||||
QApplication.processEvents()
|
||||
if response.status_code == 200:
|
||||
return int(float(xmlet.fromstring(response.text).find('.//e_level').text))
|
||||
ftype = str(f".{file.split('.')[-1]}").lower()
|
||||
label, level = self.pe_scan(file)
|
||||
if label and "Unknown" in label:
|
||||
if self.rule_scan(file):
|
||||
return "Rules"
|
||||
elif label and "White" not in label:
|
||||
if self.json["high_sensitive"]:
|
||||
return label
|
||||
elif level and level >= 1.0:
|
||||
return label
|
||||
elif self.rule_scan(file):
|
||||
return "Rules"
|
||||
elif self.json["high_sensitive"]:
|
||||
if self.rule_scan(file):
|
||||
return "Rules"
|
||||
return False
|
||||
except:
|
||||
return False
|
||||
@@ -876,20 +903,21 @@ class MainWindow_Controller(QMainWindow):
|
||||
def pe_scan(self, file):
|
||||
try:
|
||||
fn = []
|
||||
with pefile.PE(file) as pe:
|
||||
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:
|
||||
try:
|
||||
fn.append(str(func.name, "utf-8"))
|
||||
except:
|
||||
pass
|
||||
QApplication.processEvents()
|
||||
out = self.pe.predict_all(fn)
|
||||
virus = int(out["Virus"]*100)
|
||||
white = int(out["White"]*100)
|
||||
return virus, white
|
||||
if func.name:
|
||||
try:
|
||||
fn.append(str(func.name, "utf-8"))
|
||||
except:
|
||||
pass
|
||||
if fn:
|
||||
QApplication.processEvents()
|
||||
return self.pe.predict(fn)
|
||||
return False, False
|
||||
except:
|
||||
return False
|
||||
return False, False
|
||||
|
||||
def sign_scan(self, file):
|
||||
try:
|
||||
@@ -898,11 +926,21 @@ class MainWindow_Controller(QMainWindow):
|
||||
except:
|
||||
return True
|
||||
|
||||
def rule_scan(self, file):
|
||||
try:
|
||||
with open(file, "rb") as f:
|
||||
data = f.read()
|
||||
for name, rules in self.compiled_rules.items():
|
||||
QApplication.processEvents()
|
||||
if rules.match(data=data):
|
||||
return True
|
||||
return False
|
||||
except:
|
||||
return False
|
||||
|
||||
def proc_scan(self, p):
|
||||
try:
|
||||
if isinstance(p, str) and os.path.exists(p):
|
||||
return self.start_scan(file)
|
||||
for entry in psutil.Process(p.pid).memory_maps():
|
||||
for entry in p.memory_maps():
|
||||
file = entry.path.replace("\\", "/")
|
||||
if ":/Windows" not in file and ":/Program" not in file:
|
||||
if self.start_scan(file):
|
||||
@@ -1012,8 +1050,7 @@ class MainWindow_Controller(QMainWindow):
|
||||
for i in Permission:
|
||||
try:
|
||||
win32api.RegDeleteValue(key,i)
|
||||
file = self.proc.exe().replace("\\", "/")
|
||||
self.kill_process(self.proc, "惡意行為攔截", file)
|
||||
self.kill_process(self.proc, "惡意行為攔截")
|
||||
except:
|
||||
pass
|
||||
win32api.RegCloseKey(key)
|
||||
@@ -1237,6 +1274,7 @@ class MainWindow_Controller(QMainWindow):
|
||||
Thread(target=self.protect_net_thread, daemon=True).start()
|
||||
|
||||
def protect_proc_thread(self):
|
||||
self.proc = None
|
||||
existing_process = set()
|
||||
for p in psutil.process_iter():
|
||||
existing_process.add(p.pid)
|
||||
@@ -1259,54 +1297,64 @@ class MainWindow_Controller(QMainWindow):
|
||||
if file != self.pyas and file not in self.whitelist:
|
||||
self.lock_process(p, True)
|
||||
if "powershell" in name and self.start_scan(cmd[-1].split("'")[-2]):
|
||||
file = cmd[-1].split("'")[-2].replace("\\", "/")
|
||||
self.kill_process(p, "惡意腳本攔截", file)
|
||||
self.kill_process(p, "惡意腳本攔截")
|
||||
elif "cmd.exe" in name and self.start_scan(" ".join(cmd[2:])):
|
||||
file = " ".join(cmd[2:]).replace("\\", "/")
|
||||
self.kill_process(p, "惡意腳本攔截", file)
|
||||
self.kill_process(p, "惡意腳本攔截")
|
||||
elif ":/Windows" in file and self.start_scan(cmd[-1]):
|
||||
file = cmd[-1].replace("\\", "/")
|
||||
self.kill_process(p, "惡意軟體攔截", file)
|
||||
self.kill_process(p, "惡意軟體攔截")
|
||||
elif ":/Windows" not in file and self.proc_scan(p):
|
||||
self.kill_process(p, "惡意軟體攔截", file)
|
||||
self.kill_process(p, "惡意軟體攔截")
|
||||
elif ":/Windows" not in file and self.sign_scan(file):
|
||||
self.proc = p
|
||||
self.lock_process(p, False)
|
||||
gc.collect()
|
||||
except:
|
||||
self.lock_process(p, False)
|
||||
|
||||
def lock_process(self, p, lock):
|
||||
try:
|
||||
if lock:
|
||||
psutil.Process(p.pid).suspend()
|
||||
p.suspend()
|
||||
else:
|
||||
psutil.Process(p.pid).resume()
|
||||
p.resume()
|
||||
except:
|
||||
pass
|
||||
|
||||
def kill_process(self, parent, info, file):
|
||||
def kill_process(self, p, info):
|
||||
try:
|
||||
parent.kill()
|
||||
self.send_notify(self.trans(f"{info}: ")+file)
|
||||
for child in parent.children(recursive=True):
|
||||
child.kill()
|
||||
if p.is_running():
|
||||
file = p.exe().replace("\\", "/")
|
||||
self.send_notify(self.trans(f"{info}: ")+file)
|
||||
for child in p.children(recursive=True):
|
||||
child.kill()
|
||||
p.kill()
|
||||
self.proc = None
|
||||
except:
|
||||
pass
|
||||
|
||||
def protect_file_thread(self):
|
||||
hDir = win32file.CreateFile("C:/",win32con.GENERIC_READ,win32con.FILE_SHARE_READ|win32con.FILE_SHARE_WRITE|win32con.FILE_SHARE_DELETE,None,win32con.OPEN_EXISTING,win32con.FILE_FLAG_BACKUP_SEMANTICS,None)
|
||||
self.ransom_counts = 0
|
||||
while self.file_protect:
|
||||
for action, file in win32file.ReadDirectoryChangesW(hDir,10485760,True,win32con.FILE_NOTIFY_CHANGE_FILE_NAME|win32con.FILE_NOTIFY_CHANGE_DIR_NAME|win32con.FILE_NOTIFY_CHANGE_ATTRIBUTES|win32con.FILE_NOTIFY_CHANGE_SIZE|win32con.FILE_NOTIFY_CHANGE_LAST_WRITE|win32con.FILE_NOTIFY_CHANGE_SECURITY,None,None):
|
||||
try:
|
||||
fpath = str(f"C:/{file}").replace("\\", "/")
|
||||
ftype = str(f".{fpath.split('.')[-1]}").lower()
|
||||
if action == 2 and ":/Users" in fpath and ftype in alist:
|
||||
file = self.proc.exe().replace("\\", "/")
|
||||
if "/AppData/" not in file and ":/Program" not in file:
|
||||
self.kill_process(self.proc, "勒索行為攔截", file)
|
||||
elif action == 3 and ":/Users" in fpath and "/AppData/" not in fpath:
|
||||
if os.path.getsize(fpath) <= 52428800 and ftype in slist:
|
||||
if self.start_scan(fpath):
|
||||
if self.ransom_counts >= 3 and self.proc:
|
||||
self.ransom_counts = 0
|
||||
self.kill_process(self.proc, "勒索行為攔截")
|
||||
elif ":/Windows" in fpath and "/Temp/" not in fpath:
|
||||
if action == 2 and ftype in alist:
|
||||
self.ransom_counts += 1
|
||||
elif action == 4 and ftype in alist:
|
||||
self.ransom_counts += 1
|
||||
elif ":/Users" in fpath and "/AppData/" not in fpath:
|
||||
if action == 2 and ftype in alist:
|
||||
self.ransom_counts += 1
|
||||
elif action == 4 and ftype in alist:
|
||||
self.ransom_counts += 1
|
||||
elif action == 3 and ftype in slist and os.path.getsize(fpath) <= 52428800:
|
||||
if self.sign_scan(file) and self.start_scan(fpath):
|
||||
os.remove(fpath)
|
||||
self.send_notify(self.trans("惡意軟體刪除: ")+fpath)
|
||||
except:
|
||||
@@ -1318,15 +1366,13 @@ class MainWindow_Controller(QMainWindow):
|
||||
time.sleep(0.2)
|
||||
with open(r"\\.\PhysicalDrive0", "r+b") as f:
|
||||
if self.mbr_value[510:512] != b'\x55\xAA':
|
||||
file = self.proc.exe().replace("\\", "/")
|
||||
self.kill_process(self.proc, "惡意行為攔截", file)
|
||||
self.kill_process(self.proc, "惡意行為攔截")
|
||||
elif f.read(512) != self.mbr_value:
|
||||
f.seek(0)
|
||||
f.write(self.mbr_value)
|
||||
file = self.proc.exe().replace("\\", "/")
|
||||
self.kill_process(self.proc, "惡意行為攔截", file)
|
||||
self.kill_process(self.proc, "惡意行為攔截")
|
||||
except:
|
||||
pass
|
||||
self.kill_process(self.proc, "惡意行為攔截")
|
||||
|
||||
def protect_reg_thread(self):
|
||||
while self.reg_protect:
|
||||
@@ -1345,10 +1391,9 @@ class MainWindow_Controller(QMainWindow):
|
||||
time.sleep(0.2)
|
||||
local = socket.gethostbyname(socket.gethostname())
|
||||
for conn in self.proc.connections():
|
||||
file = self.proc.exe().replace("\\", "/")
|
||||
if "/AppData/" not in file and ":/Program" not in file:
|
||||
if ":/Windows" not in file and ":/Program" not in file:
|
||||
if conn.laddr.ip == local:
|
||||
self.kill_process(self.proc, "網路通訊攔截", file)
|
||||
self.kill_process(self.proc, "網路通訊攔截")
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
+7
-7
@@ -35,7 +35,7 @@ class ListSimHash:
|
||||
features = dict(Counter(sorted(content)))
|
||||
for f, w in features.items():
|
||||
count += w
|
||||
batch.append(hashlib.md5(json.dumps(f).encode('utf-8')).digest() * w)
|
||||
batch.append(hashlib.sha256(json.dumps(f).encode('utf-8')).digest() * w)
|
||||
if len(batch) >= 10000:
|
||||
sums.append(self.sum_hashes(batch))
|
||||
batch = []
|
||||
@@ -47,15 +47,15 @@ class ListSimHash:
|
||||
|
||||
def sum_hashes(self, digests):
|
||||
bitarray = numpy.unpackbits(numpy.frombuffer(b''.join(digests), dtype='>B'))
|
||||
return numpy.sum(numpy.reshape(bitarray, (-1, 128)), 0)
|
||||
return numpy.sum(numpy.reshape(bitarray, (-1, 256)), 0)
|
||||
|
||||
def progress_bar(self, iteration, total, prefix='', suffix='', length=50, fill='█'):
|
||||
percent = min(100.0, max(0.0, 100 * (iteration / float(total))))
|
||||
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 * iteration // total)
|
||||
filled_length = int(length * items // total)
|
||||
bar = fill * filled_length + ' ' * (length - filled_length)
|
||||
print(f'\r {prefix: <10} |{bar}| {percent_string}% {suffix}', end=end_char)
|
||||
print(f'\r{prefix: <15} |{bar}| {percent_string}% {suffix}', end=end_char)
|
||||
|
||||
def predict_all(self, query):
|
||||
label_similarities = {}
|
||||
@@ -81,4 +81,4 @@ class ListSimHash:
|
||||
|
||||
def similar(self, x, y):
|
||||
hamming_distance = bin(x ^ y).count('1')
|
||||
return 1 - hamming_distance / 128
|
||||
return 1 - hamming_distance / 256
|
||||
+8
-7
@@ -4,7 +4,7 @@ translate_dict = {
|
||||
"軟體":"软件","檔案":"文件","確定":"确认","設定":"设置","關於":"关于",
|
||||
"錯誤":"错误","實時":"实时","發現":"发现","關閉":"关闭","裝置":"设备",
|
||||
"總數":"总数","註冊":"注册","圖標":"图标","路徑":"路径","網路":"网络",
|
||||
"位元":"字节","彈窗":"弹窗","靈敏":"敏感","誤報":"误报","複製":"复制",
|
||||
"位元":"字节","彈窗":"弹窗","靈敏":"敏感","複製":"复制","誤":"误","報":"报",
|
||||
"訊":"讯","項":"项","掃":"扫","試":"试","黃":"黄","嗎":"吗","防":"保",
|
||||
"鑰":"钥","當":"当","後":"后","護":"护","導":"导","區":"区","復":"复",
|
||||
"攔":"拦","請":"请","統":"统","刪":"删","進":"进","個":"个","選":"选",
|
||||
@@ -15,18 +15,18 @@ translate_dict = {
|
||||
"詢":"询","製":"制","員":"员","許":"许","條":"条","藍":"蓝","紅":"红",
|
||||
"綠":"绿","態":"态","務":"务","連":"连","檢":"检","測":"测","關":"关",
|
||||
"強":"强","驅":"驱","為":"为","腳":"脚","增":"增","單":"单","開":"开",
|
||||
"惡":"恶","據":"据","庫":"库","經":"经","敗":"败"},
|
||||
"惡":"恶","據":"据","庫":"库","經":"经","敗":"败","謝":"谢","別":"别"},
|
||||
"en_US": {"已開啟":"On","已關閉":"Off","已开启":"On","已关闭":"Off",",":", ",
|
||||
"立即刪除":"Delete Now","安全模式":"Safe Mode","官方網站":"Website",
|
||||
"立即刪除":"Delete Now","安全模式":"Safe Mode","官方網站":"Website ",
|
||||
"惡意檔案":"Virus ","惡意軟體":"Malware ","勒索行為":"Ransom ",
|
||||
"惡意腳本":"Script ","惡意行為":"Behavior ","可疑軟體":"Suspicious ",
|
||||
"許可條款":"License Terms","惡意":"Malicious","可疑":"Suspicious",
|
||||
"許可條款":"License Terms ","惡意":"Malicious","可疑":"Suspicious",
|
||||
"啟用":"Enable ","禁用":"Disable ","正在初始化中":"Initializing ",
|
||||
"正在掃描":"Scanning ","正在刪除":"Deleting ","最小化到":"Minimize To ",
|
||||
"確定要":"Sure Want To ","靈敏度":"Sensitivity ","更新":"Update ",
|
||||
"白色主題":"White","黃色主題":"Yellow","紅色主題":"Red","語言":"Language ",
|
||||
"藍色主題":"Blue","綠色主題":"Green","自定主題":"Custom","最新":"Latest ",
|
||||
"測試人員":"Testers","版本資訊":"Information","通訊":"Communication ",
|
||||
"特別感謝":"Contributors ","版本資訊":"Information","通訊":"Communication ",
|
||||
"註冊表":"Registry ","退出":"Quit ","檔案":"File ","當前":"Currently ",
|
||||
"狀態":"State ","掃描":"Scan ","工具":"Tools ","防護":"Protect ",
|
||||
"失敗":"Failed ","請":"Please ","路徑":"Path ","方式":"Method ",
|
||||
@@ -47,8 +47,9 @@ translate_dict = {
|
||||
"增加到":"Add File To ","白名單":"White List ","軟體":"Software ",
|
||||
"增加":"Add","移除":"Delete","項目":"Items ","生成":"Create ","稱":"",
|
||||
"複製":"Copy ","開啟":"Open ","此":"This ","並":"And ","全盤":"Full ",
|
||||
"已經是":"Already ","數據庫":"Database ","誤報":"False Positive ",
|
||||
"已經在":"Already ","數據庫":"Database ","誤報":"False Positive ",
|
||||
"高":"High ","新":"New ","和":"And ","可能會":"Possible ","會":"Can ",
|
||||
"日誌":"Log","已":"Has ","彈窗":"Window ","要":"To ","驅動":"Drive ",
|
||||
"的":"","顯示":"","個":"","嗎":"","中":"","了":"","行":"","立即":"",
|
||||
"密鑰":"Key ","檢測":"Detect ","製作":"Make"," ":" "}}
|
||||
"密鑰":"Key ","檢測":"Detect ","製作":"Maker ","運行":"Running",
|
||||
"自動":"Auto ","上報":"Report ","分析":"Analysis "," ":" "}}
|
||||
@@ -1 +0,0 @@
|
||||
{"Virus": [261318414186602332274638176436767278092, 138027491891768042595443233665640385515, 110357087572968576943094470150101987119, 89628141614819275279501592421270658611, 9625936089192481713091234633207548145, 146573019333239184433892013297795962994, 264541877314875483358485439014616010241, 89378687258170412207570345845754816506, 295491687946453794463476073658069199320, 270110569967616684464025230399867156597, 317767290038007567692141082439138927345, 18885788501897915917239730749935859793, 95067756796967225976055101492886444145, 5340774248576581325353819949912031489, 127221069722257753511418504633757572348, 10415246439899713411029597770193411184, 95651985866123533435079044203969354868, 188173655331549916271106901837471791624, 115920025419090664908814181482465136245, 264555963058906459534362468816145940272, 95651985871075295954016225919772204788, 230418814927598623996991522865620895293, 307822865305226887780395456446154510073, 292376319578571219959135358926367053520, 894545638663197114170691953086909252, 307408049865722049855100904733744729280, 281395069059347277039468499503754758797, 10580035239361434345353152238353587444, 116667039230079911205687280113439840357, 105638824952820428052005376209508641704, 10159525814797641639514752130410024305, 799868415884320332536138129537778698, 22744055344958721368630687581251847176, 255349869106614732679810651086278546442, 315759149185061187179391478424305256898, 95315785306000038407304639293114375376, 110684881900941951709859261701564766961, 145716650028545025053236635988099140033, 95562399119788972561845288789790891122, 222253752239577871278657531622986138289, 94821380653995263056920242811808354032, 105453663146661214242864956330772860016, 133237106118017744142061791759548170883, 106285815540718769887458629487913147505, 171522714730243767599747450471850906780, 201783522381387157888199381457569830339, 95559052534575041823542189821460810608, 6803412338476848613694005563166320666, 105787286451833022929870383496648011249, 106280623246394143467097978838728292593, 94820584548412181705953186602301163257, 95563048166632561463187231032275512432, 108010814655804390841927389574188560953, 173324173206867137081876750353781475864, 95232708608642156662699453866682554993, 106285815540717561551934825217444224113, 95318319972117721345303221798918291186, 95559057605177442847140260259121040241, 305010456281757544171469123445447117681, 106198844586809641198104478887777078384, 179710050855676845982141937253360453053, 94818541689698630943530703193593974512, 105455042350511842344155948214062747248, 20881613063668797611160339818896853168, 31018193447326218505924275935240096368, 143088668467296939342778818474878950647, 110684892675972091428741019788518218489, 137521268273704145345759177480636558327, 106119662154515582210221674170892663408, 105949568716338471638768471668461534962, 89670460543521034706908097860639104624, 10332169700047182535948410013892054257, 95145598865408927095247444731707367024, 100629312664727978741143555078594927795, 148748393343889971317559945312215468786, 93989806751692355346109462915386284256, 107244620726926889373575057027717450762, 94987377598500779420569757831453449840, 100878647073583869926186814218125905113, 20215706740235798874506125693183790832, 110684912958381676190945511157408029425, 105949568706125465724368274041836011250, 300558662558418689647121992472167150144, 106201415362574605111426884001172884597, 110684882592911957008875737340312369917, 94987377577609631169063907051139341428, 105039010693725170460743583068113023705, 114380135952416886874949645426965728392, 124017012583193473160915936873388365506, 94662072863013290725024950240040430327, 143175020845977086618208175741834533027, 132011016412170201801452237305311191441, 10580035240599374384629243014119103732, 105576376886969565715901422869178687219, 172003113737697601641723035082316482624, 109023346904934388839803760995464461049, 10496943991486934504031035936730090609, 127216527016950104546694906326424083058, 336983008266790509743060629130917677774, 10248965448213412269216028810651597936, 79036768232931406417351794113275712068, 105532141803327881065557146349585635569, 100963036754215599502702416838888975610, 105787367661937540200783035652543688177, 95319034907171535697107975830043465952, 95150935027941497330695649661434404081, 31018193447326218505924275935240096368, 176177498613631404614794194516575496896, 136271405179532594000996159423307548914, 66833476002653370931812317778542555093, 9915421242395013439142248483403569396, 162357332045345094604141502928937491106, 95650044561417669529155573147468110960, 95065159985079431125978131216282192112, 18639272732092977493351497242647705306, 230570463661756059397447611038616439025, 95484514342568128463910419849540603504, 266025808443819672030174370144173223456, 47343025305025541868952332865095320248, 100968228555433537808235270915390512872, 105953482575652408268669106292717067508, 95311896151231050439910957073435270256, 105867687984072457600475937752904732400, 116Line truncated
|
||||
+1
-1
@@ -2,7 +2,7 @@ import pyinstaller_versionfile
|
||||
|
||||
pyinstaller_versionfile.create_versionfile(
|
||||
output_file="versionfile.txt",
|
||||
version='3.0.7',
|
||||
version='3.1.3',
|
||||
company_name="PYAS Security",
|
||||
file_description="Python Antivirus Software",
|
||||
internal_name="PYAS",
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
|
||||
## Readme Language
|
||||
|
||||
[繁體中文](https://github.com/zackzheng1121/PYAS/blob/main/README_zh.md)
|
||||
[繁體中文](https://github.com/87owo/PYAS/blob/main/README_zh_TW.md) ,
|
||||
[简体中文](https://github.com/87owo/PYAS/blob/main/README_zh_CN.md)
|
||||
|
||||
## File Information
|
||||
|
||||
@@ -24,6 +25,29 @@ PYAS_Language.py -> Translate Dict (Traditional Chinese, Simplified Chinese, Eng
|
||||
|
||||
PYAS_Version.py -> Pyinstaller Info (file information, version information, original name, etc.)
|
||||
|
||||
## Dir Information
|
||||
|
||||
```
|
||||
PYAS/
|
||||
├── Driver/
|
||||
│ ├── PYAS_Driver.sys
|
||||
│ └── ...
|
||||
│
|
||||
├── Model/
|
||||
│ ├── PYAS_Model.json
|
||||
│ ├── PYAS_Model.txt
|
||||
│ └── ...
|
||||
│
|
||||
├── Rules/
|
||||
│ ├── Yara_Rules.yar
|
||||
│ ├── Compile_Rules.yrc
|
||||
│ └── ...
|
||||
│
|
||||
├── PYAS.py
|
||||
├── PYAS_Engine.py
|
||||
└── ...
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
Use pip install requirements to install import module
|
||||
@@ -37,35 +61,6 @@ pywin32==306
|
||||
PyQt5==5.15.9
|
||||
```
|
||||
|
||||
## Hash Scanning
|
||||
|
||||
Use Qihoo 360 cloud service to scan known malicious files
|
||||
|
||||
```
|
||||
import hashlib, requests
|
||||
import xml.etree.ElementTree as xmlet
|
||||
|
||||
def hash_scan(file):
|
||||
try:
|
||||
with open(file, "rb") as f:
|
||||
text = str(hashlib.md5(f.read()).hexdigest())
|
||||
strBody = f'-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="md5s"\r\n\r\n{text}\r\n-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="format"\r\n\r\nXML\r\n-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="product"\r\n\r\n360zip\r\n-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="combo"\r\n\r\n360zip_main\r\n-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="v"\r\n\r\n2\r\n-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="osver"\r\n\r\n5.1\r\n-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="vk"\r\n\r\na03bc211\r\n-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="mid"\r\n\r\n8a40d9eff408a78fe9ec10a0e7e60f62\r\n-------------------------------7d83e2d7a141e--'
|
||||
response = requests.post('http://qup.f.360.cn/file_health_info.php', data=strBody, timeout=3)
|
||||
if response.status_code == 200:
|
||||
level = float(xmlet.fromstring(response.text).find('.//e_level').text)
|
||||
if level > 50:
|
||||
return "Virus"
|
||||
elif level <= 10:
|
||||
return "Safe"
|
||||
return "Unknown"
|
||||
return f"Error: {response.status_code}"
|
||||
except Exception as e:
|
||||
return f"Error: {e}"
|
||||
|
||||
info = hash_scan("path to file")
|
||||
print(info)
|
||||
```
|
||||
|
||||
## Pefile Scanning
|
||||
|
||||
Get the pefile file function import table for scanning
|
||||
@@ -102,25 +97,25 @@ Show the new process name, file path, cmd line, pid
|
||||
import psutil, time
|
||||
|
||||
def proc_detect():
|
||||
existing_processes = set()
|
||||
existing_process = set()
|
||||
for p in psutil.process_iter():
|
||||
if p.pid not in existing_processes:
|
||||
existing_processes.add(p.pid)
|
||||
existing_process.add(p.pid)
|
||||
while True:
|
||||
time.sleep(0.1)
|
||||
new_process = set()
|
||||
for p in psutil.process_iter():
|
||||
new_process.add(p.pid)
|
||||
for pid in new_process - existing_process:
|
||||
try:
|
||||
if p.pid not in existing_processes:
|
||||
existing_processes.add(p.pid)
|
||||
name, file, cmd = p.name(), p.exe(), p.cmdline()
|
||||
print(f"Name: {name}")
|
||||
print(f"File: {file}")
|
||||
print(f"Pid: {p.pid}")
|
||||
print(f"Cmd: {cmd}")
|
||||
elif not psutil.pid_exists(p.pid):
|
||||
existing_processes.remove(p.pid)
|
||||
except:
|
||||
pass
|
||||
p = psutil.Process(pid)
|
||||
name, file, cmd = p.name(), p.exe(), p.cmdline()
|
||||
print(f"Name: {name}")
|
||||
print(f"File: {file}")
|
||||
print(f"Pid: {p.pid}")
|
||||
print(f"Cmd: {cmd}")
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
existing_process = new_process
|
||||
|
||||
proc_detect()
|
||||
```
|
||||
@@ -160,17 +155,22 @@ https://pyantivirus.wixsite.com/pyas
|
||||
|
||||
https://github.com/87owo/PYAS
|
||||
|
||||
## PYAS Driver
|
||||
|
||||
https://github.com/0sha0/PYAS_Protection
|
||||
|
||||
## MIT license
|
||||
|
||||
https://github.com/87owo/PYAS/blob/main/LICENSE.md
|
||||
|
||||
## Support System
|
||||
|
||||
Windows 8.1, 10, 11 (64-bit), Ram 1GB, Rom 1GB or higher
|
||||
Windows 8.1, 10, 11 (64-bit), Ram 500MB, Rom 200MB or higher
|
||||
|
||||
Other systems may experience software malfunctions or crash
|
||||
|
||||
## Special Thanks
|
||||
360, Wix, VirusShare, mtkiao129, AV-T Team of LisectGroup
|
||||
|
||||
Wix, 0sha0, mtkiao129, AV-T Team of LisectGroup
|
||||
|
||||
Copyright© 2020~2024 PYAS Security By 87owo
|
||||
+171
@@ -0,0 +1,171 @@
|
||||
# PYAS (Python 杀毒软件)
|
||||
|
||||

|
||||
|
||||
## 文件信息
|
||||
|
||||
PYAS.py -> PYAS主程式(包括动画、扫描、保护功能等)
|
||||
|
||||
PYAS_Engine.py -> 转换资料库(用于相互转换资料库字典和清单)
|
||||
|
||||
PYAS_Extension.py -> 副文件名(包括扫描文件副文件名和常用副文件名)
|
||||
|
||||
PYAS_Model.* -> 病毒库(病毒库必须放在同一目录下)
|
||||
|
||||
PYAS_Interface.py -> PyQt5界面(由QT设计师设计,必须与主程式相符)
|
||||
|
||||
PYAS_Resource.py -> PyQt5资源(状态图片、图示包、按钮图示等)
|
||||
|
||||
PYAS_Language.py -> 翻译字典(繁体中文、简体中文、英文)
|
||||
|
||||
PYAS_Version.py -> Pyinstaller资讯(文件资讯、版本资讯、原名等)
|
||||
|
||||
## 目录信息
|
||||
|
||||
```
|
||||
PYAS/
|
||||
├── Driver/
|
||||
│ ├── PYAS_Driver.sys
|
||||
│ └── ...
|
||||
│
|
||||
├── Model/
|
||||
│ ├── PYAS_Model.json
|
||||
│ ├── PYAS_Model.txt
|
||||
│ └── ...
|
||||
│
|
||||
├── Rules/
|
||||
│ ├── Yara_Rules.yar
|
||||
│ ├── Compile_Rules.yrc
|
||||
│ └── ...
|
||||
│
|
||||
├── PYAS.py
|
||||
├── PYAS_Engine.py
|
||||
└── ...
|
||||
```
|
||||
|
||||
## 安装要求
|
||||
|
||||
使用 pip install requirements 来安装需要的模组
|
||||
|
||||
```
|
||||
psutil==5.9.5
|
||||
pefile==2023.2.7
|
||||
requests==2.31.0
|
||||
pyperclip==1.8.2
|
||||
pywin32==306
|
||||
PyQt5==5.15.9
|
||||
```
|
||||
|
||||
## 文件扫描
|
||||
|
||||
取得pefile文件函数导入表进行扫描
|
||||
|
||||
```
|
||||
import pefile
|
||||
|
||||
def pe_scan(file):
|
||||
try:
|
||||
fn = []
|
||||
with pefile.PE(file) as pe:
|
||||
for entry in pe.DIRECTORY_ENTRY_IMPORT:
|
||||
for func in entry.imports:
|
||||
try:
|
||||
fn.append(str(func.name, "utf-8"))
|
||||
except:
|
||||
pass
|
||||
if fn in known_malicious_list:
|
||||
return "Virus"
|
||||
return "Safe"
|
||||
return "Unknown"
|
||||
except Exception as e:
|
||||
return f"Error: {e}"
|
||||
|
||||
info = pe_scan("path to file")
|
||||
print(info)
|
||||
```
|
||||
|
||||
## 进程监控
|
||||
|
||||
显示新进程名称、文件路径、cmd 行、pid
|
||||
|
||||
```
|
||||
import psutil, time
|
||||
|
||||
def proc_detect():
|
||||
existing_process = set()
|
||||
for p in psutil.process_iter():
|
||||
existing_process.add(p.pid)
|
||||
while True:
|
||||
time.sleep(0.1)
|
||||
new_process = set()
|
||||
for p in psutil.process_iter():
|
||||
new_process.add(p.pid)
|
||||
for pid in new_process - existing_process:
|
||||
try:
|
||||
p = psutil.Process(pid)
|
||||
name, file, cmd = p.name(), p.exe(), p.cmdline()
|
||||
print(f"Name: {name}")
|
||||
print(f"File: {file}")
|
||||
print(f"Pid: {p.pid}")
|
||||
print(f"Cmd: {cmd}")
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
existing_process = new_process
|
||||
|
||||
proc_detect()
|
||||
```
|
||||
|
||||
## 文件监控
|
||||
|
||||
监控指定路径下的文件变化
|
||||
|
||||
```
|
||||
import os, win32file, win32con
|
||||
|
||||
def file_detect(path):
|
||||
hDir = win32file.CreateFile(path,win32con.GENERIC_READ,win32con.FILE_SHARE_READ|win32con.FILE_SHARE_WRITE|win32con.FILE_SHARE_DELETE,None,win32con.OPEN_EXISTING,win32con.FILE_FLAG_BACKUP_SEMANTICS,None)
|
||||
while True:
|
||||
for action, file in win32file.ReadDirectoryChangesW(hDir,10485760,True,win32con.FILE_NOTIFY_CHANGE_FILE_NAME|win32con.FILE_NOTIFY_CHANGE_DIR_NAME|win32con.FILE_NOTIFY_CHANGE_ATTRIBUTES|win32con.FILE_NOTIFY_CHANGE_SIZE|win32con.FILE_NOTIFY_CHANGE_LAST_WRITE|win32con.FILE_NOTIFY_CHANGE_SECURITY,None,None):
|
||||
try:
|
||||
fpath = os.path.join(path, file)
|
||||
if action == 1:
|
||||
print(f"File Create: {fpath}")
|
||||
elif action == 2:
|
||||
print(f"File Delete: {fpath}")
|
||||
elif action == 3:
|
||||
print(f"File Modify: {fpath}")
|
||||
elif action == 4:
|
||||
print(f"File Rename: {fpath}")
|
||||
elif action == 5:
|
||||
print(f"File Rename: {fpath}")
|
||||
except:
|
||||
pass
|
||||
|
||||
file_detect("path")
|
||||
```
|
||||
|
||||
## 官方网页
|
||||
|
||||
https://pyantivirus.wixsite.com/pyas
|
||||
|
||||
https://github.com/87owo/PYAS
|
||||
|
||||
## 开源协议
|
||||
|
||||
https://github.com/87owo/PYAS/blob/main/LICENSE.md
|
||||
|
||||
## 驱动程序
|
||||
|
||||
https://github.com/0sha0/PYAS_Protection
|
||||
|
||||
## 支援系统
|
||||
|
||||
Windows 8.1, 10, 11 (64-bit), 内存 500MB, 存储 200MB 或更高
|
||||
|
||||
其他系统或版本可能会遇到软体功能故障或程序崩溃
|
||||
|
||||
## 特别感谢
|
||||
|
||||
360, Wix, VirusShare, mtkiao129, AV-T Team of LisectGroup
|
||||
|
||||
Copyright© 2020~2024 PYAS Security By 87owo
|
||||
@@ -1,8 +1,8 @@
|
||||
# PYAS (Python 防毒軟體)
|
||||
|
||||

|
||||

|
||||
|
||||
## 文件訊息
|
||||
## 檔案資訊
|
||||
|
||||
PYAS.py -> PYAS主程式(包括動畫、掃描、保護功能等)
|
||||
|
||||
@@ -20,7 +20,30 @@ PYAS_Language.py -> 翻譯字典(繁體中文、簡體中文、英文)
|
||||
|
||||
PYAS_Version.py -> Pyinstaller Info(檔案資訊、版本資訊、原名等)
|
||||
|
||||
## 要求
|
||||
## 目錄資訊
|
||||
|
||||
```
|
||||
PYAS/
|
||||
├── Driver/
|
||||
│ ├── PYAS_Driver.sys
|
||||
│ └── ...
|
||||
│
|
||||
├── Model/
|
||||
│ ├── PYAS_Model.json
|
||||
│ ├── PYAS_Model.txt
|
||||
│ └── ...
|
||||
│
|
||||
├── Rules/
|
||||
│ ├── Yara_Rules.yar
|
||||
│ ├── Compile_Rules.yrc
|
||||
│ └── ...
|
||||
│
|
||||
├── PYAS.py
|
||||
├── PYAS_Engine.py
|
||||
└── ...
|
||||
```
|
||||
|
||||
## 安裝要求
|
||||
|
||||
使用 pip install requirements 來安裝需要的模組
|
||||
|
||||
@@ -33,36 +56,7 @@ pywin32==306
|
||||
PyQt5==5.15.9
|
||||
```
|
||||
|
||||
## 哈希掃描
|
||||
|
||||
使用奇虎360雲端服務掃描已知惡意文件
|
||||
|
||||
```
|
||||
import hashlib, requests
|
||||
import xml.etree.ElementTree as xmlet
|
||||
|
||||
def hash_scan(file):
|
||||
try:
|
||||
with open(file, "rb") as f:
|
||||
text = str(hashlib.md5(f.read()).hexdigest())
|
||||
strBody = f'-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="md5s"\r\n\r\n{text}\r\n-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="format"\r\n\r\nXML\r\n-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="product"\r\n\r\n360zip\r\n-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="combo"\r\n\r\n360zip_main\r\n-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="v"\r\n\r\n2\r\n-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="osver"\r\n\r\n5.1\r\n-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="vk"\r\n\r\na03bc211\r\n-------------------------------7d83e2d7a141e\r\nContent-Disposition: form-data; name="mid"\r\n\r\n8a40d9eff408a78fe9ec10a0e7e60f62\r\n-------------------------------7d83e2d7a141e--'
|
||||
response = requests.post('http://qup.f.360.cn/file_health_info.php', data=strBody, timeout=3)
|
||||
if response.status_code == 200:
|
||||
level = float(xmlet.fromstring(response.text).find('.//e_level').text)
|
||||
if level > 50:
|
||||
return "Virus"
|
||||
elif level <= 10:
|
||||
return "Safe"
|
||||
return "Unknown"
|
||||
return f"Error: {response.status_code}"
|
||||
except Exception as e:
|
||||
return f"Error: {e}"
|
||||
|
||||
info = hash_scan("path to file")
|
||||
print(info)
|
||||
```
|
||||
|
||||
## 文件掃描
|
||||
## 檔案掃描
|
||||
|
||||
取得pefile檔案函數導入表進行掃描
|
||||
|
||||
@@ -90,35 +84,37 @@ info = pe_scan("path to file")
|
||||
print(info)
|
||||
```
|
||||
|
||||
## 進程偵測
|
||||
## 進程監控
|
||||
|
||||
顯示新進程名稱、檔案路徑、cmd 行、pid
|
||||
```
|
||||
import psutil, time
|
||||
|
||||
def proc_detect():
|
||||
existing_processes = set()
|
||||
existing_process = set()
|
||||
for p in psutil.process_iter():
|
||||
if p.pid not in existing_processes:
|
||||
existing_processes.add(p.pid)
|
||||
existing_process.add(p.pid)
|
||||
while True:
|
||||
time.sleep(0.1)
|
||||
new_process = set()
|
||||
for p in psutil.process_iter():
|
||||
new_process.add(p.pid)
|
||||
for pid in new_process - existing_process:
|
||||
try:
|
||||
if p.pid not in existing_processes:
|
||||
existing_processes.add(p.pid)
|
||||
name, file, cmd = p.name(), p.exe(), p.cmdline()
|
||||
print(f"Name: {name}")
|
||||
print(f"File: {file}")
|
||||
print(f"Pid: {p.pid}")
|
||||
print(f"Cmd: {cmd}")
|
||||
except:
|
||||
pass
|
||||
p = psutil.Process(pid)
|
||||
name, file, cmd = p.name(), p.exe(), p.cmdline()
|
||||
print(f"Name: {name}")
|
||||
print(f"File: {file}")
|
||||
print(f"Pid: {p.pid}")
|
||||
print(f"Cmd: {cmd}")
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
existing_process = new_process
|
||||
|
||||
proc_detect()
|
||||
```
|
||||
|
||||
## 檔案偵測
|
||||
## 檔案監控
|
||||
|
||||
監控指定路徑下的檔案變化
|
||||
```
|
||||
@@ -152,16 +148,22 @@ https://pyantivirus.wixsite.com/pyas
|
||||
|
||||
https://github.com/87owo/PYAS
|
||||
|
||||
## 開源許可證
|
||||
## 開源協議
|
||||
|
||||
https://github.com/87owo/PYAS/blob/main/LICENSE.md
|
||||
|
||||
## 支援的系統
|
||||
## 驅動程式
|
||||
|
||||
Windows 8.1, 10, 11 (64-bit),記憶體 1GB, 磁碟容量 1GB 或更高
|
||||
Other systems may experience software malfunctions or crash
|
||||
https://github.com/0sha0/PYAS_Protection
|
||||
|
||||
## Special Thanks
|
||||
360, Wix, VirusShare, mtkiao129, AV-T Team of LisectGroup
|
||||
## 支援系統
|
||||
|
||||
Windows 8.1, 10, 11 (64-bit),記憶體 500MB, 磁碟容量 200MB 或更高
|
||||
|
||||
其他系統或版本可能會遇到軟體功能故障或程序崩潰
|
||||
|
||||
## 特別感謝
|
||||
|
||||
Wix, 0sha0, mtkiao129, AV-T Team of LisectGroup
|
||||
|
||||
Copyright© 2020~2024 PYAS Security By 87owo
|
||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user