Compare commits

...
9 Commits
Author SHA1 Message Date
87owo 0cef48771b Add files via upload 2026-06-28 13:29:11 +08:00
87owo a45b10b5c3 Add files via upload 2026-06-28 12:58:54 +08:00
87owo 7627d4e5d7 Add files via upload 2026-06-26 22:06:22 +08:00
87owo 5c88711094 Add files via upload 2026-06-26 22:04:47 +08:00
87owo a7fdd41530 Add files via upload 2026-06-26 19:44:46 +08:00
87owo c315b322cd Merge pull request #65 from Wangbotao2013/main 2026-06-26 19:43:42 +08:00
87owo 181bfc5b44 Add files via upload 2026-06-23 20:14:39 +08:00
wangbotao d9ea2b522a Merge branch 'main' into main 2026-06-19 18:57:39 +08:00
wangbotao c3ef1da373 PYAS 自保护增强
任务管理器通过匹配 Rule_Process_TrustedPaths 中的 *\\Windows\\* 规则被误判为可信进程,导致黑名单检查失效。
2026-06-14 17:27:05 +08:00
15 changed files with 1724 additions and 1433 deletions

No files matched your search

+37 -6
View File
@@ -588,9 +588,15 @@ class ModelPredictor:
expected_dim = self.sess.get_inputs()[0].shape[1]
current_dim = len(self.model_features)
if current_dim != expected_dim:
raise ValueError(f"Dimension mismatch! Model expects {expected_dim} features, but feature file lists {current_dim}.")
raise ValueError(f"Dimension error: Model expects {expected_dim}, but feature file has {current_dim}")
self.feat_map = {feat: i for i, feat in enumerate(self.model_features)}
self.dll_hash_dim = 512
self.api_hash_dim = 4096
self.dll_hash_pad = 3
self.api_hash_pad = 4
self._parse_hash_dims()
def _load_features(self, path):
if not os.path.exists(path):
@@ -599,6 +605,31 @@ class ModelPredictor:
with open(path, 'r') as f:
return json.load(f)
def _parse_hash_dims(self):
max_dll = -1
max_api = -1
for feat in self.model_features:
if feat.startswith("DllHash_"):
try:
val_str = feat.split("_")[1]
max_dll = max(max_dll, int(val_str))
self.dll_hash_pad = len(val_str)
except Exception:
pass
elif feat.startswith("ApiHash_"):
try:
val_str = feat.split("_")[1]
max_api = max(max_api, int(val_str))
self.api_hash_pad = len(val_str)
except Exception:
pass
if max_dll >= 0:
self.dll_hash_dim = max_dll + 1
if max_api >= 0:
self.api_hash_dim = max_api + 1
def predict(self, raw_data):
vec = np.zeros((1, len(self.model_features)), dtype=np.float32)
base = raw_data.get('Base', {})
@@ -610,14 +641,14 @@ class ModelPredictor:
vec[0, self.feat_map[k]] = v
for d in dlls:
h = zlib.crc32(d.encode('utf-8', 'ignore')) % 256
feat_name = f"DllHash_{h:03d}"
h = zlib.crc32(d.encode('utf-8', 'ignore')) % self.dll_hash_dim
feat_name = f"DllHash_{h:0{self.dll_hash_pad}d}"
if feat_name in self.feat_map:
vec[0, self.feat_map[feat_name]] += 1.0
for a in apis:
h = zlib.crc32(a.encode('utf-8', 'ignore')) % 1024
feat_name = f"ApiHash_{h:04d}"
h = zlib.crc32(a.encode('utf-8', 'ignore')) % self.api_hash_dim
feat_name = f"ApiHash_{h:0{self.api_hash_pad}d}"
if feat_name in self.feat_map:
vec[0, self.feat_map[feat_name]] += 1.0
@@ -633,7 +664,7 @@ class ModelPredictor:
elif isinstance(result, np.ndarray):
if result.ndim == 2 and result.shape[1] > 1:
return float(result[0][1])
return 0.0
####################################################################################################
+2 -2
View File
@@ -25,8 +25,8 @@ FEATURE_FILE = "features.json"
TEST_SIZE = 0.0001
RANDOM_SEED = 42
DLL_HASH_DIM = 256
API_HASH_DIM = 1024
DLL_HASH_DIM = 512
API_HASH_DIM = 4096
EXCLUDE_FEATURES = {
'label', 'filehash',
+2 -2
View File
@@ -25,8 +25,8 @@ FEATURE_FILE = "features.json"
TEST_SIZE = 0.0001
RANDOM_SEED = 42
DLL_HASH_DIM = 256
API_HASH_DIM = 1024
DLL_HASH_DIM = 512
API_HASH_DIM = 4096
EXCLUDE_FEATURES = {
'label', 'filehash',
+22
View File
@@ -184,6 +184,8 @@ window.AppI18n = {
"protect_suspend_desc": "此選項可以暫停進程等待掃描",
"opt_autostart": "開機啟動",
"opt_autostart_desc": "此選項可以設定開機自動執行",
"opt_ext_filter": "副檔名過濾",
"opt_ext_filter_desc": "此選項僅掃描指定檔案副檔名",
},
"simplified_switch": {
"app_name": "PYAS Security",
@@ -369,6 +371,8 @@ window.AppI18n = {
"protect_suspend_desc": "此选项可以暂停进程等待扫描",
"opt_autostart": "开机启动",
"opt_autostart_desc": "此选项可以设定开机自动运行",
"opt_ext_filter": "后缀名过滤",
"opt_ext_filter_desc": "此选项仅扫描指定文件后缀名",
},
"english_switch": {
"app_name": "PYAS Security",
@@ -554,6 +558,8 @@ window.AppI18n = {
"protect_suspend_desc": "Suspend processes while waiting for scanning",
"opt_autostart": "Auto Start",
"opt_autostart_desc": "Run automatically at system startup",
"opt_ext_filter": "Suffix Filter",
"opt_ext_filter_desc": "This option only scans specified file extensions",
},
"japanese_switch": {
"app_name": "PYAS Security",
@@ -739,6 +745,8 @@ window.AppI18n = {
"protect_suspend_desc": "スキャン待ちの間プロセスを一時停止します",
"opt_autostart": "自動起動",
"opt_autostart_desc": "システム起動時に自動的に実行します",
"opt_ext_filter": "拡張子フィルタ",
"opt_ext_filter_desc": "このオプションは指定された拡張子のファイルのみをスキャンします",
},
"korean_switch": {
"app_name": "PYAS Security",
@@ -924,6 +932,8 @@ window.AppI18n = {
"protect_suspend_desc": "스캔을 기다리는 동안 프로세스를 일시 중지합니다",
"opt_autostart": "자동 시작",
"opt_autostart_desc": "시스템 시작 시 자동으로 실행합니다",
"opt_ext_filter": "확장자 필터",
"opt_ext_filter_desc": "이 옵션은 지정된 파일 확장자만 스캔합니다",
},
"french_switch": {
"app_name": "PYAS Security",
@@ -1109,6 +1119,8 @@ window.AppI18n = {
"protect_suspend_desc": "Suspend les processus en attente d'analyse",
"opt_autostart": "Démarrage auto",
"opt_autostart_desc": "Exécuter automatiquement au démarrage",
"opt_ext_filter": "Filtre d'extension",
"opt_ext_filter_desc": "Cette option analyse uniquement les extensions de fichiers spécifiées",
},
"spanish_switch": {
"app_name": "PYAS Security",
@@ -1294,6 +1306,8 @@ window.AppI18n = {
"protect_suspend_desc": "Suspender procesos mientras espera el escaneo",
"opt_autostart": "Inicio automático",
"opt_autostart_desc": "Ejecutar automáticamente al inicio",
"opt_ext_filter": "Filtro de extensión",
"opt_ext_filter_desc": "Esta opción solo escanea extensiones de archivo especificadas",
},
"hindi_switch": {
"app_name": "PYAS Security",
@@ -1479,6 +1493,8 @@ window.AppI18n = {
"protect_suspend_desc": "स्कैन की प्रतीक्षा करते समय प्रक्रियाओं को रोकें",
"opt_autostart": "स्वतः प्रारंभ",
"opt_autostart_desc": "सिस्टम स्टार्टअप पर स्वचालित रूप से चलाएं",
"opt_ext_filter": "एक्सटेंशन फ़िल्टर",
"opt_ext_filter_desc": "यह विकल्प केवल निर्दिष्ट फ़ाइल एक्सटेंशन को स्कैन करता है",
},
"arabic_switch": {
"app_name": "PYAS Security",
@@ -1664,6 +1680,8 @@ window.AppI18n = {
"protect_suspend_desc": "تعليق العمليات أثناء انتظار الفحص",
"opt_autostart": "بدء تلقائي",
"opt_autostart_desc": "التشغيل تلقائيًا عند بدء التشغيل",
"opt_ext_filter": "تصفية الامتداد",
"opt_ext_filter_desc": "يقوم هذا الخيار بفحص امتدادات الملفات المحددة فقط",
},
"russian_switch": {
"app_name": "PYAS Security",
@@ -1849,6 +1867,8 @@ window.AppI18n = {
"protect_suspend_desc": "Приостановка процессов в ожидании сканирования",
"opt_autostart": "Автозапуск",
"opt_autostart_desc": "Автоматический запуск при старте системы",
"opt_ext_filter": "Фильтр расширений",
"opt_ext_filter_desc": "Этот параметр сканирует только указанные расширения файлов",
},
"slovenian_switch": {
"app_name": "PYAS Security",
@@ -2034,6 +2054,8 @@ window.AppI18n = {
"protect_suspend_desc": "Zaustavite procese med čakanjem na skeniranje",
"opt_autostart": "Samodejni zagon",
"opt_autostart_desc": "Samodejni zagon ob zagonu sistema",
"opt_ext_filter": "Filter končnic",
"opt_ext_filter_desc": "Ta možnost skenira samo določene končnice datotek",
}
},
langMap: {
+4 -4
View File
@@ -781,7 +781,7 @@ document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('.toggle-switch input').forEach((toggle, index) => {
toggle.addEventListener('change', async (e) => {
const switchMap = ["process_switch", "suspend_switch", "document_switch", "system_switch", "driver_switch", "network_switch", "sensitive_switch", "extension_switch", "cloud_switch", "autostart_switch", "context_switch"];
const switchMap = ["process_switch", "suspend_switch", "document_switch", "system_switch", "driver_switch", "network_switch", "sensitive_switch", "extension_switch", "cloud_switch", "suffix_switch", "autostart_switch", "context_switch"];
const key = switchMap[index];
if (window.pywebview && key) {
toggle.disabled = true;
@@ -1082,7 +1082,7 @@ document.addEventListener('DOMContentLoaded', () => {
updateCustomSelectUI('theme_select', theme);
updateCustomSelectUI('lang_select', lang);
const switchMap = ["process_switch", "suspend_switch", "document_switch", "system_switch", "driver_switch", "network_switch", "sensitive_switch", "extension_switch", "cloud_switch", "autostart_switch", "context_switch"];
const switchMap = ["process_switch", "suspend_switch", "document_switch", "system_switch", "driver_switch", "network_switch", "sensitive_switch", "extension_switch", "cloud_switch", "suffix_switch", "autostart_switch", "context_switch"];
document.querySelectorAll('.toggle-switch input').forEach((toggle, index) => {
if (appState.firstLaunch) {
toggle.checked = false;
@@ -1102,8 +1102,8 @@ document.addEventListener('DOMContentLoaded', () => {
window.onEngineReady = async () => {
if (!appState.firstLaunch) return;
await window.pywebview.api.update_config("first_launch", false);
const switchMap = ["process_switch", "suspend_switch", "document_switch", "system_switch", "driver_switch", "network_switch", "sensitive_switch", "extension_switch", "cloud_switch", "autostart_switch", "context_switch"];
const seq = ["cloud_switch", "autostart_switch", "process_switch", "suspend_switch", "document_switch", "system_switch", "network_switch", "driver_switch"];
const switchMap = ["process_switch", "suspend_switch", "document_switch", "system_switch", "driver_switch", "network_switch", "sensitive_switch", "extension_switch", "cloud_switch", "suffix_switch", "autostart_switch", "context_switch"];
const seq = ["cloud_switch", "autostart_switch", "suffix_switch", "process_switch", "suspend_switch", "document_switch", "system_switch", "network_switch", "driver_switch", "context_switch"];
for (const key of seq) {
const index = switchMap.indexOf(key);
+6
View File
@@ -221,6 +221,12 @@
</div>
<label class="toggle-switch"><input type="checkbox" checked><span class="slider"></span></label>
</div>
<div class="list-item">
<div class="item-info">
<h2 data-i18n>副檔名過濾</h2><p data-i18n>此選項僅掃描指定檔案副檔名</p>
</div>
<label class="toggle-switch"><input type="checkbox" checked><span class="slider"></span></label>
</div>
<div class="list-item">
<div class="item-info">
<h2 data-i18n>開機啟動</h2><p data-i18n>此選項可以設定開機自動執行</p>
+162 -35
View File
@@ -120,6 +120,20 @@ class MEMORY_BASIC_INFORMATION(ctypes.Structure):
("Type", ctypes.wintypes.DWORD)
]
class POINT(ctypes.Structure):
_fields_ = [
("x", ctypes.c_long),
("y", ctypes.c_long)
]
class RECT(ctypes.Structure):
_fields_ = [
("left", ctypes.c_long),
("top", ctypes.c_long),
("right", ctypes.c_long),
("bottom", ctypes.c_long)
]
####################################################################################################
class WindowAPI:
@@ -233,6 +247,20 @@ class WindowAPI:
self.user32.SendMessageTimeoutW.argtypes = [ctypes.wintypes.HWND, ctypes.wintypes.UINT, ctypes.wintypes.WPARAM, ctypes.c_void_p, ctypes.wintypes.UINT, ctypes.wintypes.UINT, ctypes.c_void_p]
self.user32.SendMessageTimeoutW.restype = ctypes.wintypes.LPARAM
self.user32.WindowFromPoint.argtypes = [POINT]
self.user32.WindowFromPoint.restype = ctypes.wintypes.HWND
self.user32.GetAncestor.argtypes = [ctypes.wintypes.HWND, ctypes.c_uint]
self.user32.GetAncestor.restype = ctypes.wintypes.HWND
self.user32.GetCursorPos.argtypes = [ctypes.POINTER(POINT)]
self.user32.GetCursorPos.restype = ctypes.wintypes.BOOL
self.user32.GetWindowRect.argtypes = [ctypes.wintypes.HWND, ctypes.POINTER(RECT)]
self.user32.GetWindowRect.restype = ctypes.wintypes.BOOL
self.user32.SetWindowPos.argtypes = [ctypes.wintypes.HWND, ctypes.wintypes.HWND, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.wintypes.UINT]
self.user32.SetWindowPos.restype = ctypes.wintypes.BOOL
self.user32.SetLayeredWindowAttributes.argtypes = [ctypes.wintypes.HWND, ctypes.wintypes.DWORD, ctypes.c_byte, ctypes.wintypes.DWORD]
self.user32.SetLayeredWindowAttributes.restype = ctypes.wintypes.BOOL
self.user32.CreateWindowExW.restype = ctypes.wintypes.HWND
self.ntdll.NtQueryInformationProcess.argtypes = [ctypes.wintypes.HANDLE, ctypes.wintypes.ULONG, ctypes.c_void_p, ctypes.wintypes.ULONG, ctypes.POINTER(ctypes.wintypes.ULONG)]
self.ntdll.NtQueryInformationProcess.restype = ctypes.wintypes.ULONG
self.ntdll.NtSuspendProcess.argtypes = [ctypes.wintypes.HANDLE]
@@ -321,12 +349,12 @@ class WindowAPI:
self.lock_io = threading.RLock()
self.pyas_default = {
"version": "3.6.0",
"version": "3.6.1",
"api_host": "https://pyas-security.com/",
"api_key": "fBRZxYS1UxykM-qzNOlKOEl63WILzlvgNMn6QfsG6FXCAAIktCrOPTAfY5_hEyuZ",
"suffix": [".exe", ".dll", ".sys", ".ocx", ".scr", ".efi", ".acm", ".ax", ".cpl", ".drv", ".com", ".mui", ".pyd", ".wfx", ".api", ".awx", ".rll", ".winmd", ".ax"],
"suffix": [".exe", ".dll", ".sys", ".ocx", ".scr", ".efi", ".acm", ".ax", ".cpl", ".drv", ".com", ".mui", ".pyd", ".wfx", ".api", ".awx", ".rll", ".winmd"],
"block": [2001, 3001, 5001, 6001],
"size": 100 * 1024 * 1024,
"size": 256 * 1024 * 1024,
"language": "english_switch",
"theme": "system_switch",
"first_launch": True,
@@ -339,8 +367,9 @@ class WindowAPI:
"extension_switch": False,
"sensitive_switch": False,
"cloud_switch": False,
"suffix_switch": True,
"autostart_switch": True,
"context_switch": False,
"context_switch": True,
"custom_rule": [],
"white_list": [],
"quarantine": [],
@@ -1510,7 +1539,7 @@ class WindowAPI:
def _traverse_delete(self, path):
deleted = 0
if not os.path.exists(path):
if not path or not os.path.exists(path):
return deleted
try:
@@ -1522,6 +1551,9 @@ class WindowAPI:
file = os.path.join(path, fd)
try:
if os.path.isdir(file):
if self._is_reparse_point(file):
continue
deleted += self._traverse_delete(file)
try:
os.rmdir(file)
@@ -1881,7 +1913,12 @@ class WindowAPI:
with self.lock_config:
first_launch = self.pyas_config.get("first_launch", True)
driver_enabled = self.pyas_config.get("driver_switch", False)
context_enabled = self.pyas_config.get("context_switch", True)
autostart_enabled = self.pyas_config.get("autostart_switch", True)
self.register_context_menu(context_enabled)
self.manage_autostart(autostart_enabled)
if not first_launch:
with self.lock_config:
if self.pyas_config.get("process_switch"):
@@ -1909,17 +1946,30 @@ class WindowAPI:
def yield_files(self, targets):
if isinstance(targets, str):
if os.path.isdir(targets):
for root, _, files in os.walk(targets):
for root, dirs, files in os.walk(targets):
dirs[:] = [d for d in dirs if not self._is_reparse_point(os.path.join(root, d))]
for f in files:
yield self.norm_path(os.path.join(root, f))
yield self.norm_path(os.path.join(root, f)), False
elif os.path.isfile(targets):
yield self.norm_path(targets)
yield self.norm_path(targets), True
elif isinstance(targets, (list, tuple, set)):
for t in targets:
yield from self.yield_files(t)
def _is_reparse_point(self, path):
try:
if os.path.islink(path):
return True
if hasattr(os.path, 'isjunction') and os.path.isjunction(path):
return True
st = os.lstat(path)
return bool(getattr(st, 'st_file_attributes', 0) & 0x400)
except OSError:
return False
def scan_engine(self, file_path):
with self.lock_config:
ext_switch = self.pyas_config.get("extension_switch", False)
@@ -2001,7 +2051,7 @@ class WindowAPI:
def scan_worker(self, targets):
last_update = 0.0
try:
for file_path in self.yield_files(targets):
for file_path, is_explicit in self.yield_files(targets):
with self.lock_virus:
if not self.scan_running:
break
@@ -2031,9 +2081,10 @@ class WindowAPI:
with self.lock_virus:
self.scan_count += 1
with self.lock_config:
ext_filter = self.pyas_config.get("suffix_switch", True)
suffix = self.pyas_config.get("suffix", [])
if os.path.splitext(norm_path)[-1].lower() not in suffix:
if not is_explicit and ext_filter and os.path.splitext(norm_path)[-1].lower() not in suffix:
continue
result = self.safe_scan_engine(norm_path)
@@ -2107,8 +2158,39 @@ class WindowAPI:
if os.path.exists(self.path_config):
targets.append(self.path_config)
buf = ctypes.create_unicode_buffer(1024)
max_address = 0x7FFFFFFFFFFF if ctypes.sizeof(ctypes.c_void_p) == 8 else 0x7FFFFFFF
system_dir = self.path_system.lower()
for proc in self.get_process_list():
if proc["path"] and proc["path"] != "None": targets.append(proc["path"])
if proc["path"] and proc["path"] != "None":
targets.append(proc["path"])
pid = proc["pid"]
if pid <= 4:
continue
h_process = self.kernel32.OpenProcess(0x1000, False, pid)
if h_process:
try:
address = 0
mbi = MEMORY_BASIC_INFORMATION()
while address < max_address and self.kernel32.VirtualQueryEx(h_process, ctypes.c_void_p(address), ctypes.byref(mbi), ctypes.sizeof(mbi)):
if mbi.State == 0x1000 and mbi.Type == 0x1000000:
if self.psapi.GetMappedFileNameW(h_process, ctypes.c_void_p(address), buf, 1024):
raw_path = buf.value
if raw_path.startswith("\\"):
raw_path = self.device_path_to_drive(raw_path)
file_path = self.norm_path(raw_path)
if file_path and not file_path.lower().startswith(system_dir):
targets.append(file_path)
if mbi.RegionSize == 0:
break
address += mbi.RegionSize
finally:
self.kernel32.CloseHandle(h_process)
self.start_scan(list(set(targets)))
@@ -2260,7 +2342,7 @@ class WindowAPI:
if not self.pyas_config.get("cloud_switch", True):
return False
api_host, api_key, max_size = self.pyas_config.get("api_host"), self.pyas_config.get("api_key"), self.pyas_config.get("size", 100 * 1024 * 1024)
api_host, api_key, max_size = self.pyas_config.get("api_host"), self.pyas_config.get("api_key"), self.pyas_config.get("size", 256 * 1024 * 1024)
if not os.path.exists(file_path) or not os.path.isfile(file_path):
return False
@@ -2769,13 +2851,16 @@ class WindowAPI:
all_targets.append(np)
with self.lock_config:
ext_filter = self.pyas_config.get("suffix_switch", True)
suffix = self.pyas_config.get("suffix", [])
scan_targets = []
for file_path in all_targets:
if not file_path or not os.path.isfile(file_path):
continue
if os.path.splitext(file_path)[-1].lower() not in suffix or self.is_in_whitelist(file_path):
if ext_filter and os.path.splitext(file_path)[-1].lower() not in suffix:
continue
if self.is_in_whitelist(file_path):
continue
if process_file and process_file.lower().endswith("explorer.exe") and "/select" in cmdline.lower():
continue
@@ -2824,6 +2909,7 @@ class WindowAPI:
max_address = 0x7FFFFFFFFFFF if ctypes.sizeof(ctypes.c_void_p) == 8 else 0x7FFFFFFF
with self.lock_config:
ext_filter = self.pyas_config.get("suffix_switch", True)
suffix = self.pyas_config.get("suffix", [])
try:
@@ -2844,7 +2930,7 @@ class WindowAPI:
if not file_path_lower.startswith(system_dir) and not self.is_in_whitelist(file_path):
ext = os.path.splitext(file_path_lower)[-1]
if ext != ".exe" and ext in suffix:
if ext != ".exe" and (not ext_filter or ext in suffix):
if self.safe_scan_engine(file_path):
return file_path
@@ -2900,9 +2986,10 @@ class WindowAPI:
if not (norm_path.startswith(temp_prefix) and norm_path[len(temp_prefix):].startswith("_mei")):
with self.lock_config:
ext_filter = self.pyas_config.get("suffix_switch", True)
suffix = self.pyas_config.get("suffix", [])
if os.path.splitext(file_path)[-1].lower() in suffix:
if not ext_filter or os.path.splitext(file_path)[-1].lower() in suffix:
self.protect_pool.submit(self.handle_new_file, file_path)
if notify.NextEntryOffset == 0:
@@ -3026,34 +3113,74 @@ class WindowAPI:
pass
def capture_popup_window(self):
overlay = self.user32.CreateWindowExW(0x000800A8, "STATIC", "", 0x90000004, 0, 0, 0, 0, None, None, None, None)
self.user32.SetLayeredWindowAttributes(overlay, 0, 120, 2)
target_hwnd = None
last_hwnd = None
msg = ctypes.wintypes.MSG()
while self.user32.GetAsyncKeyState(0x01) & 0x8000:
time.sleep(0.01)
try:
start_time = time.time()
while time.time() - start_time < 5:
while time.time() - start_time < 30:
if self.user32.GetAsyncKeyState(0x1B) & 0x8000:
break
hwnd = self.user32.GetForegroundWindow()
if not hwnd:
time.sleep(0.5)
continue
pt = POINT()
self.user32.GetCursorPos(ctypes.byref(pt))
hwnd = self.user32.WindowFromPoint(pt)
root_hwnd = self.user32.GetAncestor(hwnd, 2)
if not root_hwnd:
root_hwnd = hwnd
pid = ctypes.c_ulong(0)
self.user32.GetWindowThreadProcessId(hwnd, ctypes.byref(pid))
if pid.value != self.pid_pyas and pid.value > 4:
if root_hwnd and root_hwnd != overlay:
if root_hwnd != last_hwnd:
last_hwnd = root_hwnd
rect = RECT()
self.user32.GetWindowRect(root_hwnd, ctypes.byref(rect))
self.user32.SetWindowPos(
overlay, -1,
rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
0x0050
)
if self.user32.GetAsyncKeyState(0x01) & 0x8000:
target_hwnd = root_hwnd
break
length = self.user32.GetWindowTextLengthW(hwnd)
title, class_name = ctypes.create_unicode_buffer(length + 1), ctypes.create_unicode_buffer(256)
self.user32.GetWindowTextW(hwnd, title, length + 1)
self.user32.GetClassNameW(hwnd, class_name, 256)
while self.user32.PeekMessageW(ctypes.byref(msg), 0, 0, 0, 1):
self.user32.TranslateMessage(ctypes.byref(msg))
self.user32.DispatchMessageW(ctypes.byref(msg))
proc_name, _ = self.get_exe_info(pid.value)
t_str, c_str = str(title.value), str(class_name.value)
time.sleep(0.02)
finally:
self.user32.DestroyWindow(overlay)
if proc_name and not any(item.get("exe") == proc_name or item.get("class") == c_str for item in self.pass_windows):
return {"exe": proc_name, "class": c_str, "title": t_str}
if not target_hwnd:
return None
time.sleep(0.5)
except Exception as e:
self.write_log("WARN", "capture_popup_window", detail=str(e), success=False)
pid = ctypes.c_ulong(0)
self.user32.GetWindowThreadProcessId(target_hwnd, ctypes.byref(pid))
if pid.value != self.pid_pyas and pid.value > 4:
length = self.user32.GetWindowTextLengthW(target_hwnd)
title = ctypes.create_unicode_buffer(length + 1)
class_name = ctypes.create_unicode_buffer(256)
self.user32.GetWindowTextW(target_hwnd, title, length + 1)
self.user32.GetClassNameW(target_hwnd, class_name, 256)
proc_name, _ = self.get_exe_info(pid.value)
t_str, c_str = str(title.value), str(class_name.value)
if proc_name and not any(item.get("exe") == proc_name or item.get("class") == c_str for item in self.pass_windows):
return {"exe": proc_name, "class": c_str, "title": t_str}
return None
def add_popup_rule(self, rule):
+35 -4
View File
@@ -205,6 +205,10 @@ class pe_scanner:
self.model = None
self.input_name = None
self.feature_order = []
self.dll_hash_dim = 512
self.api_hash_dim = 4096
self.dll_hash_pad = 3
self.api_hash_pad = 4
self.signer = sign_scanner()
self.signer.init_windll(["wintrust"])
@@ -232,9 +236,36 @@ class pe_scanner:
with open(feat_path, 'r', encoding='utf-8') as f:
self.feature_order = json.load(f)
self._parse_hash_dims()
except Exception:
pass
def _parse_hash_dims(self):
max_dll = -1
max_api = -1
for feat in self.feature_order:
if feat.startswith("DllHash_"):
try:
val_str = feat.split("_")[1]
max_dll = max(max_dll, int(val_str))
self.dll_hash_pad = len(val_str)
except Exception:
pass
elif feat.startswith("ApiHash_"):
try:
val_str = feat.split("_")[1]
max_api = max(max_api, int(val_str))
self.api_hash_pad = len(val_str)
except Exception:
pass
if max_dll >= 0:
self.dll_hash_dim = max_dll + 1
if max_api >= 0:
self.api_hash_dim = max_api + 1
def _safe_float(self, val):
try:
f = float(val)
@@ -761,8 +792,8 @@ class pe_scanner:
if old_fn in feat_map:
vec[0, feat_map[old_fn]] = 1.0
h = zlib.crc32(d.encode('utf-8', 'ignore')) % 256
new_fn = f"DllHash_{h:03d}"
h = zlib.crc32(d.encode('utf-8', 'ignore')) % self.dll_hash_dim
new_fn = f"DllHash_{h:0{self.dll_hash_pad}d}"
if new_fn in feat_map:
vec[0, feat_map[new_fn]] += 1.0
@@ -771,8 +802,8 @@ class pe_scanner:
if old_fn in feat_map:
vec[0, feat_map[old_fn]] = 1.0
h = zlib.crc32(a.encode('utf-8', 'ignore')) % 1024
new_fn = f"ApiHash_{h:04d}"
h = zlib.crc32(a.encode('utf-8', 'ignore')) % self.api_hash_dim
new_fn = f"ApiHash_{h:0{self.api_hash_pad}d}"
if new_fn in feat_map:
vec[0, feat_map[new_fn]] += 1.0
+1 -1
View File
@@ -1,6 +1,6 @@
#define AppId "{{a7d7bac3-93b8-4630-8308-c7a56bf7fdf4}"
#define AppName "PYAS"
#define AppVersion "3.6.0.0"
#define AppVersion "3.6.1.0"
#define AppPublisher "PYAS Security"
#define AppURL "https://github.com/87owo/PYAS"
#define AppExeName "PYAS.exe"
+1 -1
View File
@@ -2,7 +2,7 @@ import pyinstaller_versionfile
pyinstaller_versionfile.create_versionfile(
output_file="versionfile.txt",
version='3.6.0.0',
version='3.6.1.0',
company_name="PYAS Security",
file_description="PYAS Security Antivirus",
internal_name="PYAS",
+175 -170
View File
@@ -1,171 +1,176 @@
#pragma once
#include <fltKernel.h>
#include <ntddk.h>
#include <ntdddisk.h>
#include <ntddscsi.h>
#include <ntstrsafe.h>
constexpr auto PYAS_PORT_NAME = L"\\PYAS_Output_Pipe";
constexpr auto MAX_PATH_LEN = 1024;
constexpr auto PYAS_POOL_TAG = 'SAYP';
#ifndef PROCESS_TERMINATE
#define PROCESS_TERMINATE (0x0001)
#endif
#ifndef PROCESS_CREATE_THREAD
#define PROCESS_CREATE_THREAD (0x0002)
#endif
#ifndef PROCESS_VM_OPERATION
#define PROCESS_VM_OPERATION (0x0008)
#endif
#ifndef PROCESS_VM_READ
#define PROCESS_VM_READ (0x0010)
#endif
#ifndef PROCESS_VM_WRITE
#define PROCESS_VM_WRITE (0x0020)
#endif
#ifndef PROCESS_DUP_HANDLE
#define PROCESS_DUP_HANDLE (0x0040)
#endif
#ifndef PROCESS_CREATE_PROCESS
#define PROCESS_CREATE_PROCESS (0x0080)
#endif
#ifndef PROCESS_SET_INFORMATION
#define PROCESS_SET_INFORMATION (0x0200)
#endif
#ifndef PROCESS_QUERY_INFORMATION
#define PROCESS_QUERY_INFORMATION (0x0400)
#endif
#ifndef PROCESS_SUSPEND_RESUME
#define PROCESS_SUSPEND_RESUME (0x0800)
#endif
#ifndef PROCESS_QUERY_LIMITED_INFORMATION
#define PROCESS_QUERY_LIMITED_INFORMATION (0x1000)
#endif
#ifndef PROCESS_SET_QUOTA
#define PROCESS_SET_QUOTA (0x0100)
#endif
#ifndef THREAD_TERMINATE
#define THREAD_TERMINATE (0x0001)
#endif
#ifndef THREAD_SUSPEND_RESUME
#define THREAD_SUSPEND_RESUME (0x0002)
#endif
#ifndef THREAD_SET_CONTEXT
#define THREAD_SET_CONTEXT (0x0010)
#endif
#ifndef THREAD_SET_INFORMATION
#define THREAD_SET_INFORMATION (0x0020)
#endif
#ifndef THREAD_SET_THREAD_TOKEN
#define THREAD_SET_THREAD_TOKEN (0x0080)
#endif
#ifndef POOL_FLAG_NON_PAGED
#define POOL_FLAG_NON_PAGED 0x0000000000000040UI64
#endif
#ifndef FSCTL_MANAGE_BYPASS_IO
#define FSCTL_MANAGE_BYPASS_IO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 188, METHOD_NEITHER, FILE_ANY_ACCESS)
typedef enum _FS_BPIO_OPERATIONS {
FS_BPIO_OP_ENABLE = 1,
FS_BPIO_OP_DISABLE = 2,
FS_BPIO_OP_QUERY = 3,
FS_BPIO_OP_VOLUME_STACK_PAUSE = 4,
FS_BPIO_OP_VOLUME_STACK_RESUME = 5,
FS_BPIO_OP_STREAM_PAUSE = 6,
FS_BPIO_OP_STREAM_RESUME = 7,
FS_BPIO_OP_GET_INFO = 8
} FS_BPIO_OPERATIONS;
typedef struct _FS_BPIO_INPUT {
FS_BPIO_OPERATIONS Operation;
ULONG InFlags;
ULONGLONG Reserved1;
ULONGLONG Reserved2;
} FS_BPIO_INPUT, * PFS_BPIO_INPUT;
typedef struct _FS_BPIO_OUTPUT {
FS_BPIO_OPERATIONS Operation;
ULONG OutFlags;
ULONGLONG Reserved1;
ULONGLONG Reserved2;
NTSTATUS Status;
} FS_BPIO_OUTPUT, * PFS_BPIO_OUTPUT;
#endif
typedef struct _PYAS_MESSAGE {
ULONG MessageCode;
ULONG ProcessId;
WCHAR Path[MAX_PATH_LEN];
} PYAS_MESSAGE, * PPYAS_MESSAGE;
typedef struct _PYAS_USER_MESSAGE {
ULONG Command;
WCHAR Path[MAX_PATH_LEN];
} PYAS_USER_MESSAGE, * PPYAS_USER_MESSAGE;
typedef struct _DRIVER_DATA {
PDRIVER_OBJECT DriverObject;
PFLT_FILTER FilterHandle;
PFLT_PORT ServerPort;
PFLT_PORT ClientPort;
PEPROCESS PyasProcess;
ULONG PyasPid;
LARGE_INTEGER Cookie;
KSPIN_LOCK PortMutex;
KSPIN_LOCK TrackerMutex;
EX_RUNDOWN_REF PortRundown;
} DRIVER_DATA, * PDRIVER_DATA;
typedef struct _RULE_NODE {
struct _RULE_NODE* Next;
UNICODE_STRING Pattern;
} RULE_NODE, * PRULE_NODE;
extern DRIVER_DATA GlobalData;
FLT_PREOP_CALLBACK_STATUS ProtectFile_PreCreate(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext);
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();
VOID UninitializeProcessProtection();
NTSTATUS InitializeRegistryProtection(PDRIVER_OBJECT DriverObject);
VOID UninitializeRegistryProtection();
NTSTATUS LoadRulesFromDisk(PUNICODE_STRING RegistryPath);
VOID UnloadRules();
VOID InitializeRulesEngine();
VOID UninitializeRulesEngine();
VOID AddDynamicWhitelist(PUNICODE_STRING RuleStr);
VOID RemoveDynamicWhitelist(PUNICODE_STRING RuleStr);
VOID ImageLoadNotify(PUNICODE_STRING FullImageName, HANDLE ProcessId, PIMAGE_INFO ImageInfo);
NTSTATUS GetProcessImageName(HANDLE ProcessId, PUNICODE_STRING* ImageName);
BOOLEAN IsProcessTrusted(HANDLE ProcessId);
BOOLEAN IsTargetProtected(HANDLE ProcessId);
BOOLEAN WildcardMatch(PCWSTR Pattern, PCWSTR String, USHORT StringLengthBytes);
BOOLEAN CheckRegistryRule(PCUNICODE_STRING KeyName);
BOOLEAN CheckFileExtensionRule(PCUNICODE_STRING FileName);
BOOLEAN CheckProtectedPathRule(PCUNICODE_STRING FileName);
BOOLEAN CheckRansomActivity(HANDLE ProcessId, PUNICODE_STRING FileName, PVOID WriteBuffer, ULONG WriteLength, BOOLEAN IsWrite);
NTSTATUS SendMessageToUser(ULONG Code, ULONG Pid, PWCHAR Path, USHORT PathSize);
FORCEINLINE PVOID PyasAllocate(SIZE_T Size) {
return ExAllocatePool2(POOL_FLAG_NON_PAGED, Size, PYAS_POOL_TAG);
}
FORCEINLINE VOID PyasFree(PVOID Ptr) {
if (Ptr) ExFreePoolWithTag(Ptr, PYAS_POOL_TAG);
#pragma once
#include <fltKernel.h>
#include <ntddk.h>
#include <ntdddisk.h>
#include <ntddscsi.h>
#include <ntstrsafe.h>
constexpr auto PYAS_PORT_NAME = L"\\PYAS_Output_Pipe";
constexpr auto MAX_PATH_LEN = 1024;
constexpr auto PYAS_POOL_TAG = 'SAYP';
#ifndef PROCESS_TERMINATE
#define PROCESS_TERMINATE (0x0001)
#endif
#ifndef PROCESS_CREATE_THREAD
#define PROCESS_CREATE_THREAD (0x0002)
#endif
#ifndef PROCESS_VM_OPERATION
#define PROCESS_VM_OPERATION (0x0008)
#endif
#ifndef PROCESS_VM_READ
#define PROCESS_VM_READ (0x0010)
#endif
#ifndef PROCESS_VM_WRITE
#define PROCESS_VM_WRITE (0x0020)
#endif
#ifndef PROCESS_DUP_HANDLE
#define PROCESS_DUP_HANDLE (0x0040)
#endif
#ifndef PROCESS_CREATE_PROCESS
#define PROCESS_CREATE_PROCESS (0x0080)
#endif
#ifndef PROCESS_SET_INFORMATION
#define PROCESS_SET_INFORMATION (0x0200)
#endif
#ifndef PROCESS_QUERY_INFORMATION
#define PROCESS_QUERY_INFORMATION (0x0400)
#endif
#ifndef PROCESS_SUSPEND_RESUME
#define PROCESS_SUSPEND_RESUME (0x0800)
#endif
#ifndef PROCESS_QUERY_LIMITED_INFORMATION
#define PROCESS_QUERY_LIMITED_INFORMATION (0x1000)
#endif
#ifndef PROCESS_SET_QUOTA
#define PROCESS_SET_QUOTA (0x0100)
#endif
#ifndef THREAD_TERMINATE
#define THREAD_TERMINATE (0x0001)
#endif
#ifndef THREAD_SUSPEND_RESUME
#define THREAD_SUSPEND_RESUME (0x0002)
#endif
#ifndef THREAD_SET_CONTEXT
#define THREAD_SET_CONTEXT (0x0010)
#endif
#ifndef THREAD_SET_INFORMATION
#define THREAD_SET_INFORMATION (0x0020)
#endif
#ifndef THREAD_SET_THREAD_TOKEN
#define THREAD_SET_THREAD_TOKEN (0x0080)
#endif
#ifndef POOL_FLAG_NON_PAGED
#define POOL_FLAG_NON_PAGED 0x0000000000000040UI64
#endif
#ifndef FSCTL_MANAGE_BYPASS_IO
#define FSCTL_MANAGE_BYPASS_IO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 188, METHOD_NEITHER, FILE_ANY_ACCESS)
typedef enum _FS_BPIO_OPERATIONS {
FS_BPIO_OP_ENABLE = 1,
FS_BPIO_OP_DISABLE = 2,
FS_BPIO_OP_QUERY = 3,
FS_BPIO_OP_VOLUME_STACK_PAUSE = 4,
FS_BPIO_OP_VOLUME_STACK_RESUME = 5,
FS_BPIO_OP_STREAM_PAUSE = 6,
FS_BPIO_OP_STREAM_RESUME = 7,
FS_BPIO_OP_GET_INFO = 8
} FS_BPIO_OPERATIONS;
typedef struct _FS_BPIO_INPUT {
FS_BPIO_OPERATIONS Operation;
ULONG InFlags;
ULONGLONG Reserved1;
ULONGLONG Reserved2;
} FS_BPIO_INPUT, * PFS_BPIO_INPUT;
typedef struct _FS_BPIO_OUTPUT {
FS_BPIO_OPERATIONS Operation;
ULONG OutFlags;
ULONGLONG Reserved1;
ULONGLONG Reserved2;
NTSTATUS Status;
} FS_BPIO_OUTPUT, * PFS_BPIO_OUTPUT;
#endif
typedef struct _PYAS_MESSAGE {
ULONG MessageCode;
ULONG ProcessId;
WCHAR Path[MAX_PATH_LEN];
} PYAS_MESSAGE, * PPYAS_MESSAGE;
typedef struct _PYAS_USER_MESSAGE {
ULONG Command;
WCHAR Path[MAX_PATH_LEN];
} PYAS_USER_MESSAGE, * PPYAS_USER_MESSAGE;
typedef struct _DRIVER_DATA {
PDRIVER_OBJECT DriverObject;
PFLT_FILTER FilterHandle;
PFLT_PORT ServerPort;
PFLT_PORT ClientPort;
PEPROCESS PyasProcess;
ULONG PyasPid;
LARGE_INTEGER Cookie;
KSPIN_LOCK PortMutex;
KSPIN_LOCK TrackerMutex;
KSPIN_LOCK PidLock;
BOOLEAN Initialized;
EX_RUNDOWN_REF PortRundown;
} DRIVER_DATA, * PDRIVER_DATA;
typedef struct _RULE_NODE {
struct _RULE_NODE* Next;
UNICODE_STRING Pattern;
} RULE_NODE, * PRULE_NODE;
extern DRIVER_DATA GlobalData;
FLT_PREOP_CALLBACK_STATUS ProtectFile_PreCreate(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext);
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();
VOID UninitializeProcessProtection();
NTSTATUS InitializeRegistryProtection(PDRIVER_OBJECT DriverObject);
VOID UninitializeRegistryProtection();
NTSTATUS LoadRulesFromDisk(PUNICODE_STRING RegistryPath);
VOID UnloadRules();
VOID InitializeRulesEngine();
VOID UninitializeRulesEngine();
VOID AddDynamicWhitelist(PUNICODE_STRING RuleStr);
VOID RemoveDynamicWhitelist(PUNICODE_STRING RuleStr);
VOID ImageLoadNotify(PUNICODE_STRING FullImageName, HANDLE ProcessId, PIMAGE_INFO ImageInfo);
NTSTATUS GetProcessImageName(HANDLE ProcessId, PUNICODE_STRING* ImageName);
ULONG SafeGetPyasPid();
VOID SafeSetPyasPid(ULONG Pid);
BOOLEAN IsProcessTrusted(HANDLE ProcessId);
BOOLEAN IsTargetProtected(HANDLE ProcessId);
BOOLEAN WildcardMatch(PCWSTR Pattern, PCWSTR String, USHORT StringLengthBytes);
BOOLEAN CheckRegistryRule(PCUNICODE_STRING KeyName);
BOOLEAN CheckFileExtensionRule(PCUNICODE_STRING FileName);
BOOLEAN CheckProtectedPathRule(PCUNICODE_STRING FileName);
BOOLEAN CheckRansomActivity(HANDLE ProcessId, PUNICODE_STRING FileName, PVOID WriteBuffer, ULONG WriteLength, BOOLEAN IsWrite);
NTSTATUS SendMessageToUser(ULONG Code, ULONG Pid, PWCHAR Path, USHORT PathSize);
FORCEINLINE PVOID PyasAllocate(SIZE_T Size) {
return ExAllocatePool2(POOL_FLAG_NON_PAGED, Size, PYAS_POOL_TAG);
}
FORCEINLINE VOID PyasFree(PVOID Ptr) {
if (Ptr) ExFreePoolWithTag(Ptr, PYAS_POOL_TAG);
}
+223 -219
View File
@@ -1,220 +1,224 @@
#include "DriverCommon.h"
DRIVER_DATA GlobalData;
static BOOLEAN g_ImageNotifyRegistered = FALSE;
static NTSTATUS InstanceSetup(PCFLT_RELATED_OBJECTS FltObjects, FLT_INSTANCE_SETUP_FLAGS Flags, DEVICE_TYPE VolumeDeviceType, FLT_FILESYSTEM_TYPE VolumeFilesystemType) {
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(Flags);
UNREFERENCED_PARAMETER(VolumeDeviceType);
UNREFERENCED_PARAMETER(VolumeFilesystemType);
return STATUS_SUCCESS;
}
static NTSTATUS InstanceQueryTeardown(PCFLT_RELATED_OBJECTS FltObjects, FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags) {
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(Flags);
return STATUS_SUCCESS;
}
static VOID InstanceTeardownStart(PCFLT_RELATED_OBJECTS FltObjects, FLT_INSTANCE_TEARDOWN_FLAGS Flags) {
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(Flags);
}
static VOID InstanceTeardownComplete(PCFLT_RELATED_OBJECTS FltObjects, FLT_INSTANCE_TEARDOWN_FLAGS Flags) {
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(Flags);
}
static NTSTATUS DriverUnload(FLT_FILTER_UNLOAD_FLAGS Flags) {
UNREFERENCED_PARAMETER(Flags);
if (GlobalData.ServerPort) {
FltCloseCommunicationPort(GlobalData.ServerPort);
GlobalData.ServerPort = NULL;
}
if (GlobalData.FilterHandle) {
FltUnregisterFilter(GlobalData.FilterHandle);
GlobalData.FilterHandle = NULL;
}
if (g_ImageNotifyRegistered) {
PsRemoveLoadImageNotifyRoutine(ImageLoadNotify);
g_ImageNotifyRegistered = FALSE;
}
UninitializeRegistryProtection();
UninitializeProcessProtection();
UnloadRules();
UninitializeRulesEngine();
return STATUS_SUCCESS;
}
static NTSTATUS PortMessage(PVOID PortCookie, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength, PULONG ReturnOutputBufferLength) {
UNREFERENCED_PARAMETER(PortCookie);
UNREFERENCED_PARAMETER(OutputBuffer);
UNREFERENCED_PARAMETER(OutputBufferLength);
if (InputBuffer && InputBufferLength >= sizeof(PYAS_USER_MESSAGE)) {
PPYAS_USER_MESSAGE msg = (PPYAS_USER_MESSAGE)InputBuffer;
if (msg->Command == 1 || msg->Command == 2) {
msg->Path[MAX_PATH_LEN - 1] = L'\0';
UNICODE_STRING us;
RtlInitUnicodeString(&us, msg->Path);
if (us.Length > 0) {
if (msg->Command == 1) {
AddDynamicWhitelist(&us);
}
else {
RemoveDynamicWhitelist(&us);
}
}
}
}
if (ReturnOutputBufferLength) {
*ReturnOutputBufferLength = 0;
}
return STATUS_SUCCESS;
}
static NTSTATUS PortConnect(PFLT_PORT ClientPort, PVOID ServerPortCookie, PVOID ConnectionContext, ULONG SizeOfContext, PVOID* ConnectionPortCookie) {
UNREFERENCED_PARAMETER(ServerPortCookie);
UNREFERENCED_PARAMETER(ConnectionContext);
UNREFERENCED_PARAMETER(SizeOfContext);
UNREFERENCED_PARAMETER(ConnectionPortCookie);
KIRQL OldIrql;
KeAcquireSpinLock(&GlobalData.PortMutex, &OldIrql);
GlobalData.ClientPort = ClientPort;
GlobalData.PyasPid = (ULONG)(ULONG_PTR)PsGetCurrentProcessId();
GlobalData.PyasProcess = PsGetCurrentProcess();
ExReInitializeRundownProtection(&GlobalData.PortRundown);
KeReleaseSpinLock(&GlobalData.PortMutex, OldIrql);
return STATUS_SUCCESS;
}
static VOID PortDisconnect(PVOID ConnectionCookie) {
UNREFERENCED_PARAMETER(ConnectionCookie);
KIRQL OldIrql;
KeAcquireSpinLock(&GlobalData.PortMutex, &OldIrql);
GlobalData.ClientPort = NULL;
GlobalData.PyasPid = 0;
GlobalData.PyasProcess = NULL;
KeReleaseSpinLock(&GlobalData.PortMutex, OldIrql);
ExWaitForRundownProtectionRelease(&GlobalData.PortRundown);
}
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 }
};
CONST FLT_REGISTRATION FilterRegistration = {
sizeof(FLT_REGISTRATION),
FLT_REGISTRATION_VERSION,
0,
NULL,
Callbacks,
DriverUnload,
InstanceSetup,
InstanceQueryTeardown,
InstanceTeardownStart,
InstanceTeardownComplete,
NULL,
NULL,
NULL
};
extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) {
NTSTATUS status = STATUS_SUCCESS;
PSECURITY_DESCRIPTOR sd = NULL;
OBJECT_ATTRIBUTES oa = { 0 };
UNICODE_STRING name = { 0 };
RtlZeroMemory(&GlobalData, sizeof(GlobalData));
GlobalData.DriverObject = DriverObject;
KeInitializeSpinLock(&GlobalData.PortMutex);
KeInitializeSpinLock(&GlobalData.TrackerMutex);
ExInitializeRundownProtection(&GlobalData.PortRundown);
InitializeRulesEngine();
status = LoadRulesFromDisk(RegistryPath);
status = FltRegisterFilter(DriverObject, &FilterRegistration, &GlobalData.FilterHandle);
if (!NT_SUCCESS(status)) {
UnloadRules();
UninitializeRulesEngine();
return status;
}
status = FltBuildDefaultSecurityDescriptor(&sd, FLT_PORT_ALL_ACCESS);
if (NT_SUCCESS(status)) {
RtlInitUnicodeString(&name, PYAS_PORT_NAME);
InitializeObjectAttributes(&oa, &name, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, sd);
status = FltCreateCommunicationPort(GlobalData.FilterHandle, &GlobalData.ServerPort, &oa, NULL, PortConnect, PortDisconnect, PortMessage, 1);
FltFreeSecurityDescriptor(sd);
}
if (!NT_SUCCESS(status)) {
FltUnregisterFilter(GlobalData.FilterHandle);
GlobalData.FilterHandle = NULL;
UnloadRules();
UninitializeRulesEngine();
return status;
}
InitializeProcessProtection();
InitializeRegistryProtection(DriverObject);
NTSTATUS imageNotifyStatus = PsSetLoadImageNotifyRoutine(ImageLoadNotify);
if (NT_SUCCESS(imageNotifyStatus)) {
g_ImageNotifyRegistered = TRUE;
}
status = FltStartFiltering(GlobalData.FilterHandle);
if (!NT_SUCCESS(status)) {
if (g_ImageNotifyRegistered) {
PsRemoveLoadImageNotifyRoutine(ImageLoadNotify);
g_ImageNotifyRegistered = FALSE;
}
UninitializeRegistryProtection();
UninitializeProcessProtection();
if (GlobalData.ServerPort) {
FltCloseCommunicationPort(GlobalData.ServerPort);
GlobalData.ServerPort = NULL;
}
if (GlobalData.FilterHandle) {
FltUnregisterFilter(GlobalData.FilterHandle);
GlobalData.FilterHandle = NULL;
}
UnloadRules();
UninitializeRulesEngine();
}
return status;
#include "DriverCommon.h"
DRIVER_DATA GlobalData;
static BOOLEAN g_ImageNotifyRegistered = FALSE;
static NTSTATUS InstanceSetup(PCFLT_RELATED_OBJECTS FltObjects, FLT_INSTANCE_SETUP_FLAGS Flags, DEVICE_TYPE VolumeDeviceType, FLT_FILESYSTEM_TYPE VolumeFilesystemType) {
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(Flags);
UNREFERENCED_PARAMETER(VolumeDeviceType);
UNREFERENCED_PARAMETER(VolumeFilesystemType);
return STATUS_SUCCESS;
}
static NTSTATUS InstanceQueryTeardown(PCFLT_RELATED_OBJECTS FltObjects, FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags) {
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(Flags);
return STATUS_SUCCESS;
}
static VOID InstanceTeardownStart(PCFLT_RELATED_OBJECTS FltObjects, FLT_INSTANCE_TEARDOWN_FLAGS Flags) {
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(Flags);
}
static VOID InstanceTeardownComplete(PCFLT_RELATED_OBJECTS FltObjects, FLT_INSTANCE_TEARDOWN_FLAGS Flags) {
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(Flags);
}
static NTSTATUS DriverUnload(FLT_FILTER_UNLOAD_FLAGS Flags) {
UNREFERENCED_PARAMETER(Flags);
if (GlobalData.ServerPort) {
FltCloseCommunicationPort(GlobalData.ServerPort);
GlobalData.ServerPort = NULL;
}
if (GlobalData.FilterHandle) {
FltUnregisterFilter(GlobalData.FilterHandle);
GlobalData.FilterHandle = NULL;
}
if (g_ImageNotifyRegistered) {
PsRemoveLoadImageNotifyRoutine(ImageLoadNotify);
g_ImageNotifyRegistered = FALSE;
}
UninitializeRegistryProtection();
UninitializeProcessProtection();
UnloadRules();
UninitializeRulesEngine();
GlobalData.Initialized = FALSE;
return STATUS_SUCCESS;
}
static NTSTATUS PortMessage(PVOID PortCookie, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength, PULONG ReturnOutputBufferLength) {
UNREFERENCED_PARAMETER(PortCookie);
UNREFERENCED_PARAMETER(OutputBuffer);
UNREFERENCED_PARAMETER(OutputBufferLength);
if (InputBuffer && InputBufferLength >= sizeof(PYAS_USER_MESSAGE)) {
PPYAS_USER_MESSAGE msg = (PPYAS_USER_MESSAGE)InputBuffer;
if (msg->Command == 1 || msg->Command == 2) {
msg->Path[MAX_PATH_LEN - 1] = L'\0';
UNICODE_STRING us;
RtlInitUnicodeString(&us, msg->Path);
if (us.Length > 0) {
if (msg->Command == 1) {
AddDynamicWhitelist(&us);
}
else {
RemoveDynamicWhitelist(&us);
}
}
}
}
if (ReturnOutputBufferLength) {
*ReturnOutputBufferLength = 0;
}
return STATUS_SUCCESS;
}
static NTSTATUS PortConnect(PFLT_PORT ClientPort, PVOID ServerPortCookie, PVOID ConnectionContext, ULONG SizeOfContext, PVOID* ConnectionPortCookie) {
UNREFERENCED_PARAMETER(ServerPortCookie);
UNREFERENCED_PARAMETER(ConnectionContext);
UNREFERENCED_PARAMETER(SizeOfContext);
UNREFERENCED_PARAMETER(ConnectionPortCookie);
KIRQL OldIrql;
KeAcquireSpinLock(&GlobalData.PortMutex, &OldIrql);
GlobalData.ClientPort = ClientPort;
SafeSetPyasPid((ULONG)(ULONG_PTR)PsGetCurrentProcessId());
GlobalData.PyasProcess = PsGetCurrentProcess();
ExReInitializeRundownProtection(&GlobalData.PortRundown);
KeReleaseSpinLock(&GlobalData.PortMutex, OldIrql);
return STATUS_SUCCESS;
}
static VOID PortDisconnect(PVOID ConnectionCookie) {
UNREFERENCED_PARAMETER(ConnectionCookie);
KIRQL OldIrql;
KeAcquireSpinLock(&GlobalData.PortMutex, &OldIrql);
GlobalData.ClientPort = NULL;
SafeSetPyasPid(0);
GlobalData.PyasProcess = NULL;
KeReleaseSpinLock(&GlobalData.PortMutex, OldIrql);
ExWaitForRundownProtectionRelease(&GlobalData.PortRundown);
}
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 }
};
CONST FLT_REGISTRATION FilterRegistration = {
sizeof(FLT_REGISTRATION),
FLT_REGISTRATION_VERSION,
0,
NULL,
Callbacks,
DriverUnload,
InstanceSetup,
InstanceQueryTeardown,
InstanceTeardownStart,
InstanceTeardownComplete,
NULL,
NULL,
NULL
};
extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) {
NTSTATUS status = STATUS_SUCCESS;
PSECURITY_DESCRIPTOR sd = NULL;
OBJECT_ATTRIBUTES oa = { 0 };
UNICODE_STRING name = { 0 };
RtlZeroMemory(&GlobalData, sizeof(GlobalData));
GlobalData.DriverObject = DriverObject;
KeInitializeSpinLock(&GlobalData.PortMutex);
KeInitializeSpinLock(&GlobalData.TrackerMutex);
KeInitializeSpinLock(&GlobalData.PidLock);
GlobalData.Initialized = TRUE;
ExInitializeRundownProtection(&GlobalData.PortRundown);
InitializeRulesEngine();
status = LoadRulesFromDisk(RegistryPath);
status = FltRegisterFilter(DriverObject, &FilterRegistration, &GlobalData.FilterHandle);
if (!NT_SUCCESS(status)) {
UnloadRules();
UninitializeRulesEngine();
return status;
}
status = FltBuildDefaultSecurityDescriptor(&sd, FLT_PORT_ALL_ACCESS);
if (NT_SUCCESS(status)) {
RtlInitUnicodeString(&name, PYAS_PORT_NAME);
InitializeObjectAttributes(&oa, &name, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, sd);
status = FltCreateCommunicationPort(GlobalData.FilterHandle, &GlobalData.ServerPort, &oa, NULL, PortConnect, PortDisconnect, PortMessage, 1);
FltFreeSecurityDescriptor(sd);
}
if (!NT_SUCCESS(status)) {
FltUnregisterFilter(GlobalData.FilterHandle);
GlobalData.FilterHandle = NULL;
UnloadRules();
UninitializeRulesEngine();
return status;
}
InitializeProcessProtection();
InitializeRegistryProtection(DriverObject);
NTSTATUS imageNotifyStatus = PsSetLoadImageNotifyRoutine(ImageLoadNotify);
if (NT_SUCCESS(imageNotifyStatus)) {
g_ImageNotifyRegistered = TRUE;
}
status = FltStartFiltering(GlobalData.FilterHandle);
if (!NT_SUCCESS(status)) {
if (g_ImageNotifyRegistered) {
PsRemoveLoadImageNotifyRoutine(ImageLoadNotify);
g_ImageNotifyRegistered = FALSE;
}
UninitializeRegistryProtection();
UninitializeProcessProtection();
if (GlobalData.ServerPort) {
FltCloseCommunicationPort(GlobalData.ServerPort);
GlobalData.ServerPort = NULL;
}
if (GlobalData.FilterHandle) {
FltUnregisterFilter(GlobalData.FilterHandle);
GlobalData.FilterHandle = NULL;
}
UnloadRules();
UninitializeRulesEngine();
}
return status;
}
+67 -24
View File
@@ -1,8 +1,10 @@
#include "DriverCommon.h"
static PVOID ObRegistrationHandle = NULL;
static OB_CALLBACK_REGISTRATION ObRegistration;
static OB_OPERATION_REGISTRATION ObCallbacks[2];
static OB_CALLBACK_REGISTRATION ObRegistration = {0};
static OB_OPERATION_REGISTRATION ObCallbacks[2] = {0};
static KSPIN_LOCK ObDataLock = {0};
static BOOLEAN ObDataInitialized = FALSE;
static BOOLEAN IsSystemImage(PUNICODE_STRING FullImageName) {
if (!FullImageName || !FullImageName->Buffer) return FALSE;
@@ -57,6 +59,10 @@ static BOOLEAN IsCriticalSystemProcess(HANDLE ProcessId) {
WildcardMatch(L"*\\Windows\\System32\\smss.exe", imageFileName->Buffer, imageFileName->Length)) {
isCritical = TRUE;
}
}
if (imageFileName) {
if (imageFileName->Buffer) ExFreePool(imageFileName->Buffer);
ExFreePool(imageFileName);
}
@@ -77,15 +83,17 @@ static BOOLEAN IsBlacklistedAdminTool(HANDLE ProcessId) {
status = SeLocateProcessImageName(Process, &imageFileName);
if (NT_SUCCESS(status) && imageFileName) {
if (imageFileName->Buffer) {
if (WildcardMatch(L"*Taskmgr.exe", imageFileName->Buffer, imageFileName->Length) ||
WildcardMatch(L"*taskkill.exe", imageFileName->Buffer, imageFileName->Length) ||
WildcardMatch(L"*ProcessHacker.exe", imageFileName->Buffer, imageFileName->Length) ||
WildcardMatch(L"*procmon.exe", imageFileName->Buffer, imageFileName->Length)) {
isBlacklisted = TRUE;
}
if (NT_SUCCESS(status) && imageFileName && imageFileName->Buffer) {
if (WildcardMatch(L"*Taskmgr.exe", imageFileName->Buffer, imageFileName->Length) ||
WildcardMatch(L"*taskkill.exe", imageFileName->Buffer, imageFileName->Length) ||
WildcardMatch(L"*ProcessHacker.exe", imageFileName->Buffer, imageFileName->Length) ||
WildcardMatch(L"*procmon.exe", imageFileName->Buffer, imageFileName->Length)) {
isBlacklisted = TRUE;
}
}
if (imageFileName) {
if (imageFileName->Buffer) ExFreePool(imageFileName->Buffer);
ExFreePool(imageFileName);
}
@@ -105,20 +113,37 @@ static OB_PREOP_CALLBACK_STATUS PreOpenProcess(PVOID RegistrationContext, POB_PR
HANDLE SourcePid = PsGetCurrentProcessId();
if (SourcePid == TargetPid) return OB_PREOP_SUCCESS;
if ((ULONG)(ULONG_PTR)SourcePid == GlobalData.PyasPid) return OB_PREOP_SUCCESS;
if ((ULONG)(ULONG_PTR)SourcePid == SafeGetPyasPid()) return OB_PREOP_SUCCESS;
if (SourcePid == (HANDLE)4) return OB_PREOP_SUCCESS;
if (IsTargetProtected(TargetPid)) {
if (IsCriticalSystemProcess(SourcePid)) return OB_PREOP_SUCCESS;
BOOLEAN bIsTrusted = IsProcessTrusted(SourcePid);
if (bIsTrusted) {
if (IsBlacklistedAdminTool(SourcePid)) {
bIsTrusted = FALSE;
}
BOOLEAN isBlacklisted = FALSE;
if (KeGetCurrentIrql() == PASSIVE_LEVEL) {
isBlacklisted = IsBlacklistedAdminTool(SourcePid);
}
if (isBlacklisted) {
ACCESS_MASK DenyMask = PROCESS_TERMINATE |
PROCESS_VM_OPERATION |
PROCESS_VM_WRITE |
PROCESS_CREATE_THREAD |
PROCESS_VM_READ |
PROCESS_DUP_HANDLE |
PROCESS_SUSPEND_RESUME |
PROCESS_SET_INFORMATION |
PROCESS_SET_QUOTA;
OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= (ACCESS_MASK)(~DenyMask);
if (OperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE) {
OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess &= (ACCESS_MASK)(~DenyMask);
}
return OB_PREOP_SUCCESS;
}
BOOLEAN bIsTrusted = IsProcessTrusted(SourcePid);
if (bIsTrusted) return OB_PREOP_SUCCESS;
ACCESS_MASK DenyMask = PROCESS_TERMINATE |
@@ -156,20 +181,33 @@ static OB_PREOP_CALLBACK_STATUS PreOpenThread(PVOID RegistrationContext, POB_PRE
HANDLE SourcePid = PsGetCurrentProcessId();
if (SourcePid == TargetPid) return OB_PREOP_SUCCESS;
if ((ULONG)(ULONG_PTR)SourcePid == GlobalData.PyasPid) return OB_PREOP_SUCCESS;
if ((ULONG)(ULONG_PTR)SourcePid == SafeGetPyasPid()) return OB_PREOP_SUCCESS;
if (SourcePid == (HANDLE)4) return OB_PREOP_SUCCESS;
if (IsTargetProtected(TargetPid)) {
if (IsCriticalSystemProcess(SourcePid)) return OB_PREOP_SUCCESS;
BOOLEAN bIsTrusted = IsProcessTrusted(SourcePid);
if (bIsTrusted) {
if (IsBlacklistedAdminTool(SourcePid)) {
bIsTrusted = FALSE;
}
BOOLEAN isBlacklisted = FALSE;
if (KeGetCurrentIrql() == PASSIVE_LEVEL) {
isBlacklisted = IsBlacklistedAdminTool(SourcePid);
}
if (isBlacklisted) {
ACCESS_MASK DenyMask = THREAD_TERMINATE |
THREAD_SUSPEND_RESUME |
THREAD_SET_CONTEXT |
THREAD_SET_INFORMATION |
THREAD_SET_THREAD_TOKEN;
OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= (ACCESS_MASK)(~DenyMask);
if (OperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE) {
OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess &= (ACCESS_MASK)(~DenyMask);
}
return OB_PREOP_SUCCESS;
}
BOOLEAN bIsTrusted = IsProcessTrusted(SourcePid);
if (bIsTrusted) return OB_PREOP_SUCCESS;
ACCESS_MASK DenyMask = THREAD_TERMINATE |
@@ -191,6 +229,9 @@ static OB_PREOP_CALLBACK_STATUS PreOpenThread(PVOID RegistrationContext, POB_PRE
NTSTATUS InitializeProcessProtection() {
static UNICODE_STRING Altitude = RTL_CONSTANT_STRING(L"320000.PYAS.Ob");
KeInitializeSpinLock(&ObDataLock);
ObDataInitialized = TRUE;
ObCallbacks[0].ObjectType = PsProcessType;
ObCallbacks[0].Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
ObCallbacks[0].PreOperation = PreOpenProcess;
@@ -219,6 +260,8 @@ NTSTATUS InitializeProcessProtection() {
}
VOID UninitializeProcessProtection() {
ObDataInitialized = FALSE;
if (ObRegistrationHandle) {
ObUnRegisterCallbacks(ObRegistrationHandle);
ObRegistrationHandle = NULL;
File diff suppressed because it is too large. Load diff
+3 -3
View File
@@ -128,9 +128,9 @@
"*\\360Safe.exe",
"*\\bilibili\\bilibili.exe",
"*\\Kingsoft\\WPS Office\\ksolaunch.exe",
"*\\Kingsoft\\WPS Office\\*\\wps.exe",
"*\\Kingsoft\\WPS Office\\*\\*.exe",
"*\\WPS Office\\ksolaunch.exe",
"*\\WPS Office\\*\\wps.exe",
"*\\WPS Office\\*\\*.exe",
"*\\PC4399_WPFLauncher.exe",
"*\\bin\\APlayer.exe",