Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9eb55deedf | ||
|
|
6e76b5b8eb | ||
|
|
491b0da83d | ||
|
|
5d2c17e940 | ||
|
|
0497c4a9e7 | ||
|
|
6d0765848b | ||
|
|
40c4ae71bd | ||
|
|
8edba10dff | ||
|
|
85aa7bc652 | ||
|
|
854ad1db07 | ||
|
|
955600a1e1 | ||
|
|
b739134d85 | ||
|
|
723152566d | ||
|
|
678b045e0e | ||
|
|
681f4df49a | ||
|
|
b19f7d7098 | ||
|
|
daaae3ec10 |
No files matched your search
@@ -1,5 +1,5 @@
|
||||
from PIL import Image
|
||||
import numpy, pefile, os
|
||||
import numpy, os
|
||||
|
||||
####################################################################################################
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user