Обновление Защитника + TXT инструкции

This commit is contained in:
Данил Ярош 2026-03-10 10:30:07 +03:00
parent 833ec4ca6f
commit ce851f8ef2
4 changed files with 607 additions and 178 deletions

View File

@ -10,211 +10,310 @@ by:kotovskij393
Вот этот функционал скопировать. Где то в точке старта будем вызывать (Отдельным файлом):
##### Код
```cs
    #region DEFENCE
    #region DEFENCE
[StructLayout(LayoutKind.Sequential)]
private struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
    [StructLayout(LayoutKind.Sequential)]
    private struct PROCESS_INFORMATION
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct STARTUPINFO
{
public int cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public int dwX;
public int dwY;
public int dwXSize;
public int dwYSize;
public int dwXCountChars;
public int dwYCountChars;
public int dwFillAttribute;
public int dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
    {
        public IntPtr hProcess;
        public IntPtr hThread;
        public int dwProcessId;
        public int dwThreadId;
    }
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool CreateProcess(
string lpApplicationName,
string lpCommandLine,
IntPtr lpProcessAttributes,
IntPtr lpThreadAttributes,
bool bInheritHandles,
uint dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    private struct STARTUPINFO
    {
        public int cb;
        public string lpReserved;
        public string lpDesktop;
        public string lpTitle;
        public int dwX;
        public int dwY;
        public int dwXSize;
        public int dwYSize;
        public int dwXCountChars;
        public int dwYCountChars;
        public int dwFillAttribute;
        public int dwFlags;
        public short wShowWindow;
        public short cbReserved2;
        public IntPtr lpReserved2;
        public IntPtr hStdInput;
        public IntPtr hStdOutput;
        public IntPtr hStdError;
    }
[DllImport("kernel32.dll", SetLastError = true)]
private static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern bool CreateProcess(
        string lpApplicationName,
        string lpCommandLine,
        IntPtr lpProcessAttributes,
        IntPtr lpThreadAttributes,
        bool bInheritHandles,
        uint dwCreationFlags,
        IntPtr lpEnvironment,
        string lpCurrentDirectory,
        ref STARTUPINFO lpStartupInfo,
        out PROCESS_INFORMATION lpProcessInformation);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool GetExitCodeProcess(IntPtr hProcess, out uint lpExitCode);
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool GetExitCodeProcess(IntPtr hProcess, out uint lpExitCode);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(IntPtr hObject);
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool CloseHandle(IntPtr hObject);
private const uint WAIT_TIMEOUT = 0x00000102;
private const uint WAIT_OBJECT_0 = 0x00000000;
    private const uint WAIT_TIMEOUT = 0x00000102;
    private const uint WAIT_OBJECT_0 = 0x00000000;
private System.Collections.IEnumerator CheckLicenseCoroutine()
{
// Ждём один кадр, чтобы Unity завершил инициализацию
yield return null;
    private System.Collections.IEnumerator CheckLicenseCoroutine()
    {
        // Ждём один кадр, чтобы Unity завершил инициализацию
        yield return null;
        bool licenseValid = false;
        bool checkCompleted = false;
        //bool licenseValid = true;
        //bool checkCompleted = true;
        string errorMessage = "";
bool licenseValid = false;
bool checkCompleted = false;
//bool licenseValid = true;
//bool checkCompleted = true;
string errorMessage = "";
        // Запускаем проверку в отдельном потоке (совместимо с IL2CPP)
        System.Threading.Thread thread = new System.Threading.Thread(() =>
        {
            try
            {
                licenseValid = CheckLicense();
            }
            catch (Exception ex)
            {
                errorMessage = ex.Message;
            }
            finally
            {
                checkCompleted = true;
            }
        });
// Запускаем проверку в отдельном потоке (совместимо с IL2CPP)
System.Threading.Thread thread = new System.Threading.Thread(() =>
{
try
{
licenseValid = CheckLicense();
}
catch (Exception ex)
{
errorMessage = ex.Message;
}
finally
{
checkCompleted = true;
}
});
        thread.IsBackground = true;
        thread.Start();
thread.IsBackground = true;
thread.Start();
        float timerest = 30f;
       
        while (!checkCompleted && timerest > 0)
        {
            timerest -= Time.deltaTime;
            yield return null;
        }
float timerest = 30f;
while (!checkCompleted && timerest > 0)
{
timerest -= Time.deltaTime;
yield return null;
}
        if (!checkCompleted) licenseValid = false;
if (!checkCompleted) licenseValid = false;
if (!licenseValid)
{
yield return new WaitForSeconds(3f);
        if (!licenseValid)
        {
            yield return new WaitForSeconds(3f);
#if UNITY_EDITOR
            EditorApplication.isPlaying = false;
EditorApplication.isPlaying = false;
#else
            Application.Quit();
Application.Quit();
#endif
        }
    }
}
else
{
//exclusive
Screen.fullScreenMode = FullScreenMode.ExclusiveFullScreen;
Screen.SetResolution(1920, 1080, true);
ClickCenter();
}
}
    /// <summary>
    /// Проверяет лицензию через внешний лаунчер RRLauncher.exe.
    /// Возвращает true, если проверка пройдена, иначе false.
    /// </summary>
    private bool CheckLicense()
    {
        try
        {
            string launcherName = "RRLauncher.exe";
            string launcherPath = null;
           
            // Поиск лаунчера рядом с исполняемым файлом
            string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
            string pathInBase = Path.Combine(baseDirectory, launcherName);
            if (File.Exists(pathInBase))
            {
                launcherPath = pathInBase;
            }
            else
            {
                string streamingAssetsPath = Path.Combine(Application.streamingAssetsPath, launcherName);
                if (File.Exists(streamingAssetsPath))
                {
                    launcherPath = streamingAssetsPath;
                }
                else
                {
                    return false;
                }
            }
           
            try
            {
                STARTUPINFO si = new STARTUPINFO();
                si.cb = Marshal.SizeOf(si);
                PROCESS_INFORMATION pi;
private bool CheckLicense()
{
try
{
string launcherName = "RRLauncher.exe";
string launcherPath = null;
                string workingDir = Path.GetDirectoryName(launcherPath);
// Поиск лаунчера рядом с исполняемым файлом
string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
string pathInBase = Path.Combine(baseDirectory, launcherName);
                bool success = CreateProcess(
                    launcherPath,
                    null,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    false,
                    0,
                    IntPtr.Zero,
                    workingDir,
                    ref si,
                    out pi);
if (File.Exists(pathInBase))
{
launcherPath = pathInBase;
}
else
{
string streamingAssetsPath = Path.Combine(Application.streamingAssetsPath, launcherName);
if (File.Exists(streamingAssetsPath))
{
launcherPath = streamingAssetsPath;
}
else
{
return false;
}
}
                if (!success) return false;
try
{
STARTUPINFO si = new STARTUPINFO();
si.cb = Marshal.SizeOf(si);
PROCESS_INFORMATION pi;
                uint waitResult = WaitForSingleObject(pi.hProcess, 30000);
string workingDir = Path.GetDirectoryName(launcherPath);
                if (waitResult == WAIT_TIMEOUT)
                {
                    CloseHandle(pi.hProcess);
                    CloseHandle(pi.hThread);
                    return false;
                }
bool success = CreateProcess(
launcherPath,
null,
IntPtr.Zero,
IntPtr.Zero,
false,
0,
IntPtr.Zero,
workingDir,
ref si,
out pi);
                // Получение кода возврата
                uint exitCode;
               
                if (!GetExitCodeProcess(pi.hProcess, out exitCode))
                {
                    CloseHandle(pi.hProcess);
                    CloseHandle(pi.hThread);
                    return false;
                }
if (!success) return false;
uint waitResult = WaitForSingleObject(pi.hProcess, 30000);
                CloseHandle(pi.hProcess);
                CloseHandle(pi.hThread);
if (waitResult == WAIT_TIMEOUT)
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return false;
}
                if (exitCode == 0) return true;
// Получение кода возврата
uint exitCode;
if (!GetExitCodeProcess(pi.hProcess, out exitCode))
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return false;
}
                return false;
            }
            catch
            {
                return false;
            }
        }
        catch (Exception outerEx)
        {
            UnityEngine.Debug.LogError($"[License] CRITICAL ERROR in CheckLicense: {outerEx.Message}");
            UnityEngine.Debug.LogError($"[License] Stack trace: {outerEx.StackTrace}");
            return false;
        }
    }
    #endregion
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
if (exitCode == 0)
{
ForceToFront();
return true;
}
return false;
}
catch
{
return false;
}
}
catch (Exception outerEx)
{
Debug.LogError($"[License] CRITICAL ERROR in CheckLicense: {outerEx.Message}");
Debug.LogError($"[License] Stack trace: {outerEx.StackTrace}");
return false;
}
}
#region FORCE TO FRONT
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hwnd);
[DllImport("user32.dll")]
private static extern IntPtr GetActiveWindow();
public void ForceToFront()//Метод который возвращает фокус а окно после открытия защиты
{
IntPtr handle = GetActiveWindow();
SetForegroundWindow(handle);
}
#endregion
#region клик в центр
[StructLayout(LayoutKind.Sequential)]
public struct INPUT
{
public uint type;
public MOUSEINPUT mi;
}
[StructLayout(LayoutKind.Sequential)]
public struct MOUSEINPUT
{
public int dx;
public int dy;
public uint mouseData;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
private const uint INPUT_MOUSE = 0;
private const uint MOUSEEVENTF_MOVE = 0x0001;
private const uint MOUSEEVENTF_ABSOLUTE = 0x8000;
private const uint MOUSEEVENTF_LEFTDOWN = 0x0002;
private const uint MOUSEEVENTF_LEFTUP = 0x0004;
[DllImport("user32.dll")]
static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
public static void ClickCenter()
{
int screenX = Screen.currentResolution.width / 2;
int screenY = Screen.currentResolution.height / 2;
// WinAPI использует координаты 0–65535
int absoluteX = (int)(screenX * 65535 / Screen.currentResolution.width);
int absoluteY = (int)(screenY * 65535 / Screen.currentResolution.height);
INPUT[] inputs = new INPUT[3];
// движение мыши
inputs[0] = new INPUT
{
type = INPUT_MOUSE,
mi = new MOUSEINPUT
{
dx = absoluteX,
dy = absoluteY,
dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
}
};
// нажатие
inputs[1] = new INPUT
{
type = INPUT_MOUSE,
mi = new MOUSEINPUT
{
dwFlags = MOUSEEVENTF_LEFTDOWN
}
};
// отпускание
inputs[2] = new INPUT
{
type = INPUT_MOUSE,
mi = new MOUSEINPUT
{
dwFlags = MOUSEEVENTF_LEFTUP
}
};
SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT)));
}
#endregion
#endregion
```
##### Привязка к игре

