Compare commits

..
17 Commits
Author SHA1 Message Date
87owo 05e952c5ee Add files via upload 2026-09-04 13:11:56 +08:00
87owo 8a0209a99a Add files via upload 2026-09-04 13:10:39 +08:00
87owo 65bc5c7c2a Add files via upload 2026-09-04 09:20:51 +08:00
87owo 07c64042be Add files via upload 2026-08-24 22:39:54 +08:00
87owo 22c04063cf Add files via upload 2026-08-23 10:33:53 +08:00
87owo 68a7ab657a Update README.md 2026-08-21 16:33:16 +08:00
87owo 630dc67058 Add files via upload 2026-08-21 14:19:12 +08:00
87owo 591507512c Delete Plugins/Rules/Report.json 2026-08-21 13:33:13 +08:00
87owo ff49cafc74 Add files via upload 2026-08-21 13:32:08 +08:00
87owo b077ba06bd Add files via upload 2026-08-19 17:20:02 +08:00
87owo a2b66aec64 Add files via upload 2026-08-14 12:43:24 +08:00
87owo 4b692b0c87 Add files via upload 2026-08-11 13:17:24 +08:00
87owo 99d1b20d0f Add files via upload 2026-08-09 19:52:15 +08:00
87owo fae5edb57b Add files via upload 2026-08-09 19:50:38 +08:00
87owo 6db91483a0 Add files via upload 2026-08-09 19:36:22 +08:00
87owo 90383f3d09 Add files via upload 2026-08-04 22:31:09 +08:00
87owo 966a5a3592 Add files via upload 2026-08-04 22:29:20 +08:00
8 changed files with 477 additions and 135 deletions

No files matched your search

