This code includes anti-debug, obfuscation-ready structure, and encrypted validation.
SecureLicenseValidator.cs - Anti-Crack Edition
using System;
using System.Net;
using System.Text;
using System.Security.Cryptography;
using System.Diagnostics;
using System.Runtime.InteropServices;
using UnityEngine;
using System.Collections.Generic;
public class SecureLicenseValidator : MonoBehaviour
{
// OBFUSCATE THESE STRINGS IN BUILD!
private static readonly string FIREBASE_URL = ObfuscateString("YOUR_ENCRYPTED_URL");
private static readonly string SECRET_SALT = ObfuscateString("YOUR_SECRET_SALT");
[System.Serializable]
public class LicenseData
{
public string encryptedPayload;
public string iv;
public string hmac;
public long timestamp;
}
// Anti-debug: Check for debuggers
private static bool IsDebuggerPresent()
{
if (Debugger.IsAttached) return true;
// Check for common debuggers
string[] debuggers = { "cheatengine", "dnspy", "x64dbg", "x32dbg", "idaq" };
foreach (var proc in Process.GetProcesses())
{
string name = proc.ProcessName.ToLower();
foreach (var dbg in debuggers)
if (name.Contains(dbg)) return true;
}
return false;
}
// Anti-VM: Check for virtual machines
private static bool IsVirtualMachine()
{
// Check for VM artifacts
string[] vmIndicators = { "vmware", "virtualbox", "hyper-v", "xen" };
string systemInfo = SystemInfo.deviceModel + SystemInfo.operatingSystem;
foreach (var vm in vmIndicators)
if (systemInfo.ToLower().Contains(vm)) return true;
return false;
}
// Multi-factor HWID generation
public static string GetSecureHWID()
{
try
{
// Combine multiple hardware identifiers
string cpuId = SystemInfo.processorType;
string deviceId = SystemInfo.deviceUniqueIdentifier;
string graphics = SystemInfo.graphicsDeviceName;
string system = SystemInfo.operatingSystem;
// Add some entropy
string combined = $"{cpuId}|{deviceId}|{graphics}|{system}|{SECRET_SALT}";
using (SHA512 sha512 = SHA512.Create())
{
byte[] hash = sha512.ComputeHash(Encoding.UTF8.GetBytes(combined));
// Return first 32 chars of base64
return Convert.ToBase64String(hash).Substring(0, 32);
}
}
catch
{
// Fallback with obfuscation
return Convert.ToBase64String(Encoding.UTF8.GetBytes(
SystemInfo.deviceUniqueIdentifier + SECRET_SALT));
}
}
// Decrypt response from server
private static string DecryptPayload(string encrypted, string iv, string key)
{
try
{
byte[] encryptedBytes = Convert.FromBase64String(encrypted);
byte[] ivBytes = Convert.FromBase64String(iv);
byte[] keyBytes = Encoding.UTF8.GetBytes(key.PadRight(32).Substring(0, 32));
using (Aes aes = Aes.Create())
{
aes.Key = keyBytes;
aes.IV = ivBytes;
aes.Mode = CipherMode.CBC;
using (var decryptor = aes.CreateDecryptor())
{
byte[] result = decryptor.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
return Encoding.UTF8.GetString(result);
}
}
}
catch { return null; }
}
// Main validation with all protections
public static void ValidateLicenseSecure(string licenseKey, Action<bool, string> callback)
{
// Layer 1: Anti-debug
if (IsDebuggerPresent() && SECRET_SALT != "DEBUG_MODE")
{
callback(false, "Security violation detected");
ReportTampering("Debugger detected");
return;
}
// Layer 2: Anti-VM
if (IsVirtualMachine())
{
callback(false, "Virtual machines not supported");
return;
}
// Layer 3: Key format validation
if (!System.Text.RegularExpressions.Regex.IsMatch(licenseKey, @"^[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}$"))
{
callback(false, "Invalid key format");
return;
}
string hwid = GetSecureHWID();
string url = $"{FIREBASE_URL}/licenses/{licenseKey}.json";
using (WebClient client = new WebClient())
{
client.DownloadStringCompleted += (sender, e) =>
{
if (e.Error != null)
{
callback(false, "Network error");
return;
}
// Parse encrypted response
LicenseData data = JsonUtility.FromJson<LicenseData>(e.Result);
if (data == null || string.IsNullOrEmpty(data.encryptedPayload))
{
callback(false, "Invalid license");
return;
}
// Verify HMAC
string computedHmac = ComputeHmac(data.encryptedPayload, SECRET_SALT);
if (computedHmac != data.hmac)
{
callback(false, "Data tampering detected");
ReportTampering("HMAC mismatch");
return;
}
// Decrypt payload
string payload = DecryptPayload(data.encryptedPayload, data.iv, SECRET_SALT);
if (payload == null)
{
callback(false, "Decryption failed");
return;
}
// Check timestamp (prevent replay attacks)
long currentTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
if (Math.Abs(currentTime - data.timestamp) > 300) // 5 min tolerance
{
callback(false, "Request expired");
return;
}
// Validate HWID
if (payload.Contains("\"hwid\"") && !payload.Contains(hwid))
{
callback(false, "Hardware mismatch");
return;
}
callback(true, "License valid");
};
client.DownloadStringAsync(new Uri(url));
}
}
private static string ComputeHmac(string data, string key)
{
using (HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key)))
{
byte[] hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
return Convert.ToBase64String(hash);
}
}
private static void ReportTampering(string reason)
{
// Send tampering report to server
Debug.Log($"[SECURITY] Tampering detected: {reason}");
// Implementation: POST to your logging endpoint
}
// String obfuscation helper (call this at runtime)
private static string ObfuscateString(string input)
{
// Simple XOR obfuscation - replace with proper implementation
char[] result = new char[input.Length];
for (int i = 0; i < input.Length; i++)
result[i] = (char)(input[i] ^ 0x55);
return new string(result);
}
}
Build-Time Obfuscation Checklist
1. Use IL2CPP scripting backend (NOT Mono)
2. Enable "Release" mode with code stripping
3. Use Obfuscator Pro or Beebyte Obfuscator:
- Rename classes/methods
- Encrypt strings (especially FIREBASE_URL)
- Control flow obfuscation
- Anti-tamper protection
4. Remove debug symbols:
- Strip .pdb files
- Disable development build
5. Certificate pinning (optional but recommended):
- Hardcode Firebase SSL certificate hash
- Validate on every request