Add files via upload
This commit is contained in:
1 parent
b1b77b73ac
commit
d6bd383822
3 files changed
+262
-66
No files matched your search
+69
-32
@@ -110,7 +110,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
"修復映像劫持": "修復映像劫持",
|
||||
"修復桌面壁紙": "修復桌面壁紙",
|
||||
"正在掃描": "正在掃描",
|
||||
"正在刪除": "正在刪除"
|
||||
"正在刪除": "正在刪除",
|
||||
"選單掃描": "選單掃描",
|
||||
"此選項可以加入右鍵掃描": "此選項可以加入右鍵掃描"
|
||||
},
|
||||
"simplified_switch": {
|
||||
"PYAS Security": "PYAS Security",
|
||||
@@ -219,7 +221,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
"修復映像劫持": "修复映像劫持",
|
||||
"修復桌面壁紙": "修复桌面壁纸",
|
||||
"正在掃描": "正在扫描",
|
||||
"正在刪除": "正在删除"
|
||||
"正在刪除": "正在删除",
|
||||
"選單掃描": "菜单扫描",
|
||||
"此選項可以加入右鍵掃描": "此选项可以加入右键扫描菜单"
|
||||
},
|
||||
"english_switch": {
|
||||
"PYAS Security": "PYAS Security",
|
||||
@@ -328,7 +332,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
"修復映像劫持": "Repair Image Hijacking",
|
||||
"修復桌面壁紙": "Repair Desktop Wallpaper",
|
||||
"正在掃描": "Scanning...",
|
||||
"正在刪除": "Deleting..."
|
||||
"正在刪除": "Deleting...",
|
||||
"選單掃描": "Context Menu Scan",
|
||||
"此選項可以加入右鍵掃描": "Add scan option to right-click menu"
|
||||
},
|
||||
"japanese_switch": {
|
||||
"PYAS Security": "PYAS Security",
|
||||
@@ -437,7 +443,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
"修復映像劫持": "イメージハイジャックの修復",
|
||||
"修復桌面壁紙": "デスクトップの壁紙を修復",
|
||||
"正在掃描": "スキャン中...",
|
||||
"正在刪除": "削除中..."
|
||||
"正在刪除": "削除中...",
|
||||
"選單掃描": "コンテキストメニュースキャン",
|
||||
"此選項可以加入右鍵掃描": "右クリックメニューにスキャンオプションを追加します"
|
||||
},
|
||||
"korean_switch": {
|
||||
"PYAS Security": "PYAS Security",
|
||||
@@ -546,7 +554,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
"修復映像劫持": "이미지 하이재킹 복구",
|
||||
"修復桌面壁紙": "바탕 화면 배경 무늬 복구",
|
||||
"正在掃描": "스캔 중...",
|
||||
"正在刪除": "삭제 중..."
|
||||
"正在刪除": "삭제 중...",
|
||||
"選單掃描": "컨텍스트 메뉴 스캔",
|
||||
"此選項可以加入右鍵掃描": "마우스 우클릭 메뉴에 스캔 옵션을 추가합니다"
|
||||
},
|
||||
"french_switch": {
|
||||
"PYAS Security": "PYAS Security",
|
||||
@@ -655,7 +665,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
"修復映像劫持": "Réparer le détournement d'image",
|
||||
"修復桌面壁紙": "Réparer le fond d'écran du bureau",
|
||||
"正在掃描": "Analyse en cours...",
|
||||
"正在刪除": "Suppression en cours..."
|
||||
"正在刪除": "Suppression en cours...",
|
||||
"選單掃描": "Analyse du menu contextuel",
|
||||
"此選項可以加入右鍵掃描": "Ajouter l'option d'analyse au menu contextuel"
|
||||
},
|
||||
"spanish_switch": {
|
||||
"PYAS Security": "PYAS Security",
|
||||
@@ -764,7 +776,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
"修復映像劫持": "Reparar secuestro de imagen",
|
||||
"修復桌面壁紙": "Reparar fondo de escritorio",
|
||||
"正在掃描": "Escaneando...",
|
||||
"正在刪除": "Eliminando..."
|
||||
"正在刪除": "Eliminando...",
|
||||
"選單掃描": "Escaneo de menú contextual",
|
||||
"此選項可以加入右鍵掃描": "Añadir opción de escaneo al menú contextual"
|
||||
},
|
||||
"hindi_switch": {
|
||||
"PYAS Security": "PYAS Security",
|
||||
@@ -873,7 +887,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
"修復映像劫持": "छवि अपहरण की मरम्मत",
|
||||
"修復桌面壁紙": "डेस्कटॉप वॉलपेपर की मरम्मत",
|
||||
"正在掃描": "स्कैन कर रहा है...",
|
||||
"正在刪除": "हटा रहा है..."
|
||||
"正在刪除": "हटा रहा है...",
|
||||
"選單掃描": "संदर्भ मेनू स्कैन",
|
||||
"此選項可以加入右鍵掃描": "राइट-क्लिक मेनू में स्कैन विकल्प जोड़ें"
|
||||
},
|
||||
"arabic_switch": {
|
||||
"PYAS Security": "PYAS Security",
|
||||
@@ -982,7 +998,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
"修復映像劫持": "إصلاح اختطاف الصور",
|
||||
"修復桌面壁紙": "إصلاح خلفية سطح المكتب",
|
||||
"正在掃描": "جاري الفحص...",
|
||||
"正在刪除": "جاري الحذف..."
|
||||
"正在刪除": "جاري الحذف...",
|
||||
"選單掃描": "فحص قائمة السياق",
|
||||
"此選項可以加入右鍵掃描": "إضافة خيار الفحص إلى قائمة النقر الأيمن"
|
||||
},
|
||||
"russian_switch": {
|
||||
"PYAS Security": "PYAS Security",
|
||||
@@ -1091,7 +1109,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
"修復映像劫持": "Восстановление Image Hijacking",
|
||||
"修復桌面壁紙": "Восстановление обоев рабочего стола",
|
||||
"正在掃描": "Сканирование...",
|
||||
"正在刪除": "Удаление..."
|
||||
"正在刪除": "Удаление...",
|
||||
"選單掃描": "Сканирование из контекстного меню",
|
||||
"此選項可以加入右鍵掃描": "Добавить опцию сканирования в контекстное меню"
|
||||
},
|
||||
"slovenian_switch": {
|
||||
"PYAS Security": "PYAS Security",
|
||||
@@ -1200,7 +1220,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
"修復映像劫持": "Popravilo ugrabitve slike",
|
||||
"修復桌面壁紙": "Popravilo ozadja namizja",
|
||||
"正在掃描": "Skeniranje...",
|
||||
"正在刪除": "Brisanje..."
|
||||
"正在刪除": "Brisanje...",
|
||||
"選單掃描": "Skeniranje iz kontekstnega menija",
|
||||
"此選項可以加入右鍵掃描": "Dodaj možnost skeniranja v kontekstni meni"
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1521,7 +1543,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
|
||||
window.revertSwitch = (switchKey) => {
|
||||
const switchMap = ["process_switch", "document_switch", "system_switch", "driver_switch", "network_switch", "sensitive_switch", "extension_switch", "cloud_switch"];
|
||||
const switchMap = ["process_switch", "document_switch", "system_switch", "driver_switch", "network_switch", "sensitive_switch", "extension_switch", "cloud_switch", "context_switch"];
|
||||
const index = switchMap.indexOf(switchKey);
|
||||
if (index !== -1) {
|
||||
const toggle = document.querySelectorAll('.toggle-switch input')[index];
|
||||
@@ -1533,13 +1555,47 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
document.querySelectorAll('.toggle-switch input').forEach((toggle, index) => {
|
||||
toggle.addEventListener('change', (e) => {
|
||||
const switchMap = ["process_switch", "document_switch", "system_switch", "driver_switch", "network_switch", "sensitive_switch", "extension_switch", "cloud_switch"];
|
||||
const switchMap = ["process_switch", "document_switch", "system_switch", "driver_switch", "network_switch", "sensitive_switch", "extension_switch", "cloud_switch", "context_switch"];
|
||||
if (window.pywebview && switchMap[index]) {
|
||||
window.pywebview.api.update_config(switchMap[index], e.target.checked);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
window.triggerContextScan = (path) => {
|
||||
if (isScanning) return;
|
||||
switchPage('scan_window');
|
||||
if (window.pywebview) {
|
||||
isScanning = true;
|
||||
virusList.innerHTML = '';
|
||||
scanMethodSelect.classList.add('hidden');
|
||||
stopBtn.classList.remove('hidden');
|
||||
solveBtn.classList.add('hidden');
|
||||
if (progressTitle) progressTitle.textContent = getMsg("正在掃描");
|
||||
progressText.textContent = getMsg("正在初始化中");
|
||||
window.pywebview.api.start_scan([path]);
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('pywebviewready', () => {
|
||||
window.pywebview.api.get_config().then(cfg => {
|
||||
const theme = cfg.theme || "white_switch";
|
||||
const lang = cfg.language || "english_switch";
|
||||
applyTheme(theme);
|
||||
translateText(lang);
|
||||
updateCustomSelectUI('theme_select', theme);
|
||||
updateCustomSelectUI('lang_select', lang);
|
||||
|
||||
const switchMap = ["process_switch", "document_switch", "system_switch", "driver_switch", "network_switch", "sensitive_switch", "extension_switch", "cloud_switch", "context_switch"];
|
||||
document.querySelectorAll('.toggle-switch input').forEach((toggle, index) => {
|
||||
if (switchMap[index]) {
|
||||
toggle.checked = !!cfg[switchMap[index]];
|
||||
}
|
||||
});
|
||||
});
|
||||
window.pywebview.api.init_ui_ready();
|
||||
});
|
||||
|
||||
function renderManageList(containerSelector, dataList, displayKey, valKey, defaultChecked = false) {
|
||||
const container = document.querySelector(`${containerSelector} .manage-list`);
|
||||
const searchInput = document.querySelector(`${containerSelector} .search-box input`);
|
||||
@@ -1918,23 +1974,4 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('pywebviewready', () => {
|
||||
window.pywebview.api.get_config().then(cfg => {
|
||||
const theme = cfg.theme || "white_switch";
|
||||
const lang = cfg.language || "english_switch";
|
||||
applyTheme(theme);
|
||||
translateText(lang);
|
||||
updateCustomSelectUI('theme_select', theme);
|
||||
updateCustomSelectUI('lang_select', lang);
|
||||
|
||||
const switchMap = ["process_switch", "document_switch", "system_switch", "driver_switch", "network_switch", "sensitive_switch", "extension_switch", "cloud_switch"];
|
||||
document.querySelectorAll('.toggle-switch input').forEach((toggle, index) => {
|
||||
if (switchMap[index]) {
|
||||
toggle.checked = !!cfg[switchMap[index]];
|
||||
}
|
||||
});
|
||||
});
|
||||
window.pywebview.api.init_ui_ready();
|
||||
});
|
||||
});
|
||||
@@ -203,6 +203,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"><span class="slider"></span></label>
|
||||
</div>
|
||||
<div class="list-item">
|
||||
<div class="item-info">
|
||||
<h2 data-i18n>顯色主題</h2><p data-i18n>此選項可以選擇主題顏色</p>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import os, re, sys, time, json, uuid, queue, msvcrt, winreg, pystray
|
||||
import shutil, hashlib, platform, threading, subprocess, pefile
|
||||
import os, re, sys, time, json, uuid, stat, queue, msvcrt, winreg
|
||||
import shutil, hashlib, platform, threading, subprocess, pefile, pystray
|
||||
import socket, requests, webview, webbrowser, ctypes, ctypes.wintypes
|
||||
|
||||
from PIL import Image, ImageDraw
|
||||
@@ -101,6 +101,13 @@ class PYAS_USER_MESSAGE(ctypes.Structure):
|
||||
("Path", ctypes.wintypes.WCHAR * 1024)
|
||||
]
|
||||
|
||||
class COPYDATASTRUCT(ctypes.Structure):
|
||||
_fields_ = [
|
||||
("dwData", ctypes.c_size_t),
|
||||
("cbData", ctypes.wintypes.DWORD),
|
||||
("lpData", ctypes.c_void_p)
|
||||
]
|
||||
|
||||
####################################################################################################
|
||||
|
||||
class WindowAPI:
|
||||
@@ -117,7 +124,28 @@ class WindowAPI:
|
||||
if not self.check_singleton("PYAS_Security_Mutex"):
|
||||
hwnd = self.user32.FindWindowW(None, "PYAS Security")
|
||||
if hwnd:
|
||||
self.user32.ShowWindow(hwnd, 9)
|
||||
if "-scan" in self.args_pyas:
|
||||
try:
|
||||
idx = self.args_pyas.index("-scan")
|
||||
target = self.args_pyas[idx+1]
|
||||
cds = COPYDATASTRUCT()
|
||||
cds.dwData = 1
|
||||
encoded = target.encode('utf-8')
|
||||
cds.cbData = len(encoded) + 1
|
||||
buffer = ctypes.create_string_buffer(encoded)
|
||||
cds.lpData = ctypes.cast(buffer, ctypes.c_void_p)
|
||||
self.user32.SendMessageTimeoutW(hwnd, 0x004A, 0, ctypes.byref(cds), 0x0002, 3000, None)
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
cds = COPYDATASTRUCT()
|
||||
cds.dwData = 2
|
||||
cds.cbData = 0
|
||||
cds.lpData = None
|
||||
self.user32.SendMessageTimeoutW(hwnd, 0x004A, 0, ctypes.byref(cds), 0x0002, 3000, None)
|
||||
except Exception:
|
||||
pass
|
||||
self.user32.SetForegroundWindow(hwnd)
|
||||
os._exit(0)
|
||||
|
||||
@@ -135,6 +163,11 @@ class WindowAPI:
|
||||
return False
|
||||
|
||||
def init_ui_ready(self):
|
||||
with self.lock_config:
|
||||
if self.engine_initialized:
|
||||
return
|
||||
self.engine_initialized = True
|
||||
|
||||
self.start_daemon_thread(self.init_engine_thread)
|
||||
|
||||
def set_window(self, window):
|
||||
@@ -206,25 +239,42 @@ class WindowAPI:
|
||||
|
||||
def restore_from_tray(self, icon=None, item=None):
|
||||
if self._window:
|
||||
self._window.restore()
|
||||
self._window.show()
|
||||
|
||||
hwnd = self.user32.FindWindowW(None, "PYAS Security")
|
||||
if hwnd:
|
||||
self.user32.ShowWindow(hwnd, 9)
|
||||
self.user32.SetForegroundWindow(hwnd)
|
||||
|
||||
def close(self):
|
||||
with self.lock_config:
|
||||
self.pyas_config["process_switch"] = False
|
||||
self.pyas_config["document_switch"] = False
|
||||
self.pyas_config["system_switch"] = False
|
||||
self.pyas_config["driver_switch"] = False
|
||||
self.pyas_config["network_switch"] = False
|
||||
def close(self, *args, **kwargs):
|
||||
if self.tray_icon:
|
||||
try:
|
||||
self.tray_icon.stop()
|
||||
except Exception:
|
||||
pass
|
||||
self.tray_icon = None
|
||||
|
||||
self.stop_system_driver()
|
||||
if self._window:
|
||||
self._window.destroy()
|
||||
os._exit(0)
|
||||
try:
|
||||
self._window.hide()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _cleanup_and_exit():
|
||||
with self.lock_config:
|
||||
self.pyas_config["process_switch"] = False
|
||||
self.pyas_config["document_switch"] = False
|
||||
self.pyas_config["system_switch"] = False
|
||||
self.pyas_config["driver_switch"] = False
|
||||
self.pyas_config["network_switch"] = False
|
||||
|
||||
self.stop_system_driver()
|
||||
|
||||
if self._window:
|
||||
self._window.destroy()
|
||||
os._exit(0)
|
||||
|
||||
threading.Thread(target=_cleanup_and_exit, daemon=True).start()
|
||||
|
||||
def get_file_version(self, file_path):
|
||||
try:
|
||||
@@ -257,7 +307,12 @@ class WindowAPI:
|
||||
####################################################################################################
|
||||
|
||||
def init_environ(self):
|
||||
self.file_pyas = self.norm_path(sys.argv[0])
|
||||
self.python = sys.executable
|
||||
if getattr(sys, 'frozen', False):
|
||||
self.file_pyas = self.norm_path(sys.executable)
|
||||
else:
|
||||
self.file_pyas = self.norm_path(os.path.abspath(sys.argv[0]))
|
||||
|
||||
self.args_pyas = sys.argv[1:]
|
||||
self.path_pyas = os.path.dirname(self.file_pyas)
|
||||
self.pid_pyas = int(os.getpid())
|
||||
@@ -365,6 +420,7 @@ class WindowAPI:
|
||||
self.mbr_backup = {}
|
||||
self.logs_data = []
|
||||
self.tray_icon = None
|
||||
self.engine_initialized = False
|
||||
|
||||
self.pyas_default = {
|
||||
"version": "3.5.0",
|
||||
@@ -383,6 +439,7 @@ class WindowAPI:
|
||||
"extension_switch": False,
|
||||
"sensitive_switch": False,
|
||||
"cloud_switch": True,
|
||||
"context_switch": False,
|
||||
"custom_rule": [],
|
||||
"white_list": [],
|
||||
"quarantine": [],
|
||||
@@ -441,6 +498,8 @@ class WindowAPI:
|
||||
self.start_daemon_thread(self.protect_system_thread)
|
||||
elif key == "network_switch" and value:
|
||||
self.start_daemon_thread(self.protect_net_thread)
|
||||
elif key == "context_switch":
|
||||
self.register_context_menu(value)
|
||||
elif key == "driver_switch":
|
||||
if value:
|
||||
if self.install_system_driver():
|
||||
@@ -458,6 +517,40 @@ class WindowAPI:
|
||||
with self.lock_config:
|
||||
return self.pyas_config.copy()
|
||||
|
||||
####################################################################################################
|
||||
|
||||
def register_context_menu(self, enable):
|
||||
paths = [
|
||||
r"Software\Classes\*\shell\PYAS_Scan",
|
||||
r"Software\Classes\Directory\shell\PYAS_Scan"
|
||||
]
|
||||
|
||||
if getattr(sys, 'frozen', False):
|
||||
cmd_path = f'"{self.file_pyas}"'
|
||||
else:
|
||||
cmd_path = f'"{self.python}" "{self.file_pyas}"'
|
||||
|
||||
try:
|
||||
for path in paths:
|
||||
if enable:
|
||||
with winreg.CreateKey(winreg.HKEY_CURRENT_USER, path) as key:
|
||||
winreg.SetValue(key, "", winreg.REG_SZ, "PYAS Security Scan")
|
||||
winreg.SetValueEx(key, "Icon", 0, winreg.REG_SZ, f'{cmd_path},0')
|
||||
with winreg.CreateKey(winreg.HKEY_CURRENT_USER, rf"{path}\command") as key:
|
||||
winreg.SetValue(key, "", winreg.REG_SZ, f'{cmd_path} -scan "%1"')
|
||||
else:
|
||||
try:
|
||||
winreg.DeleteKey(winreg.HKEY_CURRENT_USER, rf"{path}\command")
|
||||
winreg.DeleteKey(winreg.HKEY_CURRENT_USER, path)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.write_log("WARN", "register_context_menu", detail=str(e), success=False)
|
||||
|
||||
def trigger_context_scan(self, target):
|
||||
if self._window:
|
||||
self._window.evaluate_js(f"if(window.triggerContextScan) window.triggerContextScan({json.dumps(target.replace(os.sep, '/'))});")
|
||||
|
||||
####################################################################################################
|
||||
|
||||
def show_notification(self, title, message):
|
||||
@@ -711,6 +804,14 @@ class WindowAPI:
|
||||
self.properties.load_path(self.path_properties, callback=log_callback)
|
||||
self.write_log("INFO", "System", detail="Engine Initialization Complete")
|
||||
|
||||
if "-scan" in self.args_pyas:
|
||||
try:
|
||||
idx = self.args_pyas.index("-scan")
|
||||
target = self.args_pyas[idx+1]
|
||||
self.trigger_context_scan(target)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
with self.lock_config:
|
||||
if self.pyas_config.get("process_switch"): self.start_daemon_thread(self.protect_proc_thread)
|
||||
if self.pyas_config.get("document_switch"): self.start_daemon_thread(self.protect_file_thread)
|
||||
@@ -725,7 +826,6 @@ class WindowAPI:
|
||||
except Exception as e:
|
||||
self.write_log("WARN", "init_engine_thread", detail=str(e), success=False)
|
||||
|
||||
|
||||
def backup_mbr(self, max_drives=26):
|
||||
self.mbr_backup = {}
|
||||
mbr_signature = b"\x55\xAA"
|
||||
@@ -898,6 +998,8 @@ class WindowAPI:
|
||||
|
||||
def solve_scan(self, file_paths):
|
||||
deleted_paths = []
|
||||
running_procs = self.get_process_list()
|
||||
|
||||
with self.lock_virus:
|
||||
for path in file_paths:
|
||||
if self._window:
|
||||
@@ -907,9 +1009,18 @@ class WindowAPI:
|
||||
if path in self.virus_lock:
|
||||
self.lock_file(path, False)
|
||||
|
||||
os.remove(path)
|
||||
deleted_paths.append(path)
|
||||
for proc in running_procs:
|
||||
if self.path_equal(proc["path"], path):
|
||||
self.kill_process(proc["pid"])
|
||||
|
||||
try:
|
||||
os.chmod(path, stat.S_IWRITE)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
os.remove(path)
|
||||
|
||||
deleted_paths.append(path)
|
||||
if path in self.virus_results:
|
||||
self.virus_results.remove(path)
|
||||
|
||||
@@ -1634,6 +1745,10 @@ class WindowAPI:
|
||||
self.ntdll.NtSuspendProcess(h)
|
||||
try:
|
||||
cmdline = self.get_process_cmdline(h)
|
||||
|
||||
if "-scan" in cmdline and self.path_equal(self.get_process_file(h), self.file_pyas):
|
||||
return
|
||||
|
||||
paths = self.extract_paths_from_cmdline(cmdline)
|
||||
with self.lock_config:
|
||||
suffix = self.pyas_config.get("suffix", [])
|
||||
@@ -1724,6 +1839,10 @@ class WindowAPI:
|
||||
hDir = self.kernel32.CreateFileW(self.path_user, 0x0001, 0x00000007, None, 3, 0x02000000, None)
|
||||
buffer = ctypes.create_string_buffer(65536)
|
||||
|
||||
temp_prefix = os.path.normcase(self.path_temp)
|
||||
if not temp_prefix.endswith(os.sep):
|
||||
temp_prefix += os.sep
|
||||
|
||||
while True:
|
||||
with self.lock_config:
|
||||
if not self.pyas_config.get("document_switch", False):
|
||||
@@ -1741,6 +1860,13 @@ class WindowAPI:
|
||||
|
||||
file_path = self.norm_path(os.path.join(self.path_user, raw_filename), must_exist=True)
|
||||
if file_path and notify.Action in [2, 3, 4] and not self.is_in_whitelist(file_path):
|
||||
|
||||
norm_path = os.path.normcase(file_path)
|
||||
if norm_path.startswith(temp_prefix):
|
||||
sub_path = norm_path[len(temp_prefix):]
|
||||
if sub_path.startswith("_mei"):
|
||||
continue
|
||||
|
||||
with self.lock_config:
|
||||
suffix = self.pyas_config.get("suffix", [])
|
||||
|
||||
@@ -1766,7 +1892,7 @@ class WindowAPI:
|
||||
if not self.pyas_config.get("network_switch", False):
|
||||
break
|
||||
try:
|
||||
time.sleep(0.2)
|
||||
time.sleep(0.5)
|
||||
conns = self.get_connections_list()
|
||||
|
||||
for key in conns - self.exist_connections:
|
||||
@@ -1851,7 +1977,7 @@ class WindowAPI:
|
||||
while time.time() - start_time < 5:
|
||||
hwnd = self.user32.GetForegroundWindow()
|
||||
if not hwnd:
|
||||
time.sleep(0.2)
|
||||
time.sleep(0.5)
|
||||
continue
|
||||
|
||||
pid = ctypes.c_ulong(0)
|
||||
@@ -1870,7 +1996,7 @@ class WindowAPI:
|
||||
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}
|
||||
|
||||
time.sleep(0.2)
|
||||
time.sleep(0.5)
|
||||
except Exception as e:
|
||||
self.write_log("WARN", "capture_popup_window", detail=str(e), success=False)
|
||||
return None
|
||||
@@ -2138,24 +2264,20 @@ class WindowAPI:
|
||||
WNDENUMPROC = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.c_int, ctypes.c_int)
|
||||
while True:
|
||||
try:
|
||||
time.sleep(0.2)
|
||||
time.sleep(0.5)
|
||||
with self.lock_config:
|
||||
rules = self.pyas_config.get("block_list", [])
|
||||
cur_ver = self.pyas_config.get("version", "0.0.0")
|
||||
|
||||
hwnd_list = []
|
||||
def enum_windows_callback(hWnd, lParam):
|
||||
hwnd_list.append(hWnd)
|
||||
if self.user32.IsWindowVisible(hWnd):
|
||||
hwnd_list.append(hWnd)
|
||||
return True
|
||||
|
||||
self.user32.EnumWindows(WNDENUMPROC(enum_windows_callback), 0)
|
||||
|
||||
for hWnd in hwnd_list:
|
||||
length = self.user32.GetWindowTextLengthW(hWnd)
|
||||
title = ctypes.create_unicode_buffer(length + 1)
|
||||
self.user32.GetWindowTextW(hWnd, title, length + 1)
|
||||
class_name = ctypes.create_unicode_buffer(256)
|
||||
self.user32.GetClassNameW(hWnd, class_name, 256)
|
||||
pid = ctypes.c_ulong(0)
|
||||
self.user32.GetWindowThreadProcessId(hWnd, ctypes.byref(pid))
|
||||
|
||||
@@ -2163,22 +2285,32 @@ class WindowAPI:
|
||||
continue
|
||||
|
||||
proc_name, file_path = self.get_exe_info(pid.value)
|
||||
|
||||
if proc_name != "PYAS_Setup.exe" and not rules:
|
||||
continue
|
||||
|
||||
length = self.user32.GetWindowTextLengthW(hWnd)
|
||||
title = ctypes.create_unicode_buffer(length + 1)
|
||||
self.user32.GetWindowTextW(hWnd, title, length + 1)
|
||||
class_name = ctypes.create_unicode_buffer(256)
|
||||
self.user32.GetClassNameW(hWnd, class_name, 256)
|
||||
|
||||
t_str = str(title.value)
|
||||
c_str = str(class_name.value)
|
||||
|
||||
|
||||
if proc_name == "PYAS_Setup.exe" and c_str == "WindowClass_0" and t_str == "PYAS Setup":
|
||||
if file_path:
|
||||
setup_ver = self.get_file_version(file_path)
|
||||
if self.compare_versions(setup_ver, cur_ver):
|
||||
self.close()
|
||||
|
||||
if not rules:
|
||||
continue
|
||||
|
||||
is_pass = any(item.get("exe") == proc_name or item.get("class") == c_str for item in self.pass_windows)
|
||||
if is_pass:
|
||||
continue
|
||||
|
||||
if not rules:
|
||||
continue
|
||||
|
||||
is_block = any(item.get("exe") == proc_name or item.get("class") == c_str or item.get("title") == t_str for item in rules)
|
||||
if is_block:
|
||||
for msg in [0x0010, 0x0002, 0x0012, 0x0112]:
|
||||
@@ -2231,11 +2363,13 @@ class NoCacheRequestHandler(SimpleHTTPRequestHandler):
|
||||
####################################################################################################
|
||||
|
||||
class WindowHook:
|
||||
def __init__(self, title):
|
||||
def __init__(self, title, api_ref=None):
|
||||
self.title = title
|
||||
self.api_ref = api_ref
|
||||
self.old_wndproc = None
|
||||
self.WM_DPICHANGED = 0x02E0
|
||||
self.WM_NCHITTEST = 0x0084
|
||||
self.WM_COPYDATA = 0x004A
|
||||
self.HTCAPTION = 2
|
||||
self.GWLP_WNDPROC = -4
|
||||
|
||||
@@ -2275,6 +2409,25 @@ class WindowHook:
|
||||
|
||||
if msg == 0x0112 and (wparam & 0xFFF0) == 0xF060:
|
||||
return 0
|
||||
|
||||
if msg == self.WM_COPYDATA:
|
||||
try:
|
||||
cds = ctypes.cast(lparam, ctypes.POINTER(COPYDATASTRUCT)).contents
|
||||
if cds.dwData == 1:
|
||||
buffer = ctypes.string_at(cds.lpData, cds.cbData)
|
||||
path = buffer.decode('utf-8').strip('\x00')
|
||||
if self.api_ref:
|
||||
if self.api_ref._window:
|
||||
self.api_ref._window.restore()
|
||||
self.api_ref._window.show()
|
||||
threading.Thread(target=self.api_ref.trigger_context_scan, args=(path,), daemon=True).start()
|
||||
elif cds.dwData == 2:
|
||||
if self.api_ref and self.api_ref._window:
|
||||
self.api_ref._window.restore()
|
||||
self.api_ref._window.show()
|
||||
except Exception:
|
||||
pass
|
||||
return 1
|
||||
|
||||
if msg == self.WM_NCHITTEST:
|
||||
x = lparam & 0xFFFF
|
||||
@@ -2335,7 +2488,7 @@ if __name__ == "__main__":
|
||||
background_color='#e0e0e0', hidden=hide_on_start)
|
||||
|
||||
if platform.system() == "Windows":
|
||||
window_hook = WindowHook("PYAS Security")
|
||||
window_hook = WindowHook("PYAS Security", js_api)
|
||||
window.events.shown += window_hook.hook
|
||||
|
||||
js_api.set_window(window)
|
||||
|
||||
Reference in new issue
Block a user