+1 -1
View File
@@ -191,7 +191,7 @@ def train_process(X, y, feature_names):
n_neg = (y_train == 0).sum()
base_weight = n_neg / n_pos if n_pos > 0 else 1.0
weight_ratio_target = 0.005
weight_ratio_target = 0.01
final_pos_weight = base_weight * weight_ratio_target
print(f"[*] Sample distribution: Safe={n_neg}, Malware={n_pos}")
+29 -6
View File
@@ -366,7 +366,7 @@ class _MainMixin:
self.lock_io = threading.RLock()
self.pyas_default = {
"version": "3.6.6",
"version": "3.6.9",
"api_host": "https://pyas-security.com/",
"api_key": "fBRZxYS1UxykM-qzNOlKOEl63WILzlvgNMn6QfsG6FXCAAIktCrOPTAfY5_hEyuZ",
"suffix": [".exe", ".dll", ".sys", ".ocx", ".scr", ".efi", ".acm", ".ax", ".cpl", ".drv", ".com", ".mui", ".pyd", ".wfx", ".api", ".awx", ".rll", ".winmd"],
@@ -461,6 +461,18 @@ class _MainMixin:
self.pyas_config.update(data)
self.pyas_config["version"] = self.pyas_default["version"]
whitelist_metadata_updated = False
for item in self.pyas_config.get("white_list", []):
if not isinstance(item, dict) or not item.get("file") or "is_dir" in item:
continue
item_path = self.norm_path(item["file"], must_exist=False)
if item_path and os.path.exists(item_path):
item["is_dir"] = os.path.isdir(item_path)
whitelist_metadata_updated = True
if whitelist_metadata_updated:
self.save_config()
except Exception as e:
self.pyas_config = copy.deepcopy(self.pyas_default)
self.write_log("WARN", "load_config", detail=str(e), success=False)
@@ -513,7 +525,7 @@ class _MainMixin:
elif key == "context_switch":
self.register_context_menu(True)
elif key == "autostart_switch":
self.manage_autostart(True)
success = self.manage_autostart(True)
except Exception as e:
self.write_log("WARN", "Feature Start", detail=str(e), success=False)
@@ -525,7 +537,7 @@ class _MainMixin:
elif key == "context_switch":
self.register_context_menu(False)
elif key == "autostart_switch":
self.manage_autostart(False)
success = self.manage_autostart(False)
elif key == "document_switch":
self._cancel_pending_file_scans()
@@ -1110,9 +1122,17 @@ class _MainMixin:
elif full_path.startswith("HKCC"):
full_path = full_path.replace("HKCC", "HKEY_CURRENT_CONFIG", 1)
subprocess.run(["taskkill", "/F", "/IM", "regedit.exe"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, creationflags=0x08000000)
self._run_windows_tool(
("taskkill.exe",),
["/F", "/IM", "regedit.exe"],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL
)
self._reg_write(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Applets\Regedit", "LastKey", winreg.REG_SZ, full_path)
subprocess.Popen("regedit.exe")
regedit = self._find_windows_tool("regedit.exe")
if not regedit:
return False
subprocess.Popen([regedit])
return True
except Exception:
@@ -1122,7 +1142,10 @@ class _MainMixin:
if os.path.exists(expanded_path):
try:
clean_path = os.path.normpath(expanded_path)
subprocess.Popen(f'explorer /select,"{clean_path}"')
explorer = self._find_windows_tool("explorer.exe")
if not explorer:
return False
subprocess.Popen([explorer, "/select,", clean_path])
return True
except Exception:
+34 -58
View File
@@ -1,6 +1,6 @@
#define AppId "{{a7d7bac3-93b8-4630-8308-c7a56bf7fdf4}"
#define AppName "PYAS"
#define AppVersion "3.6.5.0"
#define AppVersion "3.6.9.0"
#define AppPublisher "PYAS Security"
#define AppURL "https://github.com/87owo/PYAS"
#define AppExeName "PYAS.exe"
@@ -52,9 +52,8 @@ Name: "arabic"; MessagesFile: "SetupResources\Arabic.isl"
Name: "russian"; MessagesFile: "SetupResources\Russian.isl"
Name: "slovenian"; MessagesFile: "SetupResources\Slovenian.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"
Name: "autostart"; Description: "{cm:AutoStartTask}"; GroupDescription: "{cm:AdditionalIcons}"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"
[Files]
Source: "Redist\VC_redist.x64.exe"; DestDir: "{tmp}\PYAS_Redist"; Flags: deleteafterinstall ignoreversion; AfterInstall: EnsureVCRedist
@@ -65,9 +64,10 @@ Source: "Payload\License\*"; DestDir: "{app}\License"; Flags: ignoreversion recu
Source: "Payload\PYAS.exe"; DestDir: "{app}"; Flags: ignoreversion; AfterInstall: FinalizeDriverRemoval
Source: "Payload\Plugins\*"; DestDir: "{app}\Plugins"; Flags: ignoreversion recursesubdirs createallsubdirs
[Registry]
Root: HKCU; Subkey: "Software\Classes\*\shell\PYAS_Scan"; Flags: uninsdeletekey dontcreatekey
Root: HKCU; Subkey: "Software\Classes\Directory\shell\PYAS_Scan"; Flags: uninsdeletekey dontcreatekey
[Registry]
Root: HKCU; Subkey: "Software\Classes\*\shell\PYAS_Scan"; Flags: uninsdeletekey dontcreatekey
Root: HKCU; Subkey: "Software\Classes\Directory\shell\PYAS_Scan"; Flags: uninsdeletekey dontcreatekey
Root: HKCU; Subkey: "Software\Microsoft\Windows\CurrentVersion\Run"; ValueName: "PYAS_Security"; Flags: uninsdeletevalue dontcreatekey
[UninstallDelete]
Type: filesandordirs; Name: "{commonappdata}\PYAS"
@@ -87,9 +87,6 @@ chinesetraditional.InstallingVCRuntime=正在安裝 Microsoft Visual C++ 執行
english.InstallingWebView2Runtime=Installing Microsoft Edge WebView2 Runtime...
chinesesimplified.InstallingWebView2Runtime=正在安装 Microsoft Edge WebView2 Runtime...
chinesetraditional.InstallingWebView2Runtime=正在安裝 Microsoft Edge WebView2 Runtime...
english.AutoStartTask=Run PYAS automatically at system startup
chinesesimplified.AutoStartTask=开机时自动运行 PYAS
chinesetraditional.AutoStartTask=開機時自動執行 PYAS
english.Dependencies=Dependencies:
chinesesimplified.Dependencies=运行环境:
chinesetraditional.Dependencies=執行環境:
@@ -277,63 +274,42 @@ function NeedRestart: Boolean;
begin
Result := DependencyRestartRequired;
end;
procedure TryCreateStartupTask;
var
ResultCode: Integer;
PSExe: string;
PSCommand: string;
AppPath: string;
begin
AppPath := ExpandConstant('{app}\{#AppExeName}');
PSExe := ExpandConstant('{sys}\WindowsPowerShell\v1.0\powershell.exe');
PSCommand := '-NoProfile -NonInteractive -ExecutionPolicy Bypass -WindowStyle Hidden -Command ' +
'$Action = New-ScheduledTaskAction -Execute ''' + AppPath + ''' -Argument ''-hide''; ' +
'$Trigger = New-ScheduledTaskTrigger -AtLogOn; ' +
'$Settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries; ' +
'Register-ScheduledTask -TaskName ''PYAS_Security_ATS'' -Action $Action -Trigger $Trigger -Settings $Settings -RunLevel Highest -Force';
if not Exec(PSExe, PSCommand, '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then
begin
Log(Format('Failed to create scheduled task, Exec error code: %d', [ResultCode]));
end
else if ResultCode <> 0 then
begin
Log(Format('powershell returned exit code %d while creating the scheduled task', [ResultCode]));
end;
end;
procedure TryDeleteStartupTask;
var
ResultCode: Integer;
begin
if not Exec(ExpandConstant('{sys}\schtasks.exe'), '/Delete /TN "PYAS_Security_ATS" /F', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then
begin
Log(Format('Failed to delete scheduled task, Exec error code: %d', [ResultCode]));
end
else if ResultCode <> 0 then
begin
Log(Format('schtasks returned exit code %d while deleting the scheduled task', [ResultCode]));
end;
end;
procedure RemoveLegacyStartupTask;
var
TaskService: Variant;
RootFolder: Variant;
begin
try
TaskService := CreateOleObject('Schedule.Service');
TaskService.Connect();
RootFolder := TaskService.GetFolder('\');
try
RootFolder.DeleteTask('PYAS_Security_ATS', 0);
Log('Removed legacy PYAS scheduled startup task');
except
Log('Legacy PYAS scheduled startup task was not present or could not be removed');
end;
except
Log('Task Scheduler COM was unavailable while cleaning the legacy startup task');
end;
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssPostInstall then
begin
if WizardIsTaskSelected('autostart') then
begin
TryCreateStartupTask;
end;
end;
if CurStep = ssPostInstall then
begin
RemoveLegacyStartupTask;
end;
end;
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
if CurUninstallStep = usUninstall then
begin
TryDeleteStartupTask;
if CurUninstallStep = usUninstall then
begin
RemoveLegacyStartupTask;
end
else if CurUninstallStep = usPostUninstall then
begin
DelTree(ExpandConstant('{app}'), True, True, True);
end;
end;
end;
+42 -17
View File
@@ -82,26 +82,49 @@ class ProtectMixin:
def init_whitelist(self):
self.manage_named_list("white_list", [self.file_pyas], action="add")
def sync_driver_whitelist(self, file_path, is_add=True):
def _driver_whitelist_patterns(self, file_path, is_directory=None):
normalized_path = self.norm_path(file_path, must_exist=False)
if not normalized_path:
return []
if is_directory is None:
is_directory = os.path.isdir(normalized_path)
drive_letter = os.path.splitdrive(normalized_path)[0]
driver_path = "*" + normalized_path[len(drive_letter):] if drive_letter else normalized_path
patterns = [driver_path]
if is_directory:
descendant_pattern = driver_path.rstrip("\\/") + "\\*"
if descendant_pattern not in patterns:
patterns.append(descendant_pattern)
return patterns
def sync_driver_whitelist(self, file_path, is_add=True, is_directory=None):
with self.lock_driver:
if not self.driver_port:
return False
driver_path = str(file_path)
drive_letter = os.path.splitdrive(driver_path)[0]
if drive_letter:
driver_path = "*" + driver_path[len(drive_letter):]
msg = PYAS_USER_MESSAGE()
msg.Command = 1 if is_add else 2
msg.Path = driver_path
bytes_returned = ctypes.wintypes.DWORD(0)
try:
return self.fltlib.FilterSendMessage(self.driver_port, ctypes.byref(msg), ctypes.sizeof(msg), None, 0, ctypes.byref(bytes_returned)) == 0
except Exception:
patterns = self._driver_whitelist_patterns(file_path, is_directory)
if not patterns:
return False
success = True
for driver_path in patterns:
msg = PYAS_USER_MESSAGE()
msg.Command = 1 if is_add else 2
bytes_returned = ctypes.wintypes.DWORD(0)
try:
msg.Path = driver_path
if self.fltlib.FilterSendMessage(self.driver_port, ctypes.byref(msg), ctypes.sizeof(msg), None, 0, ctypes.byref(bytes_returned)) != 0:
success = False
except Exception:
success = False
return success
####################################################################################################
def _try_lock_file(self, file_path):
@@ -891,7 +914,10 @@ class ProtectMixin:
running = any(exe_name.lower() == "explorer.exe" for _, exe_name in self._enum_processes())
if not running:
subprocess.Popen("explorer.exe", shell=True)
explorer = self._find_windows_tool("explorer.exe")
if not explorer:
return
subprocess.Popen([explorer])
self.write_log("INFO", "System Restart", source="explorer.exe")
except Exception:
@@ -1905,7 +1931,7 @@ class ProtectMixin:
if self.driver_stop_event.is_set():
break
if isinstance(item, dict) and item.get("file"):
self.sync_driver_whitelist(item["file"], True)
self.sync_driver_whitelist(item["file"], True, item.get("is_dir"))
if self.driver_stop_event.is_set():
break
@@ -1972,4 +1998,3 @@ class ProtectMixin:
with self.lock_driver:
if self.driver_listener_thread is threading.current_thread():
self.driver_listener_thread = None
+336 -43
View File
@@ -1,4 +1,4 @@
import os, re, io, csv, time, shutil, threading
import os, re, io, csv, json, time, shutil, threading
import pefile, hashlib, winreg, requests, subprocess
import ctypes, ctypes.wintypes
@@ -167,6 +167,186 @@ class RECT(ctypes.Structure):
####################################################################################################
class ToolsMixin:
def _find_windows_tool(self, *names):
windows_dir = os.environ.get("SystemRoot") or os.environ.get("WINDIR") or r"C:\Windows"
search_dirs = [
os.path.join(windows_dir, "Sysnative"),
os.path.join(windows_dir, "System32"),
windows_dir
]
for name in names:
executable_name = name if name.lower().endswith(".exe") else name + ".exe"
for directory in search_dirs:
candidate = os.path.join(directory, executable_name)
if os.path.isfile(candidate):
return candidate
candidate = shutil.which(name)
if candidate:
return candidate
return None
def _run_windows_tool(self, tool_names, arguments, **kwargs):
executable = self._find_windows_tool(*tool_names)
if not executable:
return None
options = {"creationflags": 0x08000000}
options.update(kwargs)
try:
return subprocess.run([executable, *arguments], **options)
except (FileNotFoundError, OSError):
return None
def _run_powershell(self, command, **kwargs):
return self._run_windows_tool(
("powershell.exe", "pwsh.exe"),
["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-WindowStyle", "Hidden", "-Command", command],
**kwargs
)
def _set_registry_autostart(self, enable):
run_key = r"Software\Microsoft\Windows\CurrentVersion\Run"
value_name = "PYAS_Security"
if enable:
command = f'"{self.file_pyas}" -hide'
return self._reg_write(winreg.HKEY_CURRENT_USER, run_key, value_name, winreg.REG_SZ, command)
try:
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, run_key, 0, winreg.KEY_SET_VALUE) as reg:
try:
winreg.DeleteValue(reg, value_name)
except FileNotFoundError:
pass
return True
except FileNotFoundError:
return True
except Exception:
return False
def _clear_event_log(self, log_name):
result = self._run_windows_tool(
("wevtutil.exe",),
["cl", log_name],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL
)
if result is not None and result.returncode == 0:
return True
try:
wevtapi = ctypes.WinDLL("wevtapi", use_last_error=True)
wevtapi.EvtClearLog.argtypes = [ctypes.wintypes.HANDLE, ctypes.wintypes.LPCWSTR, ctypes.wintypes.LPCWSTR, ctypes.wintypes.DWORD]
wevtapi.EvtClearLog.restype = ctypes.wintypes.BOOL
return bool(wevtapi.EvtClearLog(None, log_name, None, 0))
except Exception:
return False
def _manage_service_native(self, service_name, action):
SC_MANAGER_CONNECT = 0x0001
SERVICE_CHANGE_CONFIG = 0x0002
DELETE = 0x00010000
SERVICE_NO_CHANGE = 0xFFFFFFFF
SERVICE_AUTO_START = 0x00000002
SERVICE_DISABLED = 0x00000004
try:
advapi32 = ctypes.WinDLL("advapi32", use_last_error=True)
advapi32.OpenSCManagerW.argtypes = [ctypes.wintypes.LPCWSTR, ctypes.wintypes.LPCWSTR, ctypes.wintypes.DWORD]
advapi32.OpenSCManagerW.restype = ctypes.wintypes.HANDLE
advapi32.OpenServiceW.argtypes = [ctypes.wintypes.HANDLE, ctypes.wintypes.LPCWSTR, ctypes.wintypes.DWORD]
advapi32.OpenServiceW.restype = ctypes.wintypes.HANDLE
advapi32.CloseServiceHandle.argtypes = [ctypes.wintypes.HANDLE]
advapi32.CloseServiceHandle.restype = ctypes.wintypes.BOOL
manager = advapi32.OpenSCManagerW(None, None, SC_MANAGER_CONNECT)
if not manager:
return False
service = None
try:
desired_access = DELETE if action == "delete" else SERVICE_CHANGE_CONFIG
service = advapi32.OpenServiceW(manager, service_name, desired_access)
if not service:
return False
if action == "delete":
advapi32.DeleteService.argtypes = [ctypes.wintypes.HANDLE]
advapi32.DeleteService.restype = ctypes.wintypes.BOOL
return bool(advapi32.DeleteService(service))
start_type = SERVICE_AUTO_START if action == "enable" else SERVICE_DISABLED
advapi32.ChangeServiceConfigW.argtypes = [
ctypes.wintypes.HANDLE,
ctypes.wintypes.DWORD,
ctypes.wintypes.DWORD,
ctypes.wintypes.DWORD,
ctypes.wintypes.LPCWSTR,
ctypes.wintypes.LPCWSTR,
ctypes.POINTER(ctypes.wintypes.DWORD),
ctypes.wintypes.LPCWSTR,
ctypes.wintypes.LPCWSTR,
ctypes.wintypes.LPCWSTR,
ctypes.wintypes.LPCWSTR
]
advapi32.ChangeServiceConfigW.restype = ctypes.wintypes.BOOL
return bool(advapi32.ChangeServiceConfigW(
service,
SERVICE_NO_CHANGE,
start_type,
SERVICE_NO_CHANGE,
None,
None,
None,
None,
None,
None,
None
))
finally:
if service:
advapi32.CloseServiceHandle(service)
advapi32.CloseServiceHandle(manager)
except Exception:
return False
def _manage_scheduled_task(self, task_path, action):
schtasks_action = "/delete" if action == "delete" else "/change"
arguments = [schtasks_action, "/tn", task_path]
if action == "delete":
arguments.append("/f")
else:
arguments.append("/enable" if action == "enable" else "/disable")
result = self._run_windows_tool(
("schtasks.exe",),
arguments,
capture_output=True,
text=True
)
if result is not None and result.returncode == 0:
return True
escaped_path = task_path.replace("'", "''")
operation = {
"delete": "Unregister-ScheduledTask -InputObject $Task -Confirm:$false",
"enable": "Enable-ScheduledTask -InputObject $Task | Out-Null",
"disable": "Disable-ScheduledTask -InputObject $Task | Out-Null"
}.get(action)
if not operation:
return False
command = (
f"$FullName = '{escaped_path}'; "
"$Task = Get-ScheduledTask -ErrorAction SilentlyContinue | "
"Where-Object { ($_.TaskPath + $_.TaskName) -eq $FullName } | Select-Object -First 1; "
f"if ($Task) {{ {operation} }} else {{ exit 1 }}"
)
result = self._run_powershell(command, capture_output=True, text=True)
return bool(result and result.returncode == 0)
def _reg_read(self, root, path, value_name):
try:
with winreg.OpenKey(root, path, 0, winreg.KEY_READ) as reg:
@@ -203,18 +383,81 @@ class ToolsMixin:
####################################################################################################
def manage_autostart(self, enable):
try:
task_name = "PYAS_Security_ATS"
if enable:
cmd = f"$Action = New-ScheduledTaskAction -Execute '{self.file_pyas}' -Argument '-hide'; $Trigger = New-ScheduledTaskTrigger -AtLogOn; $Settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries; Register-ScheduledTask -TaskName '{task_name}' -Action $Action -Trigger $Trigger -Settings $Settings -RunLevel Highest -Force"
subprocess.run(["powershell", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-WindowStyle", "Hidden", "-Command", cmd], creationflags=0x08000000)
else:
subprocess.run(["schtasks", "/Delete", "/TN", task_name, "/F"], creationflags=0x08000000)
task_name = "PYAS_Security_ATS"
executable = os.path.normpath(self.file_pyas)
escaped_executable = executable.replace("'", "''")
errors = []
return True
except Exception as e:
self.write_log("WARN", "manage_autostart", detail=str(e), success=False)
return False
if enable:
task_command = f'"{executable}" -hide'
result = self._run_windows_tool(
("schtasks.exe",),
["/Create", "/TN", task_name, "/TR", task_command, "/SC", "ONLOGON", "/RL", "HIGHEST", "/F"],
capture_output=True,
text=True
)
if result and result.returncode == 0:
self._set_registry_autostart(False)
return True
if result:
errors.append((result.stderr or result.stdout or f"schtasks exit {result.returncode}").strip())
command = (
f"$Action = New-ScheduledTaskAction -Execute '{escaped_executable}' -Argument '-hide'; "
"$Trigger = New-ScheduledTaskTrigger -AtLogOn; "
"$Settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries; "
f"Register-ScheduledTask -TaskName '{task_name}' -Action $Action -Trigger $Trigger -Settings $Settings -RunLevel Highest -Force | Out-Null"
)
result = self._run_powershell(command, capture_output=True, text=True)
if result and result.returncode == 0:
self._set_registry_autostart(False)
return True
if result:
errors.append((result.stderr or result.stdout or f"PowerShell exit {result.returncode}").strip())
if self._set_registry_autostart(True):
self.write_log("INFO", "manage_autostart", detail="Scheduled Task unavailable; using HKCU Run fallback", success=True)
return True
else:
task_removed = False
query_result = self._run_windows_tool(
("schtasks.exe",),
["/Query", "/TN", task_name],
capture_output=True,
text=True
)
result = None
if query_result is not None and query_result.returncode != 0:
task_removed = True
elif query_result is not None:
result = self._run_windows_tool(
("schtasks.exe",),
["/Delete", "/TN", task_name, "/F"],
capture_output=True,
text=True
)
task_removed = bool(result and result.returncode == 0)
if query_result is None or not task_removed:
command = (
f"$Task = Get-ScheduledTask -TaskName '{task_name}' -ErrorAction SilentlyContinue; "
"if ($Task) { $Task | Unregister-ScheduledTask -Confirm:$false }"
)
powershell_result = self._run_powershell(command, capture_output=True, text=True)
if powershell_result is not None:
task_removed = powershell_result.returncode == 0
result = powershell_result
if result and result.returncode != 0:
errors.append((result.stderr or result.stdout or f"task removal exit {result.returncode}").strip())
registry_removed = self._set_registry_autostart(False)
if registry_removed and (task_removed or query_result is None and result is None):
return True
detail = "; ".join(error for error in errors if error) or "No supported autostart method was available"
self.write_log("WARN", "manage_autostart", detail=detail, success=False)
return False
####################################################################################################
@@ -292,10 +535,16 @@ class ToolsMixin:
if lock_func:
lock_func(path, True)
target_list.append({"file": path, "time": time.time()})
new_item = {"file": path, "time": time.time()}
is_directory = None
if list_key == "white_list":
is_directory = os.path.isdir(path)
new_item["is_dir"] = is_directory
target_list.append(new_item)
acted_items.append(path)
if list_key == "white_list":
self.sync_driver_whitelist(path, True)
self.sync_driver_whitelist(path, True, is_directory)
elif action == "remove":
norm_paths_case = {os.path.normcase(p) for p in norm_paths}
@@ -311,7 +560,8 @@ class ToolsMixin:
acted_items.append(val)
if list_key == "white_list":
self.sync_driver_whitelist(val, False)
is_directory = item.get("is_dir") if isinstance(item, dict) else None
self.sync_driver_whitelist(val, False, is_directory)
continue
new_list.append(item)
@@ -356,7 +606,8 @@ class ToolsMixin:
if np and os.path.normcase(np) in norm_paths_to_remove:
removed_items.append(val)
if list_key == "white_list":
self.sync_driver_whitelist(val, False)
is_directory = item.get("is_dir") if isinstance(item, dict) else None
self.sync_driver_whitelist(val, False, is_directory)
continue
new_list.append(item)
@@ -888,7 +1139,7 @@ class ToolsMixin:
log_path = os.path.join(self.path_system, "System32", "winevt", "Logs", f"{log_type}.evtx")
size = os.path.getsize(log_path) if os.path.exists(log_path) else 0
if subprocess.run(["wevtutil", "cl", log_type], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, creationflags=0x08000000).returncode == 0:
if self._clear_event_log(log_type):
total_deleted += size
except Exception:
@@ -1035,20 +1286,57 @@ class ToolsMixin:
def get_tasks():
res = []
try:
proc = subprocess.run(["schtasks", "/query", "/fo", "csv", "/v"], capture_output=True, text=True, creationflags=0x08000000)
reader = csv.reader(io.StringIO(proc.stdout))
next(reader, None)
proc = self._run_windows_tool(
("schtasks.exe",),
["/query", "/fo", "csv", "/v"],
capture_output=True,
text=True
)
if proc is not None and proc.returncode == 0:
reader = csv.reader(io.StringIO(proc.stdout))
next(reader, None)
for row in reader:
if len(row) > 8 and row[1].strip() and row[8].strip() and row[8] != "N/A":
name = row[1].split('\\')[-1]
path = row[8]
status = row[3]
for row in reader:
if len(row) > 8 and row[1].strip() and row[8].strip() and row[8] != "N/A":
name = row[1].split('\\')[-1]
path = row[8]
status = row[3]
if path and "windows" not in path.lower():
fp = self.extract_paths_from_cmdline(path)
fpp = fp[0] if fp else path
res.append({"id": f"tsk|{row[1]}", "type": "type_tsk", "name": name, "status": "disabled" if status == "Disabled" else "enabled", "path": fpp})
if path and "windows" not in path.lower():
fp = self.extract_paths_from_cmdline(path)
fpp = fp[0] if fp else path
res.append({"id": f"tsk|{row[1]}", "type": "type_tsk", "name": name, "status": "disabled" if status.lower() == "disabled" else "enabled", "path": fpp})
return res
command = (
"[Console]::OutputEncoding = [Text.UTF8Encoding]::new(); "
"Get-ScheduledTask -ErrorAction SilentlyContinue | ForEach-Object { "
"$Action = @($_.Actions)[0]; "
"[pscustomobject]@{Name=$_.TaskName; FullName=($_.TaskPath + $_.TaskName); "
"State=[string]$_.State; Execute=$Action.Execute; Arguments=$Action.Arguments} "
"} | ConvertTo-Json -Compress"
)
proc = self._run_powershell(command, capture_output=True, text=True, encoding="utf-8", errors="replace")
if not proc or proc.returncode != 0 or not proc.stdout.strip():
return res
task_data = json.loads(proc.stdout)
if isinstance(task_data, dict):
task_data = [task_data]
for task in task_data:
name = str(task.get("Name") or "").strip()
full_name = str(task.get("FullName") or name).strip()
execute = str(task.get("Execute") or "").strip()
arguments = str(task.get("Arguments") or "").strip()
command_line = " ".join(part for part in (execute, arguments) if part)
if not name or not command_line or "windows" in command_line.lower():
continue
paths = self.extract_paths_from_cmdline(command_line)
path = paths[0] if paths else execute or command_line
status = "disabled" if str(task.get("State") or "").lower() == "disabled" else "enabled"
res.append({"id": f"tsk|{full_name}", "type": "type_tsk", "name": name, "status": status, "path": path})
except Exception:
pass
@@ -1068,44 +1356,49 @@ class ToolsMixin:
def manage_startup(self, items, action):
def process_item(item_id):
try:
parts = item_id.split('|')
parts = item_id.split('|', 3)
stype = parts[0]
if stype == "reg":
root, old_path, name = int(parts[1]), parts[2], parts[3]
if action == "delete":
self._reg_delete(root, old_path, name)
return self._reg_delete(root, old_path, name)
else:
new_path = old_path.replace("_Disabled", "") if action == "enable" else (old_path if "_Disabled" in old_path else old_path + "_Disabled")
if old_path != new_path:
val = self._reg_read(root, old_path, name)
if val:
self._reg_write(root, new_path, name, winreg.REG_SZ, val)
self._reg_delete(root, old_path, name)
return self._reg_write(root, new_path, name, winreg.REG_SZ, val) and self._reg_delete(root, old_path, name)
return True
elif stype == "srv":
name = parts[1]
if action == "delete":
subprocess.run(["sc", "delete", name], capture_output=True, creationflags=0x08000000)
result = self._run_windows_tool(("sc.exe",), ["delete", name], capture_output=True)
else:
mode = "auto" if action == "enable" else "disabled"
subprocess.run(["sc", "config", name, f"start=", mode], capture_output=True, creationflags=0x08000000)
result = self._run_windows_tool(("sc.exe",), ["config", name, "start=", mode], capture_output=True)
if result is not None and result.returncode == 0:
return True
return self._manage_service_native(name, action)
elif stype == "tsk":
name = parts[1]
if action == "delete":
subprocess.run(["schtasks", "/delete", "/tn", name, "/f"], capture_output=True, creationflags=0x08000000)
name = item_id.partition('|')[2]
return self._manage_scheduled_task(name, action)
else:
cmd = "/enable" if action == "enable" else "/disable"
subprocess.run(["schtasks", "/change", "/tn", name, cmd], capture_output=True, creationflags=0x08000000)
return False
except Exception as e:
self.write_log("WARN", "manage_startup", detail=str(e), success=False)
return False
with ThreadPoolExecutor(max_workers=5) as executor:
list(executor.map(process_item, items))
results = list(executor.map(process_item, items))
return True
success = all(results) if results else True
if not success:
self.write_log("WARN", "manage_startup", detail="One or more startup items could not be updated", success=False)
return success
+1 -1
View File
@@ -2,7 +2,7 @@ import pyinstaller_versionfile
pyinstaller_versionfile.create_versionfile(
output_file="versionfile.txt",
version='3.6.6.0',
version='3.6.9.0',
company_name="PYAS Security",
file_description="PYAS Security Antivirus",
internal_name="PYAS",
+28 -9
View File
@@ -63,6 +63,9 @@
"*\\PYAS.exe",
"\\Device\\HarddiskVolume*\\Users\\*\\AppData\\Local\\Temp\\*\\PYAS_Setup.tmp",
"\\Device\\HarddiskVolume*\\Users\\*\\AppData\\Local\\Temp\\*\\_unins.tmp",
"\\Device\\HarddiskVolume*\\Users\\*\\AppData\\Local\\sogoupdf\\pdfpopcl.exe",
"\\Device\\HarddiskVolume*\\Users\\*\\AppData\\Local\\WeGame\\*\\tiny_dl\\TinyDL.exe",
"\\Device\\HarddiskVolume*\\Users\\*\\AppData\\Local\\Microsoft\\OneDrive\\OneDrive.exe",
"\\Device\\HarddiskVolume*\\Windows\\explorer.exe",
"\\Device\\HarddiskVolume*\\Windows\\System32\\csrss.exe",
"\\Device\\HarddiskVolume*\\Windows\\System32\\lsass.exe",
@@ -74,6 +77,8 @@
"\\Device\\HarddiskVolume*\\Program Files (x86)\\*",
"*\\games\\Arknights Game\\Arknights.exe",
"*\\games\\EndField Game\\EndField.exe",
"*\\cm\\FeverGames\\*\\FeverGamesInstaller.exe",
"*\\Davinci\\Resolve.exe",
],
"Target": [
"*\\PYAS.exe",
@@ -241,13 +246,17 @@
"InitiatorExclude": [
"*\\PYAS.exe",
"*\\Huorong\\Sysdiag\\bin\\sysclean.exe",
"*\\Dell\\SARemediation\\agent\\DellSupportAssistRemedationService.exe",
"\\Device\\HarddiskVolume*\\Windows\\explorer.exe",
"\\Device\\HarddiskVolume*\\Windows\\System32\\SearchIndexer.exe",
"\\Device\\HarddiskVolume*\\Windows\\System32\\lsass.exe",
"\\Device\\HarddiskVolume*\\Windows\\System32\\svchost.exe",
"\\Device\\HarddiskVolume*\\Windows\\System32\\services.exe",
"\\Device\\HarddiskVolume*\\Windows\\System32\\taskhostw.exe",
"\\Device\\HarddiskVolume*\\Windows\\System32\\TrustedInstaller.exe",
"\\Device\\HarddiskVolume*\\Windows\\System32\\ReAgentc.exe",
"\\Device\\HarddiskVolume*\\Windows\\WinSxS\\*\\TiWorker.exe",
"\\Device\\HarddiskVolume*\\Windows\\UUS\\amd64\\wuaucltcore.exe",
"\\Device\\HarddiskVolume*\\$WinREAgent\\Scratch\\*\\DismHost.exe",
],
"Target": [
@@ -258,6 +267,10 @@
"\\Device\\HarddiskVolume*\\Boot\\*",
"\\Device\\HarddiskVolume*\\Recovery\\*",
],
"TargetExclude": [
"\\Device\\HarddiskVolume*\\Windows\\System32\\Recovery\\ReAgent.xml",
"\\Device\\HarddiskVolume*\\Recovery\\OEM\\Logs\\Versions.ini",
],
"Operations": [
"Write",
"Delete",
@@ -452,11 +465,13 @@
"*\\PYAS.exe",
"*\\rufus-*.exe",
"*\\DiskInfo*.exe",
"\\Device\\HarddiskVolume*\\Program Files\\*\\launcher\\ca_launcher.exe",
"\\Device\\HarddiskVolume*\\Windows\\System32\\diskpart.exe",
"\\Device\\HarddiskVolume*\\Windows\\System32\\diskmgmt.msc",
"\\Device\\HarddiskVolume*\\Windows\\System32\\taskhostw.exe",
"\\Device\\HarddiskVolume*\\Windows\\System32\\vds.exe",
"\\Device\\HarddiskVolume*\\Windows\\System32\\format.com",
"\\Device\\HarddiskVolume*\\Windows\\System32\\WinSAT.exe",
],
"Operations": [
"Ioctl",
@@ -489,8 +504,6 @@
"*\\DefaultPassword",
"*\\AltDefaultUserName",
"*\\AltDefaultPassword",
"*\\LegalNoticeCaption",
"*\\LegalNoticeText",
"*\\AutoReboot",
"*\\DisableAutomaticRestartOnFailure",
"*\\SystemBiosVersion",
@@ -645,6 +658,7 @@
"*\\Sources\\SetupHost.exe",
"*\\Work\\*\\DismHost.exe",
"*\\Huorong\\Sysdiag\\bin\\HipsDaemon.exe",
"*\\Huorong\\Sysdiag\\bin\\HRUpdate.exe",
"*\\360Safe.exe",
"*\\PYAS.exe",
],
@@ -656,6 +670,9 @@
"\\REGISTRY\\MACHINE\\SYSTEM\\*ControlSet*\\Control\\SafeBoot\\Option",
"\\REGISTRY\\MACHINE\\SYSTEM\\*ControlSet*\\Control\\SafeBoot\\Option\\*",
],
"TargetExclude": [
"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Control\\SafeBoot\\Network\\HipsDaemon",
],
"Operations": [
"Write",
"Delete",
@@ -669,15 +686,17 @@
"Kill": false,
"Category": "Registry",
"InitiatorExclude": [
"*\\PYAS.exe",
"*\\Sources\\SetupHost.exe",
"*\\Work\\*\\DismHost.exe",
"*\\Windows\\UUS\\amd64\\MoUsoCoreWorker.exe",
"*\\Windows\\System32\\MoUsoCoreWorker.exe",
"*\\Windows\\System32\\Sysprep\\sysprep.exe",
"*\\Windows\\System32\\oobe\\*",
"*\\Windows\\System32\\svchost.exe",
"*\\Windows\\explorer.exe",
"*\\PYAS.exe",
"\\Device\\HarddiskVolume*\\Windows\\UUS\\amd64\\MoUsoCoreWorker.exe",
"\\Device\\HarddiskVolume*\\Windows\\UUS\\Packages\\Preview\\amd64\\MoUsoCoreWorker.exe",
"\\Device\\HarddiskVolume*\\Windows\\System32\\MoUsoCoreWorker.exe",
"\\Device\\HarddiskVolume*\\Windows\\System32\\Sysprep\\sysprep.exe",
"\\Device\\HarddiskVolume*\\Windows\\System32\\oobe\\*",
"\\Device\\HarddiskVolume*\\Windows\\System32\\svchost.exe",
"\\Device\\HarddiskVolume*\\Windows\\System32\\taskhostw.exe",
"\\Device\\HarddiskVolume*\\Windows\\explorer.exe",
],
"Target": [
"\\REGISTRY\\MACHINE\\SYSTEM\\Setup\\OOBEInProgress",
+6
View File
@@ -134,6 +134,12 @@ The machine learning-based virus scanning engine training achieved extremely hig
<img width="895" height="1097" alt="train" src="https://github.com/user-attachments/assets/fa7cf0e2-01a1-4234-9358-718c2b8a2c9a" />
## Rule Editor
PYAS antivirus software driver protection rule editor, developed using Blockly. Included in the Releases.
<img width="2559" height="1271" alt="image" src="https://github.com/user-attachments/assets/29a816a8-3bf9-4e1c-b881-7336676ad7f9" />
## Support System
Please ensure your computer supports Microsoft Visual C++ 2015-2022 Redistributable and Edge Webview2.