View File

@ -0,0 +1,20 @@
1. Поместить RRLauncher.exe в папку Assets\StreamingAssets\
2. Добавить в какой либо скрипт содержимое файла Защитник.txt.
В идеале в bootstrap-script если он реализован
3. Запустить корутину с защитой (пример в файле Вызов.txt)
ВНИМАНИЕ!!!
В алгоритме есть такой костыль, может мешать работе если другое разрешение или несколько мониторов.
Можно пробовать запустить без костыля и дай бог всё будет хорошо
На фишке до какой то поры всё было хорошо, потом сломалось.
else
{
Screen.fullScreenMode = FullScreenMode.ExclusiveFullScreen;
Screen.SetResolution(1920, 1080, true);
ClickCenter();
}
Лицензирование производится отдельной программой, которую можно попросить у Бори или Тимура

View File

@ -0,0 +1,6 @@
private void Awake()
{
#if !UNITY_EDITOR
StartCoroutine(CheckLicenseCoroutine());
#endif
}

View File

@ -0,0 +1,304 @@
#region DEFENCE
[StructLayout(LayoutKind.Sequential)]
private struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct STARTUPINFO
{
public int cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public int dwX;
public int dwY;
public int dwXSize;
public int dwYSize;
public int dwXCountChars;
public int dwYCountChars;
public int dwFillAttribute;
public int dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool CreateProcess(
string lpApplicationName,
string lpCommandLine,
IntPtr lpProcessAttributes,
IntPtr lpThreadAttributes,
bool bInheritHandles,
uint dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool GetExitCodeProcess(IntPtr hProcess, out uint lpExitCode);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(IntPtr hObject);
private const uint WAIT_TIMEOUT = 0x00000102;
private const uint WAIT_OBJECT_0 = 0x00000000;
private System.Collections.IEnumerator CheckLicenseCoroutine()
{
// Ждём один кадр, чтобы Unity завершил инициализацию
yield return null;
bool licenseValid = false;
bool checkCompleted = false;
//bool licenseValid = true;
//bool checkCompleted = true;
string errorMessage = "";
// Запускаем проверку в отдельном потоке (совместимо с IL2CPP)
System.Threading.Thread thread = new System.Threading.Thread(() =>
{
try
{
licenseValid = CheckLicense();
}
catch (Exception ex)
{
errorMessage = ex.Message;
}
finally
{
checkCompleted = true;
}
});
thread.IsBackground = true;
thread.Start();
float timerest = 30f;
while (!checkCompleted && timerest > 0)
{
timerest -= Time.deltaTime;
yield return null;
}
if (!checkCompleted) licenseValid = false;
if (!licenseValid)
{
yield return new WaitForSeconds(3f);
#if UNITY_EDITOR
EditorApplication.isPlaying = false;
#else
Application.Quit();
#endif
}
else
{
//exclusive
Screen.fullScreenMode = FullScreenMode.ExclusiveFullScreen;
Screen.SetResolution(1920, 1080, true);
ClickCenter();
}
}
private bool CheckLicense()
{
try
{
string launcherName = "RRLauncher.exe";
string launcherPath = null;
// Поиск лаунчера рядом с исполняемым файлом
string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
string pathInBase = Path.Combine(baseDirectory, launcherName);
if (File.Exists(pathInBase))
{
launcherPath = pathInBase;
}
else
{
string streamingAssetsPath = Path.Combine(Application.streamingAssetsPath, launcherName);
if (File.Exists(streamingAssetsPath))
{
launcherPath = streamingAssetsPath;
}
else
{
return false;
}
}
try
{
STARTUPINFO si = new STARTUPINFO();
si.cb = Marshal.SizeOf(si);
PROCESS_INFORMATION pi;
string workingDir = Path.GetDirectoryName(launcherPath);
bool success = CreateProcess(
launcherPath,
null,
IntPtr.Zero,
IntPtr.Zero,
false,
0,
IntPtr.Zero,
workingDir,
ref si,
out pi);
if (!success) return false;
uint waitResult = WaitForSingleObject(pi.hProcess, 30000);
if (waitResult == WAIT_TIMEOUT)
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return false;
}
// Получение кода возврата
uint exitCode;
if (!GetExitCodeProcess(pi.hProcess, out exitCode))
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return false;
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
if (exitCode == 0)
{
ForceToFront();
return true;
}
return false;
}
catch
{
return false;
}
}
catch (Exception outerEx)
{
Debug.LogError($"[License] CRITICAL ERROR in CheckLicense: {outerEx.Message}");
Debug.LogError($"[License] Stack trace: {outerEx.StackTrace}");
return false;
}
}
#region FORCE TO FRONT
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hwnd);
[DllImport("user32.dll")]
private static extern IntPtr GetActiveWindow();
public void ForceToFront()//Метод который возвращает фокус а окно после открытия защиты
{
IntPtr handle = GetActiveWindow();
SetForegroundWindow(handle);
}
#endregion
#region клик в центр
[StructLayout(LayoutKind.Sequential)]
public struct INPUT
{
public uint type;
public MOUSEINPUT mi;
}
[StructLayout(LayoutKind.Sequential)]
public struct MOUSEINPUT
{
public int dx;
public int dy;
public uint mouseData;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
private const uint INPUT_MOUSE = 0;
private const uint MOUSEEVENTF_MOVE = 0x0001;
private const uint MOUSEEVENTF_ABSOLUTE = 0x8000;
private const uint MOUSEEVENTF_LEFTDOWN = 0x0002;
private const uint MOUSEEVENTF_LEFTUP = 0x0004;
[DllImport("user32.dll")]
static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
public static void ClickCenter()
{
int screenX = Screen.currentResolution.width / 2;
int screenY = Screen.currentResolution.height / 2;
// WinAPI использует координаты 0–65535
int absoluteX = (int)(screenX * 65535 / Screen.currentResolution.width);
int absoluteY = (int)(screenY * 65535 / Screen.currentResolution.height);
INPUT[] inputs = new INPUT[3];
// движение мыши
inputs[0] = new INPUT
{
type = INPUT_MOUSE,
mi = new MOUSEINPUT
{
dx = absoluteX,
dy = absoluteY,
dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
}
};
// нажатие
inputs[1] = new INPUT
{
type = INPUT_MOUSE,
mi = new MOUSEINPUT
{
dwFlags = MOUSEEVENTF_LEFTDOWN
}
};
// отпускание
inputs[2] = new INPUT
{
type = INPUT_MOUSE,
mi = new MOUSEINPUT
{
dwFlags = MOUSEEVENTF_LEFTUP
}
};
SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT)));
}
#endregion
#endregion