Files
PYAS/PYAS_Driver.py
T
2026-10-09 12:12:42 +08:00

1181 lines
38 KiB
Python

from PYAS_Diagnostics import log_exception
import os
import time
import winreg
import threading
import ctypes
import ctypes.wintypes
from PYAS_WinAPI import (
LUID,
PYAS_FULL_MESSAGE,
PYAS_USER_MESSAGE,
SERVICE_STATUS_PROCESS,
TOKEN_PRIVILEGES,
)
from PYAS_WinAPI import (
ERROR_NOT_FOUND,
ERROR_OPERATION_ABORTED,
FLT_PORT_FLAG_SYNC_HANDLE,
HRESULT_IO_PENDING,
OVERLAPPED,
PYAS_CONNECTION_CONTEXT,
PYAS_CONNECTION_MAGIC,
PYAS_CONNECTION_VERSION,
WAIT_OBJECT_0,
WAIT_TIMEOUT,
)
class DriverMixin:
def _query_service_state_handle(self, service):
status = SERVICE_STATUS_PROCESS()
needed = ctypes.wintypes.DWORD(0)
buffer = ctypes.cast(ctypes.byref(status), ctypes.POINTER(ctypes.c_ubyte))
if not self.advapi32.QueryServiceStatusEx(
service, 0, buffer, ctypes.sizeof(status), ctypes.byref(needed)
):
return None, ctypes.get_last_error()
return int(status.dwCurrentState), 0
def _query_driver_service_state(self):
scm = self.advapi32.OpenSCManagerW(None, None, 0x0001)
if not scm:
return None
service = None
try:
service = self.advapi32.OpenServiceW(scm, "PYAS_Driver", 0x0004)
if not service:
return None
state, _ = self._query_service_state_handle(service)
return state
finally:
if service:
self.advapi32.CloseServiceHandle(service)
self.advapi32.CloseServiceHandle(scm)
def _get_driver_client_image_path(self):
buffer = ctypes.create_unicode_buffer(32768)
size = ctypes.wintypes.DWORD(len(buffer))
if not self.kernel32.QueryFullProcessImageNameW(
self.kernel32.GetCurrentProcess(), 0, buffer, ctypes.byref(size)
):
return None
image_path = os.path.abspath(buffer.value)
drive, tail = os.path.splitdrive(image_path)
if not drive or not tail:
return None
device_buffer = ctypes.create_unicode_buffer(32768)
if not self.kernel32.QueryDosDeviceW(drive, device_buffer, len(device_buffer)):
return None
return device_buffer.value.rstrip("\\") + tail
def _configure_driver_identity(self):
image_path = self._get_driver_client_image_path()
if not image_path:
return False, ctypes.get_last_error() or 1
try:
access = winreg.KEY_SET_VALUE | getattr(winreg, "KEY_WOW64_64KEY", 0)
with winreg.CreateKeyEx(
winreg.HKEY_LOCAL_MACHINE,
r"SYSTEM\CurrentControlSet\Services\PYAS_Driver",
0,
access,
) as key:
winreg.SetValueEx(key, "ClientImagePath", 0, winreg.REG_SZ, image_path)
return True, 0
except OSError as e:
log_exception("PYAS_Driver.DriverMixin._configure_driver_identity:74")
return False, int(getattr(e, "winerror", 0) or 1)
def _ensure_driver_service(self):
desired_service_access = 0x0002 | 0x0004 | 0x0010 | 0x00010000
dependencies = ctypes.create_unicode_buffer("FltMgr\0\0")
dependencies_ptr = ctypes.cast(dependencies, ctypes.wintypes.LPCWSTR)
last_error = 0
for attempt in range(20):
scm = self.advapi32.OpenSCManagerW(None, None, 0x0001 | 0x0002)
if not scm:
return False, ctypes.get_last_error()
service = None
try:
ctypes.set_last_error(0)
service = self.advapi32.CreateServiceW(
scm,
"PYAS_Driver",
"PYAS_Driver",
desired_service_access,
0x00000001,
0x00000003,
0x00000001,
self.path_drivers,
"FSFilter Activity Monitor",
None,
dependencies_ptr,
None,
None,
)
if not service:
last_error = ctypes.get_last_error()
if last_error in (1073, 1078):
service = self.advapi32.OpenServiceW(
scm, "PYAS_Driver", desired_service_access
)
if not service:
last_error = ctypes.get_last_error()
elif last_error == 1072:
pass
if service:
ctypes.set_last_error(0)
changed = self.advapi32.ChangeServiceConfigW(
service,
0x00000001,
0x00000003,
0x00000001,
self.path_drivers,
"FSFilter Activity Monitor",
None,
dependencies_ptr,
None,
None,
None,
)
if not changed:
last_error = ctypes.get_last_error()
return False, last_error
return True, 0
finally:
if service:
self.advapi32.CloseServiceHandle(service)
self.advapi32.CloseServiceHandle(scm)
if last_error != 1072:
break
if attempt < 19:
time.sleep(0.05)
return False, last_error or 1
def _start_driver_service(self):
scm = self.advapi32.OpenSCManagerW(None, None, 0x0001)
if not scm:
return False, ctypes.get_last_error()
service = None
try:
service = self.advapi32.OpenServiceW(scm, "PYAS_Driver", 0x0004 | 0x0010)
if not service:
return False, ctypes.get_last_error()
state, error = self._query_service_state_handle(service)
if state in (2, 4):
return True, 0
if error:
return False, error
ctypes.set_last_error(0)
if self.advapi32.StartServiceW(service, 0, None):
return True, 0
error = ctypes.get_last_error()
if error == 1056:
return True, 0
return False, error
finally:
if service:
self.advapi32.CloseServiceHandle(service)
self.advapi32.CloseServiceHandle(scm)
def uninstall_system_driver(self):
if not self.stop_system_driver():
return False, 1051
return self._delete_driver_service()
def _delete_driver_service(self, timeout=15.0):
deadline = time.monotonic() + timeout
last_error = 0
delete_requested = False
while time.monotonic() < deadline:
scm = self.advapi32.OpenSCManagerW(None, None, 0x0001)
if not scm:
return False, ctypes.get_last_error()
service = None
try:
ctypes.set_last_error(0)
service = self.advapi32.OpenServiceW(scm, "PYAS_Driver", 0x0004 | 0x00010000)
if not service:
last_error = ctypes.get_last_error()
if last_error == 1060:
return True, 0
if last_error != 1072:
return False, last_error
else:
state, status_error = self._query_service_state_handle(service)
if status_error:
return False, status_error
if state not in (2, 3, 4) and not delete_requested:
ctypes.set_last_error(0)
if self.advapi32.DeleteService(service):
delete_requested = True
last_error = 1072
else:
last_error = ctypes.get_last_error()
if last_error == 1060:
return True, 0
if last_error == 1072:
delete_requested = True
else:
return False, last_error
elif state in (2, 3, 4):
last_error = 1051
finally:
if service:
self.advapi32.CloseServiceHandle(service)
self.advapi32.CloseServiceHandle(scm)
time.sleep(0.1)
return False, last_error or 1072
def install_system_driver(self):
try:
ensured, service_error = self._ensure_driver_service()
if not ensured:
self.write_log(
"WARN",
"Driver Service",
detail=f"CreateServiceW/ChangeServiceConfigW failed: 0x{service_error & 0xFFFFFFFF:08X}",
success=False,
)
return False
configured, identity_error = self._configure_driver_identity()
if not configured:
self.write_log(
"WARN",
"Driver Identity",
detail=f"ClientImagePath configuration failed: 0x{identity_error & 0xFFFFFFFF:08X}",
success=False,
)
return False
self._reg_write(
winreg.HKEY_LOCAL_MACHINE,
r"SYSTEM\CurrentControlSet\Services\PYAS_Driver\Instances",
"DefaultInstance",
winreg.REG_SZ,
"PYAS Instance",
)
self._reg_write(
winreg.HKEY_LOCAL_MACHINE,
r"SYSTEM\CurrentControlSet\Services\PYAS_Driver\Instances\PYAS Instance",
"Altitude",
winreg.REG_SZ,
"320000",
)
self._reg_write(
winreg.HKEY_LOCAL_MACHINE,
r"SYSTEM\CurrentControlSet\Services\PYAS_Driver\Instances\PYAS Instance",
"Flags",
winreg.REG_DWORD,
0,
)
started, start_error = self._start_driver_service()
if not started:
self.write_log(
"WARN",
"Driver Service",
detail=f"StartServiceW failed: 0x{start_error & 0xFFFFFFFF:08X}",
success=False,
)
return False
final_state = None
last_start_attempt = time.monotonic()
deadline = time.monotonic() + 3.0
while time.monotonic() < deadline:
service_state = self._query_driver_service_state()
if service_state == 4:
final_state = self._query_driver_state()
if final_state == 2:
return True
if final_state in (4, 5):
break
elif service_state == 1:
now = time.monotonic()
if now - last_start_attempt >= 0.1:
started, start_error = self._start_driver_service()
last_start_attempt = now
if not started:
break
elif service_state is None:
break
time.sleep(0.02)
if self.check_system_driver():
self.stop_system_driver()
detail = (
"Driver entered unload-retry state during startup"
if final_state == 4
else "Driver did not reach running state"
)
self.write_log("WARN", "Driver Protection", detail=detail, success=False)
return False
except Exception as e:
log_exception("PYAS_Driver.DriverMixin.install_system_driver:267")
self.write_log("WARN", "install_system_driver", detail=str(e), success=False)
return False
def _driver_handle_value(self, handle):
if handle is None:
return None
value = getattr(handle, "value", handle)
if value is None:
return None
try:
return int(value)
except Exception:
log_exception("PYAS_Driver.DriverMixin._driver_handle_value:281")
return None
def _connect_driver_port(self, asynchronous=False):
context = PYAS_CONNECTION_CONTEXT()
context.Size = ctypes.sizeof(context)
context.Version = PYAS_CONNECTION_VERSION
context.Magic = PYAS_CONNECTION_MAGIC
context.ProcessId = os.getpid()
temp_port = ctypes.wintypes.HANDLE()
status = self.fltlib.FilterConnectCommunicationPort(
"\\PYAS_Output_Pipe",
0 if asynchronous else FLT_PORT_FLAG_SYNC_HANDLE,
ctypes.byref(context),
ctypes.sizeof(context),
None,
ctypes.byref(temp_port),
)
if status != 0:
return None
return temp_port
def _detach_driver_port(self, expected_port=None):
expected_value = self._driver_handle_value(expected_port)
with self.lock_driver:
current_port = self.driver_port
current_value = self._driver_handle_value(current_port)
if current_value is None:
return None
if expected_port is not None and current_value != expected_value:
return None
self.driver_port = None
return current_port
def _close_driver_port(self, expected_port=None):
port = self._detach_driver_port(expected_port)
if not port:
return False
try:
self.kernel32.CloseHandle(port)
except Exception:
log_exception("PYAS_Driver.DriverMixin._close_driver_port:326")
pass
return True
def _driver_listener_should_run(self):
if self.driver_stop_event.is_set():
return False
with self.lock_config:
return bool(self.pyas_config.get("driver_switch", False))
def start_driver_listener(self, wait_ready=True):
with self.lock_driver:
current = self.driver_listener_thread
if current and current.is_alive():
return (
self.driver_listener_ready_event.is_set()
and not self.driver_stop_event.is_set()
)
self.driver_stop_event.clear()
self.driver_listener_ready_event.clear()
self.driver_listener_failed_event.clear()
thread = threading.Thread(target=self.pipe_server_thread, daemon=True)
self.driver_listener_thread = thread
thread.start()
if not wait_ready:
return True
deadline = time.monotonic() + 5.0
while time.monotonic() < deadline:
if self.driver_listener_ready_event.wait(0.02):
return True
if self.driver_listener_failed_event.is_set() or not thread.is_alive():
break
self._stop_driver_listener()
return False
def _stop_driver_listener(self):
self.driver_stop_event.set()
with self.lock_driver:
thread = self.driver_listener_thread
port = self.driver_port
if port:
try:
self.kernel32.CancelIoEx(port, None)
except Exception:
log_exception("PYAS_Driver.DriverMixin._stop_driver_listener:373")
pass
if thread and thread is not threading.current_thread():
thread.join(timeout=2.0)
alive = bool(thread and thread.is_alive())
if not alive:
with self.lock_driver:
if self.driver_listener_thread is thread:
self.driver_listener_thread = None
self.driver_listener_ready_event.clear()
self._close_driver_port()
return not alive
def _resume_driver_listener(self):
if not self.check_system_driver():
return False
with self.lock_config:
enabled = bool(self.pyas_config.get("driver_switch", False))
if not enabled:
return False
self._close_driver_port()
return self.start_driver_listener(wait_ready=True)
def _set_driver_unload_authorization(self, enabled):
msg = PYAS_USER_MESSAGE()
msg.Command = 5 if enabled else 6
msg.Path = ""
for _ in range(3):
if not self._ensure_driver_port():
time.sleep(0.1)
continue
with self.lock_driver:
current_port = self.driver_port
if not current_port:
continue
bytes_returned = ctypes.wintypes.DWORD(0)
try:
status = self.fltlib.FilterSendMessage(
current_port,
ctypes.byref(msg),
ctypes.sizeof(msg),
None,
0,
ctypes.byref(bytes_returned),
)
except Exception as e:
log_exception("PYAS_Driver.DriverMixin._set_driver_unload_authorization:427")
self.write_log(
"WARN", "Driver Unload Authorization", detail=str(e), success=False
)
status = -1
if status == 0:
return True
self._close_driver_port(current_port)
time.sleep(0.1)
return False
def _ensure_driver_port(self):
for _ in range(20):
with self.lock_driver:
if self.driver_port:
return True
temp_port = self._connect_driver_port()
if temp_port:
with self.lock_driver:
if not self.driver_port:
self.driver_port = temp_port
return True
try:
self.kernel32.CloseHandle(temp_port)
except Exception:
log_exception("PYAS_Driver.DriverMixin._ensure_driver_port:454")
pass
return True
time.sleep(0.05)
return False
def _query_driver_state(self):
for use_existing in (True, False):
local_port = None
port = None
if use_existing:
with self.lock_driver:
if self.driver_port:
port = self.driver_port
if not port:
continue
else:
local_port = self._connect_driver_port()
if not local_port:
return None
port = local_port
msg = PYAS_USER_MESSAGE()
msg.Command = 7
msg.Path = ""
state = ctypes.wintypes.DWORD(0)
bytes_returned = ctypes.wintypes.DWORD(0)
try:
status = self.fltlib.FilterSendMessage(
port,
ctypes.byref(msg),
ctypes.sizeof(msg),
ctypes.byref(state),
ctypes.sizeof(state),
ctypes.byref(bytes_returned),
)
if status == 0 and bytes_returned.value == ctypes.sizeof(state):
return int(state.value)
except Exception:
log_exception("PYAS_Driver.DriverMixin._query_driver_state:496")
pass
finally:
if local_port:
try:
self.kernel32.CloseHandle(local_port)
except Exception:
log_exception("PYAS_Driver.DriverMixin._query_driver_state:502")
pass
if use_existing:
self._close_driver_port(port)
return None
def _enable_token_privilege(self, privilege_name):
token = ctypes.wintypes.HANDLE()
desired_access = 0x0020 | 0x0008
if not self.advapi32.OpenProcessToken(
self.kernel32.GetCurrentProcess(), desired_access, ctypes.byref(token)
):
return None, ctypes.get_last_error()
luid = LUID()
if not self.advapi32.LookupPrivilegeValueW(None, privilege_name, ctypes.byref(luid)):
error = ctypes.get_last_error()
self.kernel32.CloseHandle(token)
return None, error
new_state = TOKEN_PRIVILEGES()
new_state.PrivilegeCount = 1
new_state.Privileges[0].Luid = luid
new_state.Privileges[0].Attributes = 0x00000002
previous_state = TOKEN_PRIVILEGES()
return_length = ctypes.wintypes.DWORD(0)
ctypes.set_last_error(0)
adjusted = self.advapi32.AdjustTokenPrivileges(
token,
False,
ctypes.byref(new_state),
ctypes.sizeof(previous_state),
ctypes.byref(previous_state),
ctypes.byref(return_length),
)
error = ctypes.get_last_error()
if not adjusted or error == 1300:
self.kernel32.CloseHandle(token)
return None, error or 1
return (token, previous_state, return_length.value), 0
def _restore_token_privilege(self, privilege_state):
if not privilege_state:
return
token, previous_state, previous_length = privilege_state
try:
if previous_length:
self.advapi32.AdjustTokenPrivileges(
token, False, ctypes.byref(previous_state), 0, None, None
)
finally:
self.kernel32.CloseHandle(token)
def _filter_unload_with_privilege(self, filter_name):
result = {
"status": None,
"privilege_error": 0,
"authorization_failed": False,
"exception": None,
"attempts": 0,
}
privilege_state = None
unload_authorized = False
self.driver_unload_worker = None
self.driver_unload_result = result
try:
privilege_state, privilege_error = self._enable_token_privilege("SeLoadDriverPrivilege")
if not privilege_state:
result["privilege_error"] = privilege_error
return result
retryable_statuses = {0x80070522, 0x80070005, 0x800700AA}
for delay in (0.0, 0.05, 0.15):
if delay:
time.sleep(delay)
if not self.check_system_driver():
result["status"] = 0
unload_authorized = False
return result
if not self._set_driver_unload_authorization(True):
continue
unload_authorized = True
result["attempts"] += 1
unload_status = self.fltlib.FilterUnload(filter_name)
result["status"] = unload_status
if unload_status == 0:
unload_authorized = False
return result
revoked = False
if self.check_system_driver():
try:
revoked = self._set_driver_unload_authorization(False)
except Exception:
log_exception("PYAS_Driver.DriverMixin._filter_unload_with_privilege:606")
revoked = False
unload_authorized = not revoked
if (unload_status & 0xFFFFFFFF) not in retryable_statuses:
return result
if result["status"] is None:
result["authorization_failed"] = True
except Exception as e:
log_exception("PYAS_Driver.DriverMixin._filter_unload_with_privilege:616")
result["exception"] = str(e)
finally:
if unload_authorized and self.check_system_driver():
try:
self._set_driver_unload_authorization(False)
except Exception:
log_exception("PYAS_Driver.DriverMixin._filter_unload_with_privilege:622")
pass
self._restore_token_privilege(privilege_state)
return result
def stop_system_driver(self):
with self.lock_driver_unload:
runtime_unloaded = False
unload_confirmed = False
try:
if not self._stop_driver_listener():
self.write_log(
"WARN",
"Driver Protection",
detail="Driver listener cancellation did not complete",
success=False,
)
return False
if not self.check_system_driver():
runtime_unloaded = True
unload_confirmed = True
else:
if not self._ensure_driver_port():
if not self.check_system_driver():
runtime_unloaded = True
unload_confirmed = True
else:
self.write_log(
"WARN",
"Driver Protection",
detail="Control port unavailable",
success=False,
)
return False
if not runtime_unloaded:
unload_result = self._filter_unload_with_privilege("PYAS_Driver")
if unload_result["privilege_error"]:
error = unload_result["privilege_error"]
self.write_log(
"WARN",
"Driver Protection",
detail=f"SeLoadDriverPrivilege unavailable: 0x{error & 0xFFFFFFFF:08X}",
success=False,
)
return False
if unload_result["authorization_failed"]:
self.write_log(
"WARN",
"Driver Protection",
detail="Unload authorization rejected",
success=False,
)
return False
if unload_result["exception"]:
self.write_log(
"WARN",
"stop_system_driver",
detail=unload_result["exception"],
success=False,
)
return False
unload_status = unload_result["status"]
if unload_status == 0:
runtime_unloaded = True
unload_confirmed = True
elif not self.check_system_driver():
runtime_unloaded = True
unload_confirmed = True
else:
attempts = unload_result["attempts"]
self.write_log(
"WARN",
"Driver Protection",
detail=f"FilterUnload failed after {attempts} attempt(s): 0x{unload_status & 0xFFFFFFFF:08X}",
success=False,
)
return False
self._close_driver_port()
if unload_confirmed:
deadline = time.monotonic() + 0.5
while time.monotonic() < deadline and self.check_system_driver():
time.sleep(0.01)
if self.check_system_driver():
self.write_log(
"INFO",
"Driver Protection",
detail="Filter unloaded; SCM state is still settling",
)
return runtime_unloaded
except Exception as e:
log_exception("PYAS_Driver.DriverMixin.stop_system_driver:689")
self.write_log("WARN", "stop_system_driver", detail=str(e), success=False)
return False
finally:
if not runtime_unloaded and self.check_system_driver():
self._resume_driver_listener()
def check_system_driver(self):
runtime_state = self._query_driver_state()
if runtime_state in (1, 2, 3, 4):
return True
service_state = self._query_driver_service_state()
return service_state in (2, 3, 4)
def clear_driver_rules(self):
with self.lock_driver:
if not self.driver_port:
return False
msg = PYAS_USER_MESSAGE()
msg.Command = 4
msg.Path = ""
bytes_returned = ctypes.wintypes.DWORD(0)
try:
return (
self.fltlib.FilterSendMessage(
self.driver_port,
ctypes.byref(msg),
ctypes.sizeof(msg),
None,
0,
ctypes.byref(bytes_returned),
)
== 0
)
except Exception:
log_exception("PYAS_Driver.DriverMixin.clear_driver_rules:723")
return False
def load_driver_rule_file(self, json_path):
with self.lock_driver:
if not self.driver_port:
return False
norm_path = os.path.abspath(json_path)
if not os.path.exists(norm_path):
return False
nt_path = f"\\??\\{norm_path}"
msg = PYAS_USER_MESSAGE()
msg.Command = 3
msg.Path = nt_path
bytes_returned = ctypes.wintypes.DWORD(0)
try:
return (
self.fltlib.FilterSendMessage(
self.driver_port,
ctypes.byref(msg),
ctypes.sizeof(msg),
None,
0,
ctypes.byref(bytes_returned),
)
== 0
)
except Exception:
log_exception("PYAS_Driver.DriverMixin.load_driver_rule_file:751")
return False
def _cancel_driver_receive(self, port, overlapped):
try:
ctypes.set_last_error(0)
cancelled = self.kernel32.CancelIoEx(port, ctypes.byref(overlapped))
error = ctypes.get_last_error()
if not cancelled and error not in (0, ERROR_NOT_FOUND):
return False
wait_status = self.kernel32.WaitForSingleObject(overlapped.hEvent, 1000)
if wait_status != WAIT_OBJECT_0:
return False
transferred = ctypes.wintypes.DWORD(0)
self.kernel32.GetOverlappedResult(
port, ctypes.byref(overlapped), ctypes.byref(transferred), False
)
return True
except Exception:
log_exception("PYAS_Driver.DriverMixin._cancel_driver_receive:774")
return False
def _receive_driver_message(self, port):
message = PYAS_FULL_MESSAGE()
overlapped = OVERLAPPED()
event_handle = self.kernel32.CreateEventW(None, True, False, None)
if not event_handle:
return "error", None
overlapped.hEvent = event_handle
try:
status = self.fltlib.FilterGetMessage(
port,
ctypes.byref(message),
ctypes.sizeof(PYAS_FULL_MESSAGE),
ctypes.byref(overlapped),
)
if status == 0:
return "message", message
if (status & 0xFFFFFFFF) != HRESULT_IO_PENDING:
return "disconnect", None
while True:
if self.driver_stop_event.is_set():
self._cancel_driver_receive(port, overlapped)
return "stop", None
wait_status = self.kernel32.WaitForSingleObject(event_handle, 20)
if wait_status == WAIT_TIMEOUT:
continue
if wait_status != WAIT_OBJECT_0:
self._cancel_driver_receive(port, overlapped)
return "error", None
transferred = ctypes.wintypes.DWORD(0)
if self.kernel32.GetOverlappedResult(
port, ctypes.byref(overlapped), ctypes.byref(transferred), False
):
return "message", message
error = ctypes.get_last_error()
if error == ERROR_OPERATION_ABORTED and self.driver_stop_event.is_set():
return "stop", None
return "disconnect", None
finally:
self.kernel32.CloseHandle(event_handle)
def pipe_server_thread(self):
owned_port = None
ready = False
try:
while self._driver_listener_should_run():
temp_port = self._connect_driver_port(asynchronous=True)
if not temp_port:
self.driver_stop_event.wait(0.02)
continue
if not self._driver_listener_should_run():
self.kernel32.CloseHandle(temp_port)
break
with self.lock_driver:
if self.driver_port:
accepted = False
else:
self.driver_port = temp_port
owned_port = temp_port
accepted = True
if not accepted:
self.kernel32.CloseHandle(temp_port)
self.driver_stop_event.wait(0.02)
continue
rule_files = []
if os.path.exists(self.path_rules):
rule_files = sorted(
os.path.join(self.path_rules, name)
for name in os.listdir(self.path_rules)
if name.lower().endswith(".json") and name.lower() != "rules_driver_p1.json"
)
load_failed = False
for rule_file in rule_files:
if self.driver_stop_event.is_set() or not self.load_driver_rule_file(rule_file):
load_failed = True
break
if load_failed:
self.driver_listener_failed_event.set()
break
with self.lock_config:
whitelist = list(self.pyas_config.get("white_list", []))
for item in whitelist:
if self.driver_stop_event.is_set():
break
if isinstance(item, dict) and item.get("file"):
self.sync_driver_whitelist(item["file"], True, item.get("is_dir"))
if self.driver_stop_event.is_set():
break
ready = True
self.driver_listener_ready_event.set()
while self._driver_listener_should_run():
with self.lock_driver:
current_port = self.driver_port
owns_current = self._driver_handle_value(
current_port
) == self._driver_handle_value(owned_port)
if not owns_current:
break
receive_state, message = self._receive_driver_message(owned_port)
if receive_state != "message":
break
code = message.Data.MessageCode
pid = message.Data.ProcessId
target = message.Data.Path
exe_info = self.get_exe_info(pid)
safe_source = exe_info[1] if exe_info and exe_info[1] else "Unknown"
if not self.is_in_whitelist(safe_source):
self.write_log(
"BLOCK",
"Driver Block",
detail="Driver protection event",
pid=pid,
source=safe_source,
target=target,
code=code,
file_hash=self.calc_file_hash(safe_source),
operate=None,
success=True,
)
self._close_driver_port(owned_port)
owned_port = None
ready = False
self.driver_listener_ready_event.clear()
if self.driver_stop_event.is_set():
break
self.driver_stop_event.wait(0.02)
except Exception as e:
log_exception("PYAS_Driver.DriverMixin.pipe_server_thread:928")
self.driver_listener_failed_event.set()
if not self.driver_stop_event.is_set():
self.write_log("WARN", "pipe_server_thread", detail=str(e), success=False)
finally:
if owned_port:
try:
self.kernel32.CancelIoEx(owned_port, None)
except Exception:
log_exception("PYAS_Driver.DriverMixin.pipe_server_thread:937")
pass
self._close_driver_port(owned_port)
if not ready and not self.driver_stop_event.is_set():
self.driver_listener_failed_event.set()
self.driver_listener_ready_event.clear()
with self.lock_driver:
if self.driver_listener_thread is threading.current_thread():
self.driver_listener_thread = None