Compare commits

...
17 Commits
Author SHA1 Message Date
87owo 9eb55deedf Add files via upload 2026-01-12 13:29:30 +08:00
87owo 6e76b5b8eb Add files via upload 2026-01-12 13:28:04 +08:00
87owo 491b0da83d Add files via upload 2026-01-10 22:48:17 +08:00
87owo 5d2c17e940 Add files via upload 2026-01-10 22:47:35 +08:00
87owo 0497c4a9e7 Add files via upload 2026-01-10 20:05:44 +08:00
87owo 6d0765848b Add files via upload 2026-01-10 20:03:39 +08:00
87owo 40c4ae71bd Merge pull request #35 from secretlay3r/main
refactor: replace ifs with dicts/sets + simplify exception handling
2026-01-10 19:37:25 +08:00
secretlay3r 8edba10dff Update PYAS.py
backup_mbr():
- Shorten except blocks logic into one
- Add len(mbr) == 512 check  
- Add MBR_SIGNATURE instead of just b"\x55\xAA"

pipe_server_thread():
- Replace whole ifs chain with RULES dict
- Replace [4001, 5001] with KILL_CODES set (for readability)

get_window_info()  and  get_process_name():
- Extract process name logic into private _get_process_name()
2026-01-10 14:17:27 +03:00
87owo 85aa7bc652 Add files via upload 2026-01-09 14:05:47 +08:00
87owo 854ad1db07 Add files via upload 2026-01-09 00:11:30 +08:00
87owo 955600a1e1 Add files via upload 2026-01-07 22:19:13 +08:00
87owo b739134d85 Add files via upload 2026-01-07 22:18:36 +08:00
87owo 723152566d Add files via upload 2026-01-07 21:10:34 +08:00
87owo 678b045e0e Update README.md 2026-01-07 17:47:13 +08:00
87owo 681f4df49a Add files via upload 2026-01-07 17:44:23 +08:00
87owo b19f7d7098 Add files via upload 2026-01-06 15:11:42 +08:00
87owo daaae3ec10 Add files via upload 2026-01-06 14:43:06 +08:00
11 changed files with 620 additions and 272 deletions

No files matched your search

