using UnityEngine; using System.Runtime.InteropServices; using System; using System.Text; using AOT; namespace NTESHTPSec { public enum RequestCmdID { // 签名信息 Cmd_GetSignInfo = 0, // 越狱状态 Cmd_IsRootDevice = 2, // SDK版本 Cmd_GetHTPVersion = 7, // 获取超时数据 Cmd_GetCollectData = 8, // 初始化配置内容,防止初始化失败情况下,客户可以通过服务端请求初始化配置并传递给SDK Cmd_SetConfigData = 16, // 客户服务端将check结果传递给SDK,便于执行后续动作 Cmd_SetResponseData = 17, // 获取服务端设备指纹 Cmd_GetDeviceId = 20, }; // 安全通信结果类 public class SafeCommResult { public static int SC_CODE_OK = 0; public static int SC_FILE_NOTEXIST = -1; // apk包文件无文件 public static int SC_FILE_IS_BROKEN = -2; // apk包文件损坏 public static int SC_PROTOCOL_VERSION_ERROR = -3; // 协议版本不匹配 public static int SC_PARAM_ERROR = -4; // 参数错误 public static int SC_DATA_TAMPERED = -5; // 数据被篡改 public static int SC_DATA_DECRYPT_ERROR = -6; // 数据解密失败 public static int SC_ALG_ERROR = -7; // 算法不匹配,指定算法解密 public static int SC_TIMEOUT = -8; // 超时 public static int SC_ENV = -9; // 当前环境存在frida xposed unidbg public static int SC_DEVICE = -10; // 设备不匹配 public static int SC_NOT_INIT = -201; // 未初始化 public static int SC_CLOSED = -202; // 试用到期 public static int SC_BUFF_MALLOC_ERROR = -98; // 这种情况一般不会出现 public static int SC_INSIDE_ERROR = -99; //内部错误,一般不会出现 public int ret; public byte[] encBytes; public string encResult; public string signResult; public byte[] decResult; public SafeCommResult() { ret = SC_INSIDE_ERROR; decResult = null; encBytes = null; } } public class AntiCheatResult { public int code; public string codeStr; public string token; public string businessId; public AntiCheatResult(int code, string codeStr, string token, string businessId) { this.code = code; this.codeStr = codeStr; this.token = token; this.businessId = businessId; } } public class NTESRiskSecProtect : MonoBehaviour { private static bool isInitialized = false; public delegate void InitCallback(int code, string msg, string content); public delegate void getTokenAysncBlock(AntiCheatResult result); private static getTokenAysncBlock getTokenAsyncCallback; public delegate void TokenBlockCallback(string token, int code, string codeStr, string businessId); // 初始化 public static void init(string productId, InitCallback callback) { if (isInitialized) { System.Console.Write("NTESSecProtect is already initialized. "); return; } #if UNITY_IPHONE || UNITY_IOS if (Application.platform == RuntimePlatform.IPhonePlayer) { System.Console.Write("NTESSecProtect is start initialized. " + callback); ___initWithProductId(productId, callback); } #endif isInitialized = true; } // 登录 public static int setRoleInfo(string businessId, string roleId, string roleName, string roleAccount, string roleServer, int serverid, string gameJson) { int ret = 0; #if UNITY_IPHONE || UNITY_IOS if (Application.platform == RuntimePlatform.IPhonePlayer) { ret = ___setRoleInfo(businessId, roleId, roleName, roleAccount, roleServer, serverid, gameJson); } #endif return ret; } /** * 获取Token,默认超时3s * * @param bussinessId 场景id * @param timeout 超时时间(范围:10000ms以内 单位:ms) * * @return 获取到的token,用于校验是否有作弊行为 */ public static AntiCheatResult getToken(int timeout, string businessId) { #if UNITY_IPHONE || UNITY_IOS if (Application.platform == RuntimePlatform.IPhonePlayer) { IntPtr outPtr = IntPtr.Zero; IntPtr codeStrPtr = IntPtr.Zero; string token = null; string codeStr = null; int tokenOutLen = 0; int codeStrOutLen = 0; int ret = ___getToken(businessId, timeout, ref outPtr, ref tokenOutLen, ref codeStrPtr, ref codeStrOutLen); byte[] cc = new byte[tokenOutLen]; Marshal.Copy(outPtr, cc, 0, tokenOutLen); token = Encoding.ASCII.GetString(cc); ___safeFree(ref outPtr); byte[] codeStrBytes = new byte[codeStrOutLen]; Marshal.Copy(codeStrPtr, codeStrBytes, 0, codeStrOutLen); codeStr = Encoding.ASCII.GetString(codeStrBytes); ___safeFree(ref codeStrPtr); AntiCheatResult result = new AntiCheatResult(ret, codeStr, token, businessId); return result; } #endif return null; } /** * 获取Token,默认超时3s * * @param bussinessId 场景id * @param timeout 超时时间(范围:10000ms以内 单位:ms) * @param callback 获取Token完成后回调 * */ public static void getTokenAsync(int timeout, String businessId, getTokenAysncBlock callback) { #if UNITY_IPHONE || UNITY_IOS if (Application.platform == RuntimePlatform.IPhonePlayer) { getTokenAsyncCallback = callback; TokenBlockCallback callbackC = new TokenBlockCallback(getTokenCallback); ___getTokenAsync(businessId, timeout, callbackC); } #endif } [MonoPInvokeCallback(typeof(TokenBlockCallback))] private static void getTokenCallback(string token, int code, string message, string businessId) { AntiCheatResult result = new AntiCheatResult(code, message, token, businessId); if (null != getTokenAsyncCallback) { getTokenAsyncCallback(result); } } /** * 获取Token,默认超时3s * * @param bussinessId 场景id * @param timeout 超时时间(范围:10000ms以内 单位:ms) * @param callback 获取Token完成后回调(直接传入回调,避免同步问题) * */ public static void getTokenAsync(int timeout, String businessId, TokenBlockCallback callback) { #if UNITY_IPHONE || UNITY_IOS if (Application.platform == RuntimePlatform.IPhonePlayer) { ___getTokenAsync(businessId, timeout, callback); } #endif } //退出登陆 public static void logOut() { #if UNITY_IPHONE || UNITY_IOS if (Application.platform == RuntimePlatform.IPhonePlayer) { ___logOut(); } #endif } public static string ioctl(RequestCmdID request, string data) { string result = "unsupported request"; #if UNITY_IPHONE || UNITY_IOS if (Application.platform == RuntimePlatform.IPhonePlayer) { result = ___ioctl(request, data); } #endif return result; } //设置服务器类型 public static void setServerType(int serverType) { Debug.Log($"setServerType -> {serverType}"); #if UNITY_IPHONE || UNITY_IOS if (Application.platform == RuntimePlatform.IPhonePlayer) { ___setServerType(serverType); } #endif } //设置渠道信息 public static void setChannel(string channel) { Debug.Log($"setChannel -> {channel}"); #if UNITY_IPHONE || UNITY_IOS if (Application.platform == RuntimePlatform.IPhonePlayer) { ___setChannel(channel); } #endif } //设置渠道信息 public static void setExtraData(string key, string value) { #if UNITY_IPHONE || UNITY_IOS if (Application.platform == RuntimePlatform.IPhonePlayer) { ___setExtraData(value, key); } #endif } public static void setHost(string host) { #if UNITY_IPHONE || UNITY_IOS if (Application.platform == RuntimePlatform.IPhonePlayer) { ___setHost(host); } #endif } // 获取数据签名 public static string getDataSign(string inputData) { string result = null; #if UNITY_IPHONE || UNITY_IOS if (Application.platform == RuntimePlatform.IPhonePlayer) { if (inputData != null && inputData.Length > 0) { result = ___getDataSign(inputData); } } #endif return result; } public static int safeCommToServer(int alg, byte[] inputData, int dataSize, ref IntPtr outData, ref int outLen) { int ret = 0; #if UNITY_IPHONE || UNITY_IOS if (Application.platform == RuntimePlatform.IPhonePlayer) { ret = ___safeCommToServer(alg, inputData, dataSize, ref outData, ref outLen); } #endif return ret; } public static int safeCommToServerByte(int alg, byte[] inputData, int dataSize, ref IntPtr outData, ref int outLen) { int ret = 0; #if UNITY_IPHONE || UNITY_IOS if (Application.platform == RuntimePlatform.IPhonePlayer) { ret = ___safeCommToServerByte(alg, inputData, dataSize, ref outData, ref outLen); } #endif return ret; } public static int safeCommFromServer(int alg, int timeout, string inputData, int dataSize, ref IntPtr outData, ref int outLen) { int ret = 0; #if UNITY_IPHONE || UNITY_IOS if (Application.platform == RuntimePlatform.IPhonePlayer) { ret = ___safeCommFromServer(alg, timeout, inputData, dataSize, ref outData, ref outLen); } #endif return ret; } public static int safeCommFromServerByte(int alg, int timeout, byte[] inputData, int dataSize, ref IntPtr outData, ref int outLen) { int ret = 0; #if UNITY_IPHONE || UNITY_IOS if (Application.platform == RuntimePlatform.IPhonePlayer) { ret = ___safeCommFromServerByte(alg, timeout, inputData, dataSize, ref outData, ref outLen); } #endif return ret; } public static NTESHTPSec.SafeCommResult safeCommToServerByteV30(int version, int alg, byte[] inputData, bool isCrucial) { NTESHTPSec.SafeCommResult safeCommResult = new NTESHTPSec.SafeCommResult(); if (inputData == null || inputData.Length == 0) { safeCommResult.ret = NTESHTPSec.SafeCommResult.SC_PARAM_ERROR; return safeCommResult; } #if UNITY_IPHONE || UNITY_IOS if (Application.platform == RuntimePlatform.IPhonePlayer) { try { var ptr = IntPtr.Zero; var size = oOOO00Oo0000o0OO(version, false, isCrucial, alg, inputData, inputData.Length, ref ptr); if (size <= 0 ) { safeCommResult.ret = size; } else { safeCommResult.ret = NTESHTPSec.SafeCommResult.SC_CODE_OK; safeCommResult.encBytes = new byte[size]; Marshal.Copy(ptr, safeCommResult.encBytes, 0, size); ___safeFree(ref ptr); } } catch (System.Exception e) { Debug.LogError("safeCommToServer" + e.ToString()); } } #endif return safeCommResult; } public static NTESHTPSec.SafeCommResult safeCommToServerV30(int version, int alg, byte[] inputData, bool isCrucial) { NTESHTPSec.SafeCommResult safeCommResult = new NTESHTPSec.SafeCommResult(); if (inputData == null || inputData.Length == 0) { safeCommResult.ret = NTESHTPSec.SafeCommResult.SC_PARAM_ERROR; return safeCommResult; } #if UNITY_IPHONE || UNITY_IOS if (Application.platform == RuntimePlatform.IPhonePlayer) { try { var ptr = IntPtr.Zero; var size = oOOO00Oo0000o0OO(version, true, isCrucial, alg, inputData, inputData.Length, ref ptr); if (size <= 0 ) { safeCommResult.ret = size; } else { safeCommResult.ret = NTESHTPSec.SafeCommResult.SC_CODE_OK; safeCommResult.encResult = Marshal.PtrToStringAnsi(ptr); ___safeFree(ref ptr); } } catch (System.Exception e) { Debug.LogError("safeCommToServer" + e.ToString()); } } #endif return safeCommResult; } public static void registerTouchEvent(ulong gameplayId, ulong sceneId) { #if UNITY_IPHONE || UNITY_IOS if (Application.platform == RuntimePlatform.IPhonePlayer) { ___registerTouchEvent(gameplayId, sceneId); } #endif } public static void unregisterTouchEvent() { #if UNITY_IPHONE || UNITY_IOS if (Application.platform == RuntimePlatform.IPhonePlayer) { ___unregisterTouchEvent(); } #endif } public static void safeFree(ref IntPtr outData) { #if UNITY_IPHONE || UNITY_IOS if (Application.platform == RuntimePlatform.IPhonePlayer) { ___safeFree(ref outData); } #endif } // ret为0时,signResult保存签名结果 public static NTESHTPSec.SafeCommResult htpSign(int version, int alg, byte[] inputData) { NTESHTPSec.SafeCommResult safeCommResult = new NTESHTPSec.SafeCommResult(); if (inputData == null || inputData.Length == 0) { safeCommResult.ret = NTESHTPSec.SafeCommResult.SC_PARAM_ERROR; return safeCommResult; } #if UNITY_IPHONE || UNITY_IOS try { var ptr = IntPtr.Zero; var size = ___htpSign(version, alg, inputData, inputData.Length, ref ptr); if (size <= 0) { safeCommResult.ret = size; } else { safeCommResult.ret = NTESHTPSec.SafeCommResult.SC_CODE_OK; safeCommResult.signResult = Marshal.PtrToStringAnsi(ptr); ___safeFree(ref ptr); } } catch (System.Exception e) { Debug.LogError("htpSign" + e.ToString()); } #endif return safeCommResult; } public static void clearAllBlock() { #if UNITY_IPHONE || UNITY_IOS ___clearAllBlock(); #endif } #if UNITY_IPHONE || UNITY_IOS [DllImport("__Internal")] private static extern void ___initWithProductId(string productId, InitCallback callback); [DllImport("__Internal")] private static extern int ___setRoleInfo(string businessId, string roleId, string roleName, string roleAccount, string roleServer, int serverid, string gameJson); [DllImport("__Internal")] private static extern int ___getToken(string bussinessId, int timeout, ref IntPtr outData, ref int outLen, ref IntPtr codeStr, ref int codeStrOutLen); [DllImport("__Internal")] private static extern void ___getTokenAsync(string bussinessId, int timeout, TokenBlockCallback callback); [DllImport("__Internal")] private static extern void ___logOut(); [DllImport("__Internal")] private static extern void ___clearAllBlock(); [DllImport("__Internal")] private static extern string ___ioctl(RequestCmdID request, string data); [DllImport("__Internal")] private static extern void ___setServerType(int type); [DllImport("__Internal")] private static extern void ___setChannel(string channel); [DllImport("__Internal")] private static extern void ___setExtraData(string value, string key); [DllImport("__Internal")] private static extern void ___setHost(string host); [DllImport("__Internal")] private static extern string ___getDataSign(string data); [DllImport("__Internal")] public static extern int ___safeCommToServer(int alg, byte[] inputData, int dataSize, ref IntPtr outData, ref int outLen); [DllImport("__Internal")] public static extern int ___safeCommToServerByte(int alg, byte[] inputData, int dataSize, ref IntPtr outData, ref int outLen); [DllImport("__Internal")] public static extern int ___safeCommFromServer(int alg, int timeout, string inputData, int dataSize, ref IntPtr outData, ref int outLen); [DllImport("__Internal")] public static extern int ___safeCommFromServerByte(int alg, int timeout, byte[] inputData, int dataSize, ref IntPtr outData, ref int outLen); [DllImport("__Internal")] public static extern int oOOO00Oo0000o0OO(int version, bool encode, bool isCrucial, int alg, byte[] data, int len, ref IntPtr ptr); [DllImport("__Internal")] public static extern int ___htpSign(int alg, int version, byte[] src, int dataSize, ref IntPtr outData); [DllImport("__Internal")] public static extern void ___registerTouchEvent(ulong gameplayId, ulong sceneId); [DllImport("__Internal")] public static extern void ___unregisterTouchEvent(); [DllImport("__Internal")] public static extern void ___safeFree(ref IntPtr outData); #endif } }