+1 -1
View File
@@ -1,5 +1,5 @@
from PIL import Image
import numpy, pefile, os
import numpy, os
####################################################################################################
+118 -95
View File
@@ -130,6 +130,7 @@ class MainWindow_Controller(QMainWindow):
self.mouse_pos = 0
self.current_opacity = 0
self.driver_port = None
self.scan_running = False
self.virus_lock = {}
self.virus_results = []
@@ -146,7 +147,7 @@ class MainWindow_Controller(QMainWindow):
self.pyas_default = {
"version": "3.3.8",
"api_host": "https://pyas-security.com/",
"api_key": "",
"api_key": "fBRZxYS1UxykM-qzNOlKOEl63WILzlvgNMn6QfsG6FXCAAIktCrOPTAfY5_hEyuZ",
"suffix": [".com", ".dll", ".drv", ".exe", ".ocx", ".scr", ".sys", ".mui", ".cpl"],
"size": 256 * 1024 * 1024,
"sensitive": 95,
@@ -179,6 +180,14 @@ class MainWindow_Controller(QMainWindow):
"SCREEN_BLOCK": "監控行為攔截",
"KILL_ATTEMPT": "終止行為攔截",
}
self.block_rules = {
2001: "FILE_BLOCK",
3001: "REG_BLOCK",
4001: "BOOT_BLOCK",
5001: "RANSOM_BLOCK",
6001: "INJECT_BLOCK"
}
self.kill_codes = {2001, 3001, 4001, 5001}
####################################################################################################
@@ -209,7 +218,7 @@ class MainWindow_Controller(QMainWindow):
try:
setattr(self, name.lower(), ctypes.WinDLL(name, use_last_error=True))
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"init_windll | {e}", "warn", False)
self.advapi32.OpenSCManagerW.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.wintypes.DWORD]
self.advapi32.OpenSCManagerW.restype = ctypes.wintypes.HANDLE
@@ -262,7 +271,7 @@ class MainWindow_Controller(QMainWindow):
with open(file_path, "w", encoding="utf-8", errors="ignore") as f:
f.write(json.dumps(filter_config, indent=4, ensure_ascii=False))
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"save_config | {e}", "warn", False)
def read_config(self, file_path, default_value):
try:
@@ -274,7 +283,7 @@ class MainWindow_Controller(QMainWindow):
config_value.setdefault(key, value)
return config_value
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"read_config | {e}", "warn", False)
return default_value.copy()
def load_config(self):
@@ -300,7 +309,7 @@ class MainWindow_Controller(QMainWindow):
self.model.load_path(self.path_models, callback=lambda x: self.init_log_signal.emit(os.path.basename(x)))
self.init_log_signal.emit("引擎加載完成")
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"init_engine_thread | {e}", "warn", False)
####################################################################################################
@@ -623,7 +632,7 @@ class MainWindow_Controller(QMainWindow):
else:
sys.exit(0)
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"show_startup | {e}", "warn", False)
def show_button(self):
self.show()
@@ -816,7 +825,7 @@ class MainWindow_Controller(QMainWindow):
lang = self.pyas_config.get("language", "english_switch")
self.scan_progress_signal.emit(self.trans(lang, "正在初始化中"))
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"init_scan | {e}", "warn", False)
def file_button(self):
targets = self.send_message("檔案掃描", "files", True)
@@ -865,7 +874,7 @@ class MainWindow_Controller(QMainWindow):
self.scan_progress_signal.emit(norm_path)
gc.collect()
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"scan_worker | {e}", "warn", False)
finally:
count = len(self.virus_results)
elapsed = int(time.time() - self.scan_start)
@@ -904,7 +913,7 @@ class MainWindow_Controller(QMainWindow):
return result
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"scan_engine | {e}", "warn", False)
return False
####################################################################################################
@@ -945,7 +954,7 @@ class MainWindow_Controller(QMainWindow):
return False
api_host = self.pyas_config.get("api_host", "https://pyas-security.com/")
api_key = self.pyas_config.get("api_key", "")
api_key = self.pyas_config.get("api_key", "fBRZxYS1UxykM-qzNOlKOEl63WILzlvgNMn6QfsG6FXCAAIktCrOPTAfY5_hEyuZ")
success, sha256 = self.cloud.upload_file(file_path, api_host, api_key)
if was_locked:
@@ -959,7 +968,7 @@ class MainWindow_Controller(QMainWindow):
self.send_message(f"雲端服務 | 通訊服務錯誤 | None | {file_path} | None", "warn", True)
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"perform_cloud_scan | {e}", "warn", False)
finally:
if 'was_locked' in locals() and was_locked:
try:
@@ -989,7 +998,7 @@ class MainWindow_Controller(QMainWindow):
virus_list.takeItem(i)
self.virus_results.remove(file_path)
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"solve_button | {e}", "warn", False)
QApplication.processEvents()
count = len(self.virus_results)
@@ -1047,7 +1056,7 @@ class MainWindow_Controller(QMainWindow):
widget.takeItem(widget.row(item))
self.virus_results.remove(file_path)
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"show_scan_menu | {e}", "warn", False)
elif act == white_action:
file_path = self.norm_path(path)
@@ -1058,7 +1067,7 @@ class MainWindow_Controller(QMainWindow):
widget.takeItem(widget.row(item))
self.virus_results.remove(file_path)
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"show_scan_menu | {e}", "warn", False)
elif act == quarantine_action:
file_path = self.norm_path(path)
@@ -1069,7 +1078,7 @@ class MainWindow_Controller(QMainWindow):
widget.takeItem(widget.row(item))
self.virus_results.remove(file_path)
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"show_scan_menu | {e}", "warn", False)
count = len(self.virus_results)
self.widgets["solve_button"].setVisible(count > 0)
@@ -1171,7 +1180,7 @@ class MainWindow_Controller(QMainWindow):
n = self.manage_named_list("white_list", [target_path], action="add", with_hash=True)
self.send_message(f"成功增加到白名單,共 {n} 個檔案", "info", True)
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"show_process_menu | {e}", "warn", False)
elif act == quarantine_action:
target_path = self.norm_path(file_path)
@@ -1180,7 +1189,7 @@ class MainWindow_Controller(QMainWindow):
n = self.manage_named_list("quarantine", [target_path], action="add", with_hash=True, lock_func=self.lock_file)
self.send_message(f"成功增加到隔離區,共 {n} 個檔案", "info", True)
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"show_process_menu | {e}", "warn", False)
def kill_process(self, pid):
try:
@@ -1193,7 +1202,7 @@ class MainWindow_Controller(QMainWindow):
self.kernel32.TerminateProcess(h, 0)
self.kernel32.CloseHandle(h)
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"kill_process | {e}", "warn", False)
self.refresh_process()
####################################################################################################
@@ -1207,7 +1216,7 @@ class MainWindow_Controller(QMainWindow):
size_text = self.format_size(self.total_deleted_size)
self.send_message(f"成功清理了 {size_text} 系統垃圾", "info", True)
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"clean_button | {e}", "warn", False)
def traverse_temp(self, path):
try:
@@ -1230,7 +1239,7 @@ class MainWindow_Controller(QMainWindow):
except Exception:
continue
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"traverse_temp | {e}", "warn", False)
def format_size(self, size):
units = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
@@ -1252,23 +1261,23 @@ class MainWindow_Controller(QMainWindow):
self.repair_system_image()
self.send_message("修復系統檔案成功", "info", True)
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"repair_button | {e}", "warn", False)
def backup_mbr(self, max_drives=26):
self.mbr_backup = {}
mbr_signature = b"\x55\xAA"
for drive in range(max_drives):
drive_path = rf"\\.\PhysicalDrive{drive}"
try:
with open(drive_path, "rb") as f:
mbr = f.read(512)
if mbr[510:512] == b"\x55\xAA":
self.mbr_backup[drive] = mbr
except FileNotFoundError:
continue
except PermissionError as e:
if len(mbr) == 512 and mbr[510:512] == mbr_signature:
self.mbr_backup[drive] = mbr
except (FileNotFoundError, PermissionError, OSError):
continue
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(str(e), "warn", False)
def repair_system_mbr(self):
if not hasattr(self, "mbr_backup") or not self.mbr_backup:
@@ -1285,7 +1294,7 @@ class MainWindow_Controller(QMainWindow):
except PermissionError as e:
continue
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"repair_system_mbr | {e}", "warn", False)
def repair_system_wallpaper(self):
try:
@@ -1314,7 +1323,7 @@ class MainWindow_Controller(QMainWindow):
pass
self.user32.SystemParametersInfoW(20, 0, wallpaper, 3)
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"repair_system_wallpaper | {e}", "warn", False)
def repair_system_restrict(self):
try:
@@ -1353,7 +1362,7 @@ class MainWindow_Controller(QMainWindow):
except FileNotFoundError:
continue
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"repair_system_restrict | {e}", "warn", False)
def repair_system_file_type(self):
try:
@@ -1373,7 +1382,7 @@ class MainWindow_Controller(QMainWindow):
except Exception:
continue
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"repair_system_file_type | {e}", "warn", False)
def repair_system_file_icon(self):
try:
@@ -1384,7 +1393,7 @@ class MainWindow_Controller(QMainWindow):
except Exception:
continue
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"repair_system_file_icon | {e}", "warn", False)
def repair_system_image(self):
try:
@@ -1405,7 +1414,7 @@ class MainWindow_Controller(QMainWindow):
except OSError:
break
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"repair_system_image | {e}", "warn", False)
####################################################################################################
@@ -1434,7 +1443,7 @@ class MainWindow_Controller(QMainWindow):
self.send_message(f"系統防護 | 系統進程重啟 | None | None | {name}", "notify", True)
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"check_process_survival | {e}", "warn", False)
####################################################################################################
@@ -1522,7 +1531,7 @@ class MainWindow_Controller(QMainWindow):
self.kernel32.TerminateProcess(h, 0)
self.kernel32.CloseHandle(h)
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"popup_intercept_thread | {e}", "warn", False)
####################################################################################################
@@ -1545,34 +1554,36 @@ class MainWindow_Controller(QMainWindow):
pid = ctypes.c_ulong()
self.user32.GetWindowThreadProcessId(hWnd, ctypes.byref(pid))
proc_name = ""
try:
proc_name = self.get_process_name(pid.value)
except Exception:
pass
proc_name = self.get_process_name(pid.value)
return str(title.value), str(class_name.value), proc_name
def get_process_name(self, pid):
name, file_path = self.get_exe_info(pid)
if name:
return name
snapshot = self.kernel32.CreateToolhelp32Snapshot(0x00000002, 0)
entry = PROCESSENTRY32W()
entry.dwSize = ctypes.sizeof(PROCESSENTRY32W)
try:
result_name = ""
name, _ = self.get_exe_info(pid)
if name:
return name
result = ""
if self.kernel32.Process32FirstW(snapshot, ctypes.byref(entry)):
while True:
if entry.th32ProcessID == pid:
try:
result = entry.szExeFile
except Exception:
result = ""
break
if not self.kernel32.Process32NextW(snapshot, ctypes.byref(entry)):
break
self.kernel32.CloseHandle(snapshot)
return result
snapshot = self.kernel32.CreateToolhelp32Snapshot(0x00000002, 0)
if snapshot == -1:
return result_name
entry = PROCESSENTRY32W()
entry.dwSize = ctypes.sizeof(PROCESSENTRY32W)
if self.kernel32.Process32FirstW(snapshot, ctypes.byref(entry)):
while True:
if entry.th32ProcessID == pid:
result_name = entry.szExeFile
break
if not self.kernel32.Process32NextW(snapshot, ctypes.byref(entry)):
break
self.kernel32.CloseHandle(snapshot)
return result_name
except:
pass
return result_name
####################################################################################################
@@ -1638,7 +1649,7 @@ class MainWindow_Controller(QMainWindow):
try:
lock_func(path, True)
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"manage_named_list | {e}", "warn", False)
self.config_list(list_key).append({"file": path, "hash": file_hash})
n += 1
@@ -1651,7 +1662,7 @@ class MainWindow_Controller(QMainWindow):
self.config_list(list_key).remove(item)
n += 1
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"manage_named_list | {e}", "warn", False)
if n:
self.save_config(self.file_config, self.pyas_config)
@@ -1674,7 +1685,7 @@ class MainWindow_Controller(QMainWindow):
webbrowser.open("https://pyas-security.com/antivirus")
return True
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"website_button | {e}", "warn", False)
return False
def cloud_button(self):
@@ -1682,7 +1693,7 @@ class MainWindow_Controller(QMainWindow):
webbrowser.open("https://pyas-security.com/analyze")
return True
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"cloud_button | {e}", "warn", False)
return False
def update_button(self):
@@ -1717,7 +1728,7 @@ class MainWindow_Controller(QMainWindow):
webbrowser.open(page)
return True
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"update_button | {e}", "warn", False)
return False
####################################################################################################
@@ -1734,7 +1745,7 @@ class MainWindow_Controller(QMainWindow):
os.close(self.virus_lock[file])
del self.virus_lock[file]
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"lock_file | {e}", "warn", False)
def relock_file(self):
quarantine_list = self.pyas_config.get("quarantine", [])
@@ -1744,7 +1755,7 @@ class MainWindow_Controller(QMainWindow):
try:
self.lock_file(file, True)
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"relock_file | {e}", "warn", False)
####################################################################################################
@@ -1758,7 +1769,7 @@ class MainWindow_Controller(QMainWindow):
self.handle_new_process(pid)
self.exist_process = cur
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"protect_proc_thread | {e}", "warn", False)
def handle_new_process(self, pid):
try:
@@ -1774,10 +1785,19 @@ class MainWindow_Controller(QMainWindow):
seen = set()
paths = [p for p in paths if p and (p not in seen and not seen.add(p))]
suffix = self.pyas_config.get("suffix", [".com", ".dll", ".drv", ".exe", ".ocx", ".scr", ".sys", ".mui"])
for p in paths:
file_path = self.norm_path(self.device_path_to_drive(p)) if p else ""
if not file_path:
if not file_path or not os.path.isfile(file_path):
continue
ext = os.path.splitext(file_path)[-1].lower()
if ext not in suffix:
continue
if self.is_in_whitelist(file_path):
continue
if self.scan_engine(file_path):
@@ -1788,7 +1808,7 @@ class MainWindow_Controller(QMainWindow):
self.suspend_process(h, False)
self.kernel32.CloseHandle(h)
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"handle_new_process | {e}", "warn", False)
def suspend_process(self, h_process, suspend):
try:
@@ -1802,7 +1822,7 @@ class MainWindow_Controller(QMainWindow):
else:
self.ntdll.NtResumeProcess(h_process)
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"suspend_process | {e}", "warn", False)
####################################################################################################
@@ -1941,7 +1961,7 @@ class MainWindow_Controller(QMainWindow):
self.send_message(f"檔案防護 | 靜態掃描攔截 | None | None | {file_path}", "notify", True)
self.start_daemon_thread(self.cloud_check, file_path)
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"protect_file_thread | {e}", "warn", False)
self.kernel32.CloseHandle(hDir)
####################################################################################################
@@ -1960,7 +1980,7 @@ class MainWindow_Controller(QMainWindow):
self.handle_new_connection(key)
self.exist_connections = conns
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"protect_net_thread | {e}", "warn", False)
self.exist_connections = set()
def get_connections_list(self):
@@ -1986,7 +2006,7 @@ class MainWindow_Controller(QMainWindow):
connections.add((row.dwOwningPid, row.dwRemoteAddr, row.dwRemotePort))
return connections
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"get_connections_list | {e}", "warn", False)
return set()
def handle_new_connection(self, key):
@@ -2004,7 +2024,7 @@ class MainWindow_Controller(QMainWindow):
self.send_message(f"網路防護 | 規則列表攔截 | {pid} | {file_path} | {remote_ip}", "notify", True)
self.kernel32.CloseHandle(h)
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"handle_new_connection | {e}", "warn", False)
####################################################################################################
@@ -2019,7 +2039,7 @@ class MainWindow_Controller(QMainWindow):
self.check_process_survival()
time.sleep(0.5)
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"protect_system_thread | {e}", "warn", False)
####################################################################################################
@@ -2048,11 +2068,19 @@ class MainWindow_Controller(QMainWindow):
subprocess.run(["sc", "start", service_name], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, shell=True)
return True
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"install_system_driver | {e}", "warn", False)
return False
def stop_system_driver(self):
try:
if self.driver_port:
try:
self.kernel32.CloseHandle(self.driver_port)
self.driver_port = None
except Exception:
pass
time.sleep(0.5)
service_name = "PYAS_Driver"
subprocess.run(["sc", "stop", service_name], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, shell=True)
subprocess.run(["sc", "delete", service_name], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, shell=True)
@@ -2065,38 +2093,31 @@ class MainWindow_Controller(QMainWindow):
def pipe_server_thread(self):
try:
port_name = "\\PYAS_Output_Pipe"
h_port = ctypes.wintypes.HANDLE()
self.driver_port = ctypes.wintypes.HANDLE()
while self.pyas_config.get("driver_switch", False):
hr = self.fltlib.FilterConnectCommunicationPort(port_name, 0, None, 0, None, ctypes.byref(h_port))
hr = self.fltlib.FilterConnectCommunicationPort(port_name, 0, None, 0, None, ctypes.byref(self.driver_port))
if hr == 0:
message = PYAS_FULL_MESSAGE()
while self.pyas_config.get("driver_switch", False):
hr_get = self.fltlib.FilterGetMessage(h_port, ctypes.byref(message), ctypes.sizeof(PYAS_FULL_MESSAGE), None)
try:
hr_get = self.fltlib.FilterGetMessage(self.driver_port, ctypes.byref(message), ctypes.sizeof(PYAS_FULL_MESSAGE), None)
except OSError:
break
if hr_get == 0:
code = message.Data.MessageCode
pid = message.Data.ProcessId
raw_path = self.get_exe_info(pid)[1]
target = message.Data.Path
rule_name = "Unknown"
if code == 2001:
rule_name = "FILE_BLOCK"
elif code == 3001:
rule_name = "REG_BLOCK"
elif code == 4001:
rule_name = "BOOT_BLOCK"
elif code == 5001:
rule_name = "RANSOM_BLOCK"
elif code == 6001:
rule_name = "INJECT_BLOCK"
rule_name = self.block_rules.get(code, "Unknown")
display_rule = self.block_replace.get(rule_name, rule_name)
self.send_message(f"驅動防護 | {display_rule} | {pid} | {raw_path} | {target}", "notify", True)
if code in [4001, 5001]:
if code in self.kill_codes and not self.is_in_whitelist(raw_path):
try:
h = self.kernel32.OpenProcess(0x1F0FFF, False, pid)
if h:
@@ -2106,10 +2127,12 @@ class MainWindow_Controller(QMainWindow):
pass
else:
break
self.kernel32.CloseHandle(h_port)
if self.driver_port:
self.kernel32.CloseHandle(self.driver_port)
self.driver_port = None
time.sleep(0.2)
except Exception as e:
self.send_message(e, "warn", False)
self.send_message(f"pipe_server_thread | {e}", "warn", False)
####################################################################################################
+1 -1
View File
@@ -27,7 +27,7 @@ translate_dict = {
"腳本":"Script ","鏈式":"Chain ","記憶體":"Memory ","正在加載":"Loading ","加載":"Load ",
"行為":"Behavior ","可疑":"Suspicious ","勒索":"Ransom ","主要":"Main ",
"許可條款":"License Terms ","惡意":"Malicious", "開發":"Developers ",
"啟用":"Enable ","禁用":"Disable ","正在初始化中":"Initializing ",
"啟用":"Enable ","禁用":"Disable ","正在初始化中":"Initializing ","初始化":"initialize ",
"正在掃描":"Scanning ","正在刪除":"Deleting ","正在追蹤":"Tracking ",
"最小化到":"Minimize To ","靈敏度":"Sensitivity ","正在檢查":"Checking ",
"確定要":"Sure Want To ","引擎靈敏度":"Sensitivity ","更新":"Update ",
+1 -1
View File
@@ -2,7 +2,7 @@ import pyinstaller_versionfile
pyinstaller_versionfile.create_versionfile(
output_file="versionfile.txt",
version='3.3.8',
version='3.3.9',
company_name="PYAS Security",
file_description="Python Antivirus Software",
internal_name="PYAS",
+2
View File
@@ -106,6 +106,7 @@ FLT_PREOP_CALLBACK_STATUS ProtectFile_PreCreate(PFLT_CALLBACK_DATA Data, PCFLT_R
FLT_PREOP_CALLBACK_STATUS ProtectFile_PreWrite(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext);
FLT_PREOP_CALLBACK_STATUS ProtectFile_PreSetInfo(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext);
FLT_PREOP_CALLBACK_STATUS ProtectFile_FileSystemControl(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext);
FLT_PREOP_CALLBACK_STATUS ProtectFile_SetSecurity(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext);
FLT_PREOP_CALLBACK_STATUS ProtectBoot_PreDeviceControl(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext);
NTSTATUS InitializeProcessProtection();
@@ -116,6 +117,7 @@ VOID UninitializeRegistryProtection();
VOID ImageLoadNotify(PUNICODE_STRING FullImageName, HANDLE ProcessId, PIMAGE_INFO ImageInfo);
BOOLEAN IsProcessTrusted(HANDLE ProcessId);
BOOLEAN IsCriticalSystemProcess(HANDLE ProcessId);
BOOLEAN IsTargetProtected(HANDLE ProcessId);
BOOLEAN IsInstallerProcess(HANDLE ProcessId);
BOOLEAN WildcardMatch(PCWSTR Pattern, PCWSTR String, USHORT StringLengthBytes);
+10 -1
View File
@@ -27,7 +27,15 @@ static VOID InstanceTeardownComplete(PCFLT_RELATED_OBJECTS FltObjects, FLT_INSTA
}
static NTSTATUS DriverUnload(FLT_FILTER_UNLOAD_FLAGS Flags) {
UNREFERENCED_PARAMETER(Flags);
if (!(Flags & FLTFL_FILTER_UNLOAD_MANDATORY)) {
ExAcquireFastMutex(&GlobalData.PortMutex);
BOOLEAN IsConnected = (GlobalData.ClientPort != NULL);
ExReleaseFastMutex(&GlobalData.PortMutex);
if (IsConnected) {
return STATUS_FLT_DO_NOT_DETACH;
}
}
PsRemoveLoadImageNotifyRoutine(ImageLoadNotify);
UninitializeRegistryProtection();
@@ -81,6 +89,7 @@ CONST FLT_OPERATION_REGISTRATION Callbacks[] = {
{ IRP_MJ_CREATE, 0, ProtectFile_PreCreate, NULL },
{ IRP_MJ_WRITE, 0, ProtectFile_PreWrite, NULL },
{ IRP_MJ_SET_INFORMATION, 0, ProtectFile_PreSetInfo, NULL },
{ IRP_MJ_SET_SECURITY, 0, ProtectFile_SetSecurity, NULL },
{ IRP_MJ_FILE_SYSTEM_CONTROL, 0, ProtectFile_FileSystemControl, NULL },
{ IRP_MJ_DEVICE_CONTROL, 0, ProtectBoot_PreDeviceControl, NULL },
{ IRP_MJ_OPERATION_END }
+57 -4
View File
@@ -40,9 +40,16 @@ FLT_PREOP_CALLBACK_STATUS ProtectFile_PreCreate(PFLT_CALLBACK_DATA Data, PCFLT_R
HANDLE Pid = PsGetCurrentProcessId();
BOOLEAN Trusted = IsProcessTrusted(Pid);
ULONG CreateDisposition = (Data->Iopb->Parameters.Create.Options >> 24) & 0xFF;
BOOLEAN IsCreateAction = (CreateDisposition == FILE_CREATE ||
CreateDisposition == FILE_SUPERSEDE ||
CreateDisposition == FILE_OVERWRITE ||
CreateDisposition == FILE_OVERWRITE_IF ||
CreateDisposition == FILE_OPEN_IF);
if (IsHoneyToken(&FileName)) {
if (!Trusted) {
if (Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess & (FILE_WRITE_DATA | DELETE)) {
if ((Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess & (FILE_WRITE_DATA | DELETE)) || IsCreateAction) {
SendMessageToUser(5001, (ULONG)(ULONG_PTR)Pid, FileName.Buffer, FileName.Length);
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
callbackStatus = FLT_PREOP_COMPLETE;
@@ -69,7 +76,8 @@ FLT_PREOP_CALLBACK_STATUS ProtectFile_PreCreate(PFLT_CALLBACK_DATA Data, PCFLT_R
if (CheckProtectedPathRule(&FileName)) {
if (!Trusted) {
if (Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess & (FILE_WRITE_DATA | DELETE | WRITE_DAC | GENERIC_WRITE)) {
if ((Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess &
(FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_ATTRIBUTES | DELETE | WRITE_DAC | GENERIC_WRITE)) || IsCreateAction) {
SendMessageToUser(2001, (ULONG)(ULONG_PTR)Pid, FileName.Buffer, FileName.Length);
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
callbackStatus = FLT_PREOP_COMPLETE;
@@ -126,7 +134,15 @@ FLT_PREOP_CALLBACK_STATUS ProtectFile_PreSetInfo(PFLT_CALLBACK_DATA Data, PCFLT_
HANDLE Pid = PsGetCurrentProcessId();
if (!IsProcessTrusted(Pid)) {
if (CheckFileExtensionRule(&nameInfo->Name) || CheckProtectedPathRule(&nameInfo->Name)) {
if (CheckProtectedPathRule(&nameInfo->Name)) {
SendMessageToUser(2001, (ULONG)(ULONG_PTR)Pid, nameInfo->Name.Buffer, nameInfo->Name.Length);
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
FltReleaseFileNameInformation(nameInfo);
return FLT_PREOP_COMPLETE;
}
if (CheckFileExtensionRule(&nameInfo->Name)) {
if (CheckRansomActivity(Pid, &nameInfo->Name, NULL, 0, FALSE)) {
SendMessageToUser(5001, (ULONG)(ULONG_PTR)Pid, nameInfo->Name.Buffer, nameInfo->Name.Length);
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
@@ -135,13 +151,50 @@ FLT_PREOP_CALLBACK_STATUS ProtectFile_PreSetInfo(PFLT_CALLBACK_DATA Data, PCFLT_
}
}
}
if (nameInfo) {
FltReleaseFileNameInformation(nameInfo);
}
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
FLT_PREOP_CALLBACK_STATUS ProtectFile_SetSecurity(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext) {
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
if (Data->RequestorMode == KernelMode) return FLT_PREOP_SUCCESS_NO_CALLBACK;
if (KeGetCurrentIrql() > APC_LEVEL) return FLT_PREOP_SUCCESS_NO_CALLBACK;
PFLT_FILE_NAME_INFORMATION nameInfo = NULL;
NTSTATUS status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo);
if (!NT_SUCCESS(status) || !nameInfo) return FLT_PREOP_SUCCESS_NO_CALLBACK;
status = FltParseFileNameInformation(nameInfo);
if (!NT_SUCCESS(status) || !nameInfo->Name.Buffer) {
FltReleaseFileNameInformation(nameInfo);
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
SECURITY_INFORMATION SecurityInfo = Data->Iopb->Parameters.SetSecurity.SecurityInformation;
if (SecurityInfo & (OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION)) {
if (CheckProtectedPathRule(&nameInfo->Name)) {
HANDLE Pid = PsGetCurrentProcessId();
if (!IsProcessTrusted(Pid) && !IsInstallerProcess(Pid)) {
SendMessageToUser(2001, (ULONG)(ULONG_PTR)Pid, nameInfo->Name.Buffer, nameInfo->Name.Length);
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
FltReleaseFileNameInformation(nameInfo);
return FLT_PREOP_COMPLETE;
}
}
}
FltReleaseFileNameInformation(nameInfo);
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
FLT_PREOP_CALLBACK_STATUS ProtectFile_PreWrite(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext) {
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
+4 -1
View File
@@ -9,7 +9,10 @@ static BOOLEAN IsSystemImage(PUNICODE_STRING FullImageName) {
if (WildcardMatch(L"*\\Windows\\System32\\*", FullImageName->Buffer, FullImageName->Length) ||
WildcardMatch(L"*\\Windows\\SysWOW64\\*", FullImageName->Buffer, FullImageName->Length) ||
WildcardMatch(L"*\\Windows\\WinSxS\\*", FullImageName->Buffer, FullImageName->Length)) {
WildcardMatch(L"*\\Windows\\WinSxS\\*", FullImageName->Buffer, FullImageName->Length) ||
WildcardMatch(L"*\\Windows\\Microsoft.NET\\*", FullImageName->Buffer, FullImageName->Length) ||
WildcardMatch(L"*\\Common Files\\Microsoft Shared\\*", FullImageName->Buffer, FullImageName->Length) ||
WildcardMatch(L"*\\Program Files*\\*", FullImageName->Buffer, FullImageName->Length)) {
return TRUE;
}
return FALSE;
+29 -2
View File
@@ -2,6 +2,14 @@
LARGE_INTEGER Cookie;
static BOOLEAN IsBamRegistryPath(PCUNICODE_STRING KeyName) {
if (!KeyName || !KeyName->Buffer) return FALSE;
if (WildcardMatch(L"*\\Services\\bam\\*", KeyName->Buffer, KeyName->Length)) {
return TRUE;
}
return FALSE;
}
static NTSTATUS RegistryCallback(PVOID CallbackContext, PVOID Argument1, PVOID Argument2) {
UNREFERENCED_PARAMETER(CallbackContext);
@@ -18,15 +26,34 @@ static NTSTATUS RegistryCallback(PVOID CallbackContext, PVOID Argument1, PVOID A
}
if (KeyName && KeyName->Buffer) {
if (IsBamRegistryPath(KeyName)) {
CmCallbackReleaseKeyObjectIDEx(KeyName);
return STATUS_SUCCESS;
}
if (CheckRegistryRule(KeyName)) {
HANDLE Pid = PsGetCurrentProcessId();
if (!IsProcessTrusted(Pid)) {
if (!IsInstallerProcess(Pid)) {
if (WildcardMatch(L"*\\MACHINE\\SAM*", KeyName->Buffer, KeyName->Length) ||
WildcardMatch(L"*\\MACHINE\\SECURITY*", KeyName->Buffer, KeyName->Length) ||
WildcardMatch(L"*\\MACHINE\\SYSTEM*", KeyName->Buffer, KeyName->Length) ||
WildcardMatch(L"*\\MACHINE\\BCD00000000*", KeyName->Buffer, KeyName->Length)) {
if (!IsCriticalSystemProcess(Pid)) {
SendMessageToUser(3001, (ULONG)(ULONG_PTR)Pid, KeyName->Buffer, KeyName->Length);
CmCallbackReleaseKeyObjectIDEx(KeyName);
return STATUS_ACCESS_DENIED;
}
}
else {
if (!IsProcessTrusted(Pid)) {
if (!IsInstallerProcess(Pid)) {
SendMessageToUser(3001, (ULONG)(ULONG_PTR)Pid, KeyName->Buffer, KeyName->Length);
CmCallbackReleaseKeyObjectIDEx(KeyName);
return STATUS_ACCESS_DENIED;
}
}
}
}
}
+391 -160
View File
@@ -13,68 +13,186 @@ typedef struct _RANSOM_TRACKER {
RANSOM_TRACKER RansomTrackers[MAX_TRACKERS];
static BOOLEAN HasSuffix(PCUNICODE_STRING String, PCWSTR Suffix) {
if (!String || !String->Buffer || !Suffix) return FALSE;
const PCWSTR SafeSystemBinaries[] = {
L"*\\Windows\\System32\\lsass.exe",
L"*\\Windows\\System32\\services.exe",
L"*\\Windows\\System32\\csrss.exe",
L"*\\Windows\\System32\\smss.exe",
L"*\\Windows\\System32\\wininit.exe",
L"*\\Windows\\System32\\winlogon.exe",
L"*\\Windows\\System32\\svchost.exe",
L"*\\Windows\\System32\\SearchIndexer.exe",
L"*\\Windows\\System32\\msiexec.exe",
L"*\\Windows\\System32\\TrustedInstaller.exe",
L"*\\Windows\\System32\\TiWorker.exe",
L"*\\Windows\\System32\\dism.exe",
L"*\\Windows\\System32\\dismhost.exe",
L"*\\Windows\\System32\\wuauclt.exe",
L"*\\Windows\\System32\\taskhostw.exe",
L"*\\Windows\\System32\\MoUsoCoreWorker.exe",
L"*\\Windows\\System32\\sppsvc.exe",
L"*\\Windows\\System32\\backgroundTaskHost.exe",
L"*\\Windows\\System32\\RuntimeBroker.exe",
L"*\\Windows\\System32\\ctfmon.exe",
L"*\\Windows\\System32\\smartscreen.exe",
L"*\\Windows\\System32\\Taskmgr.exe",
L"*\\Windows\\ImmersiveControlPanel\\SystemSettings.exe"
};
SIZE_T SuffixLenBytes = 0;
while (Suffix[SuffixLenBytes / sizeof(WCHAR)] != L'\0') {
SuffixLenBytes += sizeof(WCHAR);
}
const PCWSTR CriticalSystemBinaries[] = {
L"*\\Windows\\ImmersiveControlPanel\\SystemSettings.exe",
L"*\\Windows Defender\\MsMpEng.exe",
L"*\\Windows\\System32\\lsass.exe",
L"*\\Windows\\System32\\services.exe",
L"*\\Windows\\System32\\wininit.exe",
L"*\\Windows\\System32\\winlogon.exe",
L"*\\Windows\\System32\\svchost.exe",
L"*\\Windows\\System32\\smss.exe",
L"*\\Windows\\System32\\csrss.exe",
L"*\\Windows\\System32\\sppsvc.exe",
L"*\\Windows\\System32\\msiexec.exe",
L"*\\Windows\\System32\\TrustedInstaller.exe",
L"*\\Windows\\System32\\TiWorker.exe",
L"*\\Windows\\System32\\dism.exe",
L"*\\Windows\\System32\\dismhost.exe",
L"*\\Windows\\System32\\SgrmBroker.exe",
L"*\\Windows\\System32\\WerFault.exe",
L"*\\Windows\\System32\\wbem\\WmiApSrv.exe",
L"*\\Windows\\System32\\wbem\\WmiPrvSE.exe",
L"*\\Windows\\ImmersiveControlPanel\\SystemSettings.exe",
L"*\\Windows\\System32\\ctfmon.exe",
L"*\\Windows\\System32\\taskhostw.exe",
L"*\\Windows\\System32\\fontdrvhost.exe",
L"*\\Windows\\System32\\dwm.exe",
L"*\\Windows\\System32\\SearchIndexer.exe",
L"*\\Windows\\System32\\SearchProtocolHost.exe",
L"*\\Windows\\System32\\SearchFilterHost.exe",
L"*\\Windows\\System32\\smartscreen.exe",
L"*\\Windows\\System32\\vssvc.exe",
L"*\\Windows\\System32\\cleanmgr.exe",
L"*\\Windows\\System32\\defrag.exe",
L"*\\Windows\\System32\\chkdsk.exe",
L"*\\Windows\\System32\\conhost.exe",
L"*\\Windows\\System32\\RecoveryDrive.exe"
};
if (String->Length < SuffixLenBytes) return FALSE;
const PCWSTR SafeProcessPatterns[] = {
L"*\\Windows Defender\\*",
L"*\\Windows Defender Advanced Threat Protection\\*",
UNICODE_STRING SuffixPart{};
SuffixPart.Buffer = (PWCH)((PUCHAR)String->Buffer + String->Length - SuffixLenBytes);
SuffixPart.Length = (USHORT)SuffixLenBytes;
SuffixPart.MaximumLength = (USHORT)SuffixLenBytes;
L"*\\Program*\\*",
L"*\\AppData\\Local\\*",
L"*\\AppData\\Roaming\\*",
UNICODE_STRING TargetSuffix;
RtlInitUnicodeString(&TargetSuffix, Suffix);
L"*\\Google\\Update\\*",
L"*\\Google\\Chrome\\Application\\chrome.exe",
L"*\\Internet Explorer\\iexplore.exe",
L"*\\Microsoft\\EdgeUpdate\\*",
L"*\\Microsoft\\Edge\\Application\\msedge.exe",
L"*\\Microsoft\\EdgeWebView\\Application\\*",
L"*\\Mozilla Firefox\\firefox.exe",
L"*\\BraveSoftware\\Brave-Browser\\Application\\brave.exe",
L"*\\Opera Software\\*\\opera.exe",
L"*\\Vivaldi\\Application\\vivaldi.exe",
return RtlEqualUnicodeString(&SuffixPart, &TargetSuffix, TRUE);
}
L"*\\WinRAR\\WinRAR.exe",
L"*\\WinRAR\\UnRAR.exe",
L"*\\7-Zip\\7zG.exe",
L"*\\7-Zip\\7zFM.exe",
L"*\\Bandizip\\Bandizip.exe",
BOOLEAN WildcardMatch(PCWSTR Pattern, PCWSTR String, USHORT StringLengthBytes) {
if (!Pattern || !String) return FALSE;
L"*\\Microsoft Office\\root\\Office*\\*.EXE",
L"*\\Microsoft Office\\root\\Office*\\WINWORD.EXE",
L"*\\Microsoft Office\\root\\Office*\\EXCEL.EXE",
L"*\\Microsoft Office\\root\\Office*\\POWERPNT.EXE",
L"*\\Adobe\\Acrobat*\\*\\Acrobat.exe",
L"*\\Adobe\\Acrobat*\\*\\AcroRd32.exe",
L"*\\Foxit PDF Reader\\FoxitPDFReader.exe",
L"*\\LibreOffice*\\program\\soffice.bin",
L"*\\LibreOffice*\\program\\soffice.exe",
L"*\\Notepad++\\notepad++.exe",
L"*\\Sublime Text*\\sublime_text.exe",
PCWSTR mp = NULL;
PCWSTR cp = NULL;
PCWSTR StringEnd = (PCWSTR)((PUCHAR)String + StringLengthBytes);
L"*\\Microsoft\\Teams\\*\\Teams.exe",
L"*\\Zoom\\bin\\Zoom.exe",
L"*\\Slack\\app-*\\slack.exe",
L"*\\Telegram Desktop\\Telegram.exe",
L"*\\WhatsApp\\WhatsApp.exe",
L"*\\Discord\\app-*\\Discord.exe",
while ((PUCHAR)String < (PUCHAR)StringEnd) {
WCHAR pChar = *Pattern;
WCHAR sChar = *String;
L"*\\Microsoft Visual Studio\\*\\devenv.exe",
L"*\\Microsoft VS Code\\Code.exe",
L"*\\Git\\cmd\\git.exe",
L"*\\Git\\mingw64\\bin\\git.exe",
L"*\\bin\\cmake.exe",
L"*\\nodejs\\node.exe",
L"*\\Android Studio\\bin\\studio64.exe",
L"*\\JetBrains\\*\\bin\\*.exe",
if (pChar == L'*') {
if (!*++Pattern) return TRUE;
mp = Pattern;
cp = String + 1;
}
else if ((RtlDowncaseUnicodeChar(pChar) == RtlDowncaseUnicodeChar(sChar)) || pChar == L'?') {
Pattern++;
String++;
}
else if (mp) {
Pattern = mp;
String = cp++;
}
else {
return FALSE;
}
}
L"*\\Dropbox\\Client\\Dropbox.exe",
L"*\\Google\\Drive\\*\\GoogleDriveFS.exe",
L"*\\Microsoft OneDrive\\OneDrive.exe",
while (*Pattern == L'*') Pattern++;
return !*Pattern && ((PUCHAR)String >= (PUCHAR)StringEnd);
}
L"*\\Sangfor\\*",
L"*\\SogouInput\\*",
L"*\\baidu\\BaiduNetdisk\\*",
L"*\\TortoiseSVN\\*",
L"*\\TortoiseGit\\*",
L"*\\TortoiseOverlays\\*",
L"*\\VideoLAN\\VLC\\vlc.exe",
L"*\\Spotify\\Spotify.exe",
L"*\\obs-studio\\bin\\*\\obs64.exe",
L"*\\DaVinci Resolve\\Resolve.exe",
L"*\\Adobe\\Adobe Premiere Pro*\\Adobe Premiere Pro.exe",
L"*\\Adobe\\Adobe Photoshop*\\Photoshop.exe",
L"*\\Steam\\steam.exe",
L"*\\Steam\\bin\\steamwebhelper.exe",
L"*\\Steam\\steamapps\\*",
L"*\\Epic Games\\Launcher\\Portal\\Binaries\\*\\EpicGamesLauncher.exe",
L"*\\Battle.net\\*\\Battle.net.exe",
L"*\\NVIDIA Corporation\\*",
L"*\\AMD\\*",
L"*\\Intel\\*",
L"*\\Logitech\\*",
L"*\\Razer\\*",
L"*\\Corsair\\*",
L"*\\ASUS\\*"
};
const PCWSTR RegistryBlockList[] = {
L"\\REGISTRY\\MACHINE\\BCD00000000",
L"\\REGISTRY\\MACHINE\\BCD00000000\\*",
L"\\REGISTRY\\MACHINE\\SAM",
L"\\REGISTRY\\MACHINE\\SAM\\*",
L"\\REGISTRY\\MACHINE\\SECURITY",
L"\\REGISTRY\\MACHINE\\SECURITY\\*",
L"\\REGISTRY\\MACHINE\\SYSTEM",
L"\\REGISTRY\\MACHINE\\SYSTEM\\*",
L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\*",
L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce\\*",
L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\*",
L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartupApproved\\*",
L"\\REGISTRY\\USER\\*_Classes\\*\\shell\\open\\command\\*",
L"\\REGISTRY\\USER\\S-1-*\\SOFTWARE\\NetWire\\*",
L"\\REGISTRY\\USER\\S-1-*\\SOFTWARE\\Remcos*\\*",
L"\\REGISTRY\\USER\\S-1-*\\SOFTWARE\\DC3_FEXEC\\*",
L"*\\Image File Execution Options\\*",
L"*\\Classes\\.exe",
L"*\\Classes\\.bat",
L"*\\Classes\\.cmd",
L"*\\Classes\\.com",
L"*\\Classes\\exefile\\*",
L"*\\Classes\\batfile\\*",
L"*\\Classes\\cmdfile\\*",
L"*\\Classes\\comfile\\*",
L"*\\DefaultIcon",
L"*\\DisableAntiSpyware",
L"*\\DisableWindowsUpdateAccess",
L"*\\EnableLUA",
@@ -161,7 +279,6 @@ const PCWSTR RegistryBlockList[] = {
L"*\\LegalNoticeText",
L"*\\Run",
L"*\\RunOnce",
L"*\\Image File Execution Options\\*"
};
const PCWSTR DangerousExtensions[] = {
@@ -181,86 +298,223 @@ const PCWSTR NaturallyCompressedExtensions[] = {
L".jpg", L".jpeg", L".png", L".webp", L".gif",
L".mp3", L".wav", L".aac", L".ogg", L".flac",
L".mp4", L".avi", L".mov", L".wmv", L".mkv",
L".exe", L".dll", L".sys", L".mui",
L".docx", L".xlsx", L".pptx", L".odt", L".ods"
L".exe", L".dll", L".sys", L".mui", L".scr",
L".docx", L".xlsx", L".pptx", L".pdf", L".wps",
L".apk", L".jar", L".class", L".db", L".sqlite"
};
const PCWSTR ProtectedPaths[] = {
L"*\\System32\\drivers\\etc\\hosts",
L"*\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\*",
L"\\Device\\HarddiskVolume*\\Windows\\System32\\*.exe",
L"\\Device\\HarddiskVolume*\\Windows\\System32\\*.dll",
L"\\Device\\HarddiskVolume*\\Windows\\SysWOW64\\*.exe",
L"\\Device\\HarddiskVolume*\\Windows\\SysWOW64\\*.dll",
L"\\Device\\HarddiskVolume*\\bootmgr",
L"\\Device\\HarddiskVolume*\\EFI\\*",
L"*\\PYAS.exe",
L"*\\PYAS_Driver.sys"
L"*\\PYAS_Driver.sys",
L"*\\ProgramData\\PYAS\\*.json",
L"*\\Windows\\System32\\config\\SAM*",
L"*\\Windows\\System32\\config\\SECURITY*",
L"*\\Windows\\System32\\config\\SOFTWARE*",
L"*\\Windows\\System32\\config\\SYSTEM*",
L"*\\Windows\\System32\\config\\DEFAULT*",
L"*\\Windows\\System32\\config\\RegBack\\*",
L"*\\Windows\\System32\\drivers\\*",
L"*\\Windows\\System32\\drivers\\etc\\hosts",
L"*\\Windows\\System32\\*.exe",
L"*\\Windows\\System32\\*.dll",
L"*\\Windows\\SysWOW64\\*.exe",
L"*\\Windows\\SysWOW64\\*.dll",
L"*\\Windows\\Web\\Wallpaper\\*",
L"*\\Windows\\explorer.exe",
L"*\\Windows\\regedit.exe",
L"*\\bootmgr",
L"*\\boot.ini",
L"*\\BOOTNXT",
L"*\\EFI",
L"*\\EFI\\*",
L"*\\Boot",
L"*\\Boot\\*",
L"*\\Recovery",
L"*\\Recovery\\*",
L"*\\System Volume Information\\*",
L"*\\CON",
L"*\\CON\\*",
L"*\\PRN",
L"*\\PRN\\*",
L"*\\AUX",
L"*\\AUX\\*",
L"*\\NUL",
L"*\\NUL\\*",
L"*\\CLOCK$",
L"*\\CLOCK$\\*",
L"*\\COM?",
L"*\\COM?\\*",
L"*\\LPT?",
L"*\\LPT?\\*",
L"*\\COM0",
L"*\\COM0\\*",
L"*\\LPT0",
L"*\\LPT0\\*",
L"*\\$Mft",
L"*\\$Mft\\*",
L"*\\$MftMirr",
L"*\\$MftMirr\\*",
L"*\\$LogFile",
L"*\\$LogFile\\*",
L"*\\$Volume",
L"*\\$Volume\\*",
L"*\\$AttrDef",
L"*\\$AttrDef\\*",
L"*\\$Bitmap",
L"*\\$Bitmap\\*",
L"*\\$Boot",
L"*\\$Boot\\*",
L"*\\$BadClus",
L"*\\$BadClus\\*",
L"*\\$Secure",
L"*\\$Secure\\*",
L"*\\$Upcase",
L"*\\$Upcase\\*",
L"*\\OSDATA",
L"*\\OSDATA\\*",
L"*:*",
L"*<*",
L"*>*",
L"*|*",
};
const PCWSTR TrustedInstallerPatterns[] = {
L"*setup*",
L"*install*",
L"*update*",
L"*unins*",
L"*patch*",
L"*msiexec*",
L"*tiworker*",
L"*trustedinstaller*",
L"*dism*",
L"*pkgmgr*",
L"*wuauclt*",
L"*svchost*",
L"*taskhost*",
L"*googleupdate*",
L"*steam*",
L"*origin*",
L"*battle.net*",
L"*avast*",
L"*avg*"
};
static BOOLEAN HasSuffix(PCUNICODE_STRING String, PCWSTR Suffix) {
if (!String || !String->Buffer || !Suffix) return FALSE;
SIZE_T StringLenChars = String->Length / sizeof(WCHAR);
SIZE_T SuffixLenChars = 0;
while (Suffix[SuffixLenChars] != L'\0') {
SuffixLenChars++;
}
if (StringLenChars < SuffixLenChars) return FALSE;
PCWSTR Ptr = String->Buffer + (StringLenChars - SuffixLenChars);
for (SIZE_T i = 0; i < SuffixLenChars; i++) {
if (RtlDowncaseUnicodeChar(Ptr[i]) != RtlDowncaseUnicodeChar(Suffix[i])) {
return FALSE;
}
}
return TRUE;
}
BOOLEAN WildcardMatch(PCWSTR Pattern, PCWSTR String, USHORT StringLengthBytes) {
if (!Pattern || !String) return FALSE;
PCWSTR mp = NULL;
PCWSTR cp = NULL;
PCWSTR StringEnd = (PCWSTR)((PUCHAR)String + StringLengthBytes);
while (String < StringEnd) {
if (*Pattern == L'*') {
mp = ++Pattern;
cp = String + 1;
}
else if (*Pattern == L'?' || (RtlDowncaseUnicodeChar(*Pattern) == RtlDowncaseUnicodeChar(*String))) {
Pattern++;
String++;
}
else if (mp) {
Pattern = mp;
String = cp++;
}
else {
return FALSE;
}
}
while (*Pattern == L'*') {
Pattern++;
}
return !*Pattern;
}
static NTSTATUS GetProcessImageName(HANDLE ProcessId, PUNICODE_STRING* ImageName) {
NTSTATUS status;
PEPROCESS Process = NULL;
*ImageName = NULL;
status = PsLookupProcessByProcessId(ProcessId, &Process);
if (!NT_SUCCESS(status)) return status;
status = SeLocateProcessImageName(Process, ImageName);
ObDereferenceObject(Process);
return status;
}
BOOLEAN IsProcessTrusted(HANDLE ProcessId) {
if ((ULONG)(ULONG_PTR)ProcessId == GlobalData.PyasPid) return TRUE;
if (ProcessId == (HANDLE)4) return TRUE;
return FALSE;
if (KeGetCurrentIrql() > APC_LEVEL) return FALSE;
PUNICODE_STRING imageFileName = NULL;
NTSTATUS status = GetProcessImageName(ProcessId, &imageFileName);
BOOLEAN isTrusted = FALSE;
if (NT_SUCCESS(status) && imageFileName && imageFileName->Buffer) {
for (SIZE_T i = 0; i < sizeof(SafeSystemBinaries) / sizeof(SafeSystemBinaries[0]); i++) {
if (WildcardMatch(SafeSystemBinaries[i], imageFileName->Buffer, imageFileName->Length)) {
isTrusted = TRUE;
goto cleanup;
}
}
for (SIZE_T i = 0; i < sizeof(SafeProcessPatterns) / sizeof(SafeProcessPatterns[0]); i++) {
if (WildcardMatch(SafeProcessPatterns[i], imageFileName->Buffer, imageFileName->Length)) {
isTrusted = TRUE;
goto cleanup;
}
}
}
cleanup:
if (imageFileName) ExFreePool(imageFileName);
return isTrusted;
}
BOOLEAN IsCriticalSystemProcess(HANDLE ProcessId) {
if ((ULONG)(ULONG_PTR)ProcessId == GlobalData.PyasPid) return TRUE;
if (ProcessId == (HANDLE)4) return TRUE;
if (KeGetCurrentIrql() > APC_LEVEL) return FALSE;
PUNICODE_STRING imageFileName = NULL;
NTSTATUS status = GetProcessImageName(ProcessId, &imageFileName);
BOOLEAN isCritical = FALSE;
if (NT_SUCCESS(status) && imageFileName && imageFileName->Buffer) {
for (SIZE_T i = 0; i < sizeof(CriticalSystemBinaries) / sizeof(CriticalSystemBinaries[0]); i++) {
if (WildcardMatch(CriticalSystemBinaries[i], imageFileName->Buffer, imageFileName->Length)) {
isCritical = TRUE;
goto cleanup;
}
}
}
cleanup:
if (imageFileName) ExFreePool(imageFileName);
return isCritical;
}
BOOLEAN IsInstallerProcess(HANDLE ProcessId) {
return IsProcessTrusted(ProcessId);
}
BOOLEAN IsTargetProtected(HANDLE ProcessId) {
if ((ULONG)(ULONG_PTR)ProcessId == GlobalData.PyasPid) return TRUE;
return FALSE;
}
BOOLEAN IsInstallerProcess(HANDLE ProcessId) {
if (KeGetCurrentIrql() > APC_LEVEL) return FALSE;
NTSTATUS status;
BOOLEAN isTrusted = FALSE;
PEPROCESS Process = NULL;
PUNICODE_STRING imageFileName = NULL;
status = PsLookupProcessByProcessId(ProcessId, &Process);
if (!NT_SUCCESS(status)) return FALSE;
status = SeLocateProcessImageName(Process, &imageFileName);
if (NT_SUCCESS(status) && imageFileName) {
if (imageFileName->Buffer) {
for (int i = 0; i < sizeof(TrustedInstallerPatterns) / sizeof(TrustedInstallerPatterns[0]); i++) {
if (WildcardMatch(TrustedInstallerPatterns[i], imageFileName->Buffer, imageFileName->Length)) {
isTrusted = TRUE;
break;
}
}
}
ExFreePool(imageFileName);
}
ObDereferenceObject(Process);
return isTrusted;
}
BOOLEAN CheckRegistryRule(PCUNICODE_STRING KeyName) {
if (!KeyName || !KeyName->Buffer) return FALSE;
if (KeyName->Length < 4 * sizeof(WCHAR)) return FALSE;
for (int i = 0; i < sizeof(RegistryBlockList) / sizeof(RegistryBlockList[0]); i++) {
if (WildcardMatch(RegistryBlockList[i], KeyName->Buffer, KeyName->Length)) return TRUE;
}
@@ -269,11 +523,8 @@ BOOLEAN CheckRegistryRule(PCUNICODE_STRING KeyName) {
BOOLEAN CheckFileExtensionRule(PCUNICODE_STRING FileName) {
if (!FileName || !FileName->Buffer) return FALSE;
for (int i = 0; i < sizeof(DangerousExtensions) / sizeof(DangerousExtensions[0]); i++) {
if (HasSuffix(FileName, DangerousExtensions[i])) {
return TRUE;
}
if (HasSuffix(FileName, DangerousExtensions[i])) return TRUE;
}
return FALSE;
}
@@ -281,6 +532,10 @@ BOOLEAN CheckFileExtensionRule(PCUNICODE_STRING FileName) {
BOOLEAN CheckProtectedPathRule(PCUNICODE_STRING FileName) {
if (!FileName || !FileName->Buffer) return FALSE;
if (WildcardMatch(L"*\\Windows\\System32\\config\\systemprofile*", FileName->Buffer, FileName->Length)) {
return FALSE;
}
for (int i = 0; i < sizeof(ProtectedPaths) / sizeof(ProtectedPaths[0]); i++) {
if (WildcardMatch(ProtectedPaths[i], FileName->Buffer, FileName->Length)) return TRUE;
}
@@ -309,19 +564,13 @@ static BOOLEAN IsHighEntropy(PVOID Buffer, ULONG Length) {
}
ULONG ExpectedAvg = ScanLen / 256;
if (MaxFreq < (ExpectedAvg + HIGH_ENTROPY_THRESHOLD)) {
return TRUE;
}
return FALSE;
return (MaxFreq < (ExpectedAvg + HIGH_ENTROPY_THRESHOLD));
}
static BOOLEAN IsNaturallyCompressed(PCUNICODE_STRING FileName) {
if (!FileName || !FileName->Buffer) return FALSE;
for (int i = 0; i < sizeof(NaturallyCompressedExtensions) / sizeof(NaturallyCompressedExtensions[0]); i++) {
if (HasSuffix(FileName, NaturallyCompressedExtensions[i])) {
return TRUE;
}
if (HasSuffix(FileName, NaturallyCompressedExtensions[i])) return TRUE;
}
return FALSE;
}
@@ -330,9 +579,13 @@ static BOOLEAN IsNoisyRansomPath(PCUNICODE_STRING FileName) {
if (!FileName || !FileName->Buffer) return FALSE;
if (WildcardMatch(L"*\\Windows\\Temp\\*", FileName->Buffer, FileName->Length) ||
WildcardMatch(L"*\\AppData\\Local\\*", FileName->Buffer, FileName->Length) ||
WildcardMatch(L"*\\Windows\\SystemTemp\\*", FileName->Buffer, FileName->Length) ||
WildcardMatch(L"*\\Program Files*\\*\\Temp\\*", FileName->Buffer, FileName->Length) ||
WildcardMatch(L"*\\Windows\\Prefetch\\*", FileName->Buffer, FileName->Length) ||
WildcardMatch(L"*\\Windows\\Logs\\*", FileName->Buffer, FileName->Length) ||
WildcardMatch(L"*\\Profiles\\*", FileName->Buffer, FileName->Length) ||
WildcardMatch(L"*\\Program*\\*", FileName->Buffer, FileName->Length) ||
WildcardMatch(L"*\\AppData\\Local\\*", FileName->Buffer, FileName->Length) ||
WildcardMatch(L"*\\User Data\\*", FileName->Buffer, FileName->Length) ||
WildcardMatch(L"*$Recycle.Bin*", FileName->Buffer, FileName->Length)) {
return TRUE;
}
@@ -341,27 +594,13 @@ static BOOLEAN IsNoisyRansomPath(PCUNICODE_STRING FileName) {
static BOOLEAN IsExplorerProcess(HANDLE ProcessId) {
if (KeGetCurrentIrql() > APC_LEVEL) return FALSE;
NTSTATUS status;
BOOLEAN isExplorer = FALSE;
PEPROCESS Process = NULL;
PUNICODE_STRING imageFileName = NULL;
status = PsLookupProcessByProcessId(ProcessId, &Process);
if (!NT_SUCCESS(status)) return FALSE;
status = SeLocateProcessImageName(Process, &imageFileName);
if (NT_SUCCESS(status) && imageFileName) {
if (imageFileName->Buffer) {
if (HasSuffix(imageFileName, L"explorer.exe")) {
isExplorer = TRUE;
}
}
NTSTATUS status = GetProcessImageName(ProcessId, &imageFileName);
BOOLEAN isExplorer = FALSE;
if (NT_SUCCESS(status) && imageFileName && imageFileName->Buffer) {
if (HasSuffix(imageFileName, L"\\explorer.exe")) isExplorer = TRUE;
ExFreePool(imageFileName);
}
ObDereferenceObject(Process);
return isExplorer;
}
@@ -369,9 +608,7 @@ BOOLEAN CheckRansomActivity(HANDLE ProcessId, PUNICODE_STRING FileName, PVOID Bu
if (IsNoisyRansomPath(FileName)) return FALSE;
if (!IsWrite) {
if (IsExplorerProcess(ProcessId)) {
return FALSE;
}
if (IsExplorerProcess(ProcessId)) return FALSE;
}
LARGE_INTEGER Now = { 0 };
@@ -384,14 +621,12 @@ BOOLEAN CheckRansomActivity(HANDLE ProcessId, PUNICODE_STRING FileName, PVOID Bu
SuspiciousWrite = TRUE;
}
}
ExAcquireFastMutex(&GlobalData.TrackerMutex);
if (IsWrite && !SuspiciousWrite) {
ExReleaseFastMutex(&GlobalData.TrackerMutex);
return FALSE;
}
ExAcquireFastMutex(&GlobalData.TrackerMutex);
PRANSOM_TRACKER Tracker = NULL;
PRANSOM_TRACKER EmptySlot = NULL;
@@ -418,25 +653,29 @@ BOOLEAN CheckRansomActivity(HANDLE ProcessId, PUNICODE_STRING FileName, PVOID Bu
}
}
LARGE_INTEGER Diff = { 0 };
LARGE_INTEGER Diff;
Diff.QuadPart = Now.QuadPart - Tracker->LastActivityTime.QuadPart;
if (Diff.QuadPart > (RANSOM_TIME_WINDOW_MS * 10000LL)) {
Tracker->ActivityCount = 0;
Tracker->LastActivityTime = Now;
}
else {
Tracker->LastActivityTime = Now;
}
ULONG Weight = 1;
if (IsWrite) {
Weight = SuspiciousWrite ? 2 : 1;
}
else {
Weight = 2;
}
Tracker->ActivityCount += Weight;
if (Tracker->ActivityCount >= RANSOM_COUNT_THRESHOLD) {
Result = TRUE;
}
ExReleaseFastMutex(&GlobalData.TrackerMutex);
return Result;
}
@@ -452,34 +691,26 @@ NTSTATUS SendMessageToUser(ULONG Code, ULONG Pid, PWCHAR Path, USHORT PathSize)
if (Path && PathSize > 0) {
size_t MaxSize = sizeof(msg.Path) - sizeof(WCHAR);
size_t BytesToCopy = PathSize;
if (BytesToCopy > MaxSize) {
BytesToCopy = MaxSize;
}
if (BytesToCopy > MaxSize) BytesToCopy = MaxSize;
__try {
RtlCopyMemory(msg.Path, Path, BytesToCopy);
msg.Path[BytesToCopy / sizeof(WCHAR)] = L'\0';
}
__except (EXCEPTION_EXECUTE_HANDLER) {
return STATUS_ACCESS_VIOLATION;
}
msg.Path[BytesToCopy / sizeof(WCHAR)] = L'\0';
}
if (!ExAcquireRundownProtection(&GlobalData.PortRundown)) {
return STATUS_PORT_DISCONNECTED;
}
NTSTATUS status = STATUS_SUCCESS;
NTSTATUS status = STATUS_PORT_DISCONNECTED;
if (GlobalData.ClientPort) {
LARGE_INTEGER timeout{};
LARGE_INTEGER timeout;
timeout.QuadPart = -(5 * 10000);
PFLT_PORT Port = GlobalData.ClientPort;
status = FltSendMessage(GlobalData.FilterHandle, &Port, &msg, sizeof(msg), NULL, NULL, &timeout);
}
else {
status = STATUS_PORT_DISCONNECTED;
status = FltSendMessage(GlobalData.FilterHandle, &GlobalData.ClientPort, &msg, sizeof(msg), NULL, NULL, &timeout);
}
ExReleaseRundownProtection(&GlobalData.PortRundown);
+6 -6
View File
@@ -9,14 +9,14 @@ Antivirus software written in Python and C++ that blocks threats through deep le
Python 3.10 is recommended. Other Python versions may require different pip commands.
```
pip install numpy==1.26.4
pip install onnxruntime==1.18.1
pip install pefile==2023.2.7
pip install Pillow==11.0.0
pip install pyperclip==1.9.0
pip install PySide6==6.9.1
pip install requests==2.32.4
pip install PySide6==6.9.1
pip install yara-python==4.5.4
pip install Pillow==11.0.0
pip install numpy==1.26.4
pip install tensorflow==2.10.0
pip install tf2onnx==1.13.0
pip install onnxruntime==1.18.1
```
## File Information