端游智能反外挂(Windows)接入文档

2024.07.09 11:03:55

    隐私说明

    请参照网易易盾隐私政策

    接入说明

    前言

    端游智能反外挂的接入,从流程上分为三大部分,依次为:

    • 接入SDK(用于初始化角色信息)
    • 使用工具加固游戏(用于植入反外挂引擎)
    • 测试防护效果与数据上报链路是否正常

    本文将依次对这三部分的内容做具体的阐述。

    具体的接入与检测数据交互流程可参考下图:

    	游戏方 ->> 易盾方: 注册易盾账号并创建产品
    	易盾方 -->> 游戏方: 提供SDK及加固工具
    	游戏方 ->> 游戏方: 接入SDK,游戏出包(游戏账号初始化)
    	游戏方 ->> 易盾方: 使用加固工具请求加固
    	易盾方 -->> 易盾方: 在线加固,将反外挂引擎置入游戏包
    	易盾方 -->> 游戏方: 加固后的游戏包
    	游戏方 ->> 游戏方: 重新签名(包括加固目标PE及反外挂模块NEP2.dll)
    	游戏方 ->> 游戏方: 启动游戏,启动外挂(如CE)测试保护效果
    	游戏方 ->> 易盾方: 上报外挂玩家信息
    	易盾方 -->> 游戏方: 将确认的外挂数据同步到易盾官网后台
    	游戏服务端 ->> 游戏服务端: (可选)接入OpenAPI
    	游戏服务端 ->> 易盾方: 调用接口自动化拉取检测数据
    	易盾方 -->> 游戏服务端: 检测到的确认外挂数据
    	游戏服务端 ->> 游戏服务端: 保存检测数据
    	Note over 易盾方,游戏服务端: OpenAPI可打通检测链路 实现实时惩罚与数据追溯
    

    SDK接入步骤

    需要接入的SDK有:

    • NEPLauncher(必接,游戏客户端接入,用于初始化角色信息)
    • NEPSplash(可选,游戏客户端接入,用于展示易盾加载动画)
    • OpenAPI(可选,游戏服务端接入,用于自动化查询检测数据)

    接入NEPLauncher

    NEPLauncher的主要作用是用来接收游戏账号信息、校验反外挂引擎的状态以及设置数据透传的接口,并不提供额外的安全功能,这部分的接入工作由拥有账号信息的一方实施。为了在易盾监测到外挂时方便了解是哪个角色在使用外挂,因此这一步必须要接入,保证外挂检测信息与账号信息的关联。

    该模块的接入方式按照程序开发环境的不同,分为VC++静态库(针对Visual Studio 2015以后的版本,推荐首先考虑这种接入方式)、VC++动态库(针对较低的VS版本或其他无法接入静态库的情况)与unitypackage(Unity3D C#语言开发的游戏)三种接入方式。

    下文对这三种方式做了简要介绍,具体的接入示例请见易盾方提供的接入Demo。

    静态库接入NEPLauncher

    静态库SDK包括以下两个文件:

    NEPLauncher.h
    NEPLauncher.lib

    其中NEPLauncher.lib区分32位或64位,编译选项MT/MD,Unicode/MultiByte,编译工具v141/v142;v141最低支持的Visual Studio版本为2015,低于2015的VS版本请参考下一节选择动态库接入方式。

    接入步骤依次为:

    • 根据游戏的位数和编译选项选择合适的lib文件,配置到VS工程属性-链接器-常规-附加库目录
    • 将头文件配置到VS工程属性-C/C++-常规-附加包含目录
    • 在合适的位置包含头文件与静态lib
    • 调用角色信息初始化接口 NEP_SetAccountInfo
    • (推荐)调用拉取嫌疑数据接口 NEP_PullDoubtData,用于数据透传,从反外挂引擎拉取嫌疑数据和其他反外挂相关数据到游戏客户端
    • (可选)调用反外挂状态检查初始化接口 NEP_InstallStatusChecker,用于异步地检查反外挂引擎的工作状态是否正常
    • (可选)调用反外挂状态同步检查接口 NEP_GetSecurityStatus,用于同步地检查反外挂引擎工作状态,立即返回检查结果
    • (可选)调用停止异步检查接口 NEP_UninstallStatusChecker,用于停止异步检查反外挂引擎工作状态

    接口说明与接入示例详见第四章SDK接入调用说明。

    动态库接入NEPLauncher

    对于开发环境使用的不是Visual Studio,或Visual Studio版本过低,以及无法接入v141及以上版本静态lib的其他情况,可以使用这种接入方式。

    动态库SDK包含三个文件:

    NEPLauncher.h NEPLauncher.cpp NEPLauncher.dll

    接入步骤依次为:

    • 根据游戏将32位或64位的 NEPLauncher.dll 放置在游戏启动器同一目录(如果不能放置在同一目录, 请修改 NEPLauncher.cpp 中获取 NEPLauncher.dll路径的代码)
    • 在游戏登录逻辑相关代码处包含头文件: #include "NEPLauncher.h"
    • 调用 NEP_SetAccountInfo接口初始化角色信息
    • (推荐)调用拉取嫌疑数据接口 NEP_PullDoubtData,用于数据透传,从反外挂引擎拉取嫌疑数据和其他反外挂相关数据到游戏客户端
    • (可选)调用反外挂状态检查初始化接口 NEP_InstallStatusChecker,用于异步地检查反外挂引擎的工作状态是否正常
    • (可选)调用反外挂状态同步检查接口 NEP_GetSecurityStatus,用于同步地检查反外挂引擎工作状态,立即返回检查结果
    • (可选)调用停止异步检查接口 NEP_UninstallStatusChecker,用于停止异步检查反外挂引擎工作状态

    接口说明与接入示例详见第四章SDK接入调用说明。

    Unity3D接入NEPLauncher

    Uniy3D C#接入SDK仅需导入一个文件

    NEPLauncher-[version].unitypackage

    接入步骤依次为:

    • 在Unity3D工程中导入该unitypackage
    • 导入后,SDK代码位于NLPC目录下
    • 在游戏登录逻辑相关代码处 using NLPC;
    • 调用 LaunchStub.SetAccountProc 接口初始化角色信息。
    • (推荐)调用 LaunchStub.PullDoubtData 接入数据透传功能,从反外挂引擎拉取嫌疑数据和其他反外挂相关数据到游戏客户端。

    接口说明与接入示例详见第四章SDK接入调用说明。

    配置UAC(若需要开启驱动防护功能,则需要进行配置)

    NEP驱动的安装与卸载需要管理员权限,因此被加固的PE文件在运行时需要具备管理员权限,即用户双击程序打开游戏时,若没有管理员权限,会要求授予,否则将无法打开游戏。这里介绍两种开启UAC配置的方式。

    Visual Studio 开启UAC

    右键目标VS工程,选择属性,之后依次点击链接器-清单文件:

    • 生成清单一栏选择 是 (/MANIFEST)
    • 启用用户账户控制(UAC)一栏选择 是 (/MANIFESTUAC:)
    • UAC执行级别一栏选择 requireAdministrator (/level='requireAdministrator')

    如此配置好重新编译后,再加固即可。

    Unity3D 开启UAC

    Unity3D也类似,需要针对Windows平台,先重新编译WindowsPlayer.exe(Unity3D游戏在Windows平台上的入口程序),并将编译得到的新入口程序替换到Unity3D生成的游戏包中即可。具体为:

    • 找到WindowsPlayer对应的VS项目,以2019.4.19-f1为例,工程位于Editor\2019.4.19f1\Editor\Data\PlaybackEngines\windowsstandalonesupport\Source\WindowsPlayer\WindowsPlayer.sln

    • 打开VS项目,若发现WindowsPlayer工程加载失败,且提示”UnityCommon.props“找不到,可以手动生成该文件置于WindowsPlayer.sln同目录下,文件内容参考如下:

      <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      	<PropertyGroup>
      		<UnityInstallationDir>C:\Program Files\Unity\Hub\Editor\2019.4.19f1\Editor</UnityInstallationDir>
      		<UnityWSAPlayerDir>C:\Program Files\Unity\Hub\Editor\2019.4.19f1\Editor\Data\PlaybackEngines\windowsstandalonesupport</UnityWSAPlayerDir>
      		<UnityProjectDir>D:\Test\test-2019.4.19f1</UnityProjectDir>
      	</PropertyGroup>
      </Project>
    

    其中UnityInstallationDir指Unity3D安装路径,UnityWSAPlayerDir指的是windowsstandalonesupport所在路径,UnityProjectDir指的是待编译工程路径(这一项可以不填)。

    • 成功加载后,右键目标VS工程,选择属性,之后依次点击链接器-清单文件:
      • 生成清单一栏选择 是 (/MANIFEST)
      • 启用用户账户控制(UAC)一栏选择 是 (/MANIFESTUAC:)
      • UAC执行级别一栏选择 requireAdministrator (/level='requireAdministrator')
    • 选择需要的版本(Release/Debug,x86/x64),编译生成新的WindowsPlayer.exe
    • 最后用新生成的入口程序做替换,这里可以参考以下两种替换方式
      • 直接替换编译后的游戏入口,如游戏入口叫Game.exe,则将WindowsPlayer.exe改名为Game.exe,再进行替换即可
      • 在编译前替换至WSA目录下,如打包方式为IL2CPP、Release、Win64,则复制新生成的WindowsPlayer.exe至Editor\2019.4.19f1\Editor\Data\PlaybackEngines\windowsstandalonesupport\Variations\win64_nondevelopment_il2cpp\WindowsPlayer.exe,之后编译打出游戏包即可

    接入NEPSplash(可选)

    对于启动时间较长的程序,为避免用户长时间等待,给用户一个较好的体验,可以选择性地接入splash程序,用于在桌面的右下角显示一个加载动画,如下图

    该模块没有任何反外挂或者保护的功能,请不要与反外挂功能或者加固保护功能放在一起调用,该模块仅仅为用户提供一个程序启动时的友好提示,如无必要可以不接,以免引起分析者的注意进而分析保护系统。

    类似地,加载动画分为静态库接入和直接加载两种接入方式,下面对这两种方式做了简要介绍。

    静态库接入NEPSplash

    静态库方式接入由易盾方提供以下文件:

    NEPSplash.h libNEPSplashWindow.lib libNEPSplashWindow.res

    接入步骤(一般建议在游戏启动器中接入并调用):

    • 修改需要接入动画的工程配置,将libNEPSplashWindow.res作为附加依赖项(VS工程属性-配置属性-链接器-输入-附加依赖项)
    • 在合适的位置包含头文件NEPSplash.h,引入静态库libNEPSplashWindow.lib
    • 在合适的时机调用展示动画的接口NEP_ShowSplash

    接口声明详见第四章SDK接入调用说明。

    直接加载NEPSplash

    若游戏开发环境不适合试用静态库接入动画的方式,可采用这种方式。

    具体步骤为:

    • 向易盾方索要加载动画程序NEPSplash.exe
    • 在合适的时机(如点击了游戏启动器的“开始游戏”按钮后)启动NEPSplash.exe即可,NEPSplash.exe启动后会立即展示加载动画。

    服务端接入OpenAPI(可选)

    当易盾方检测到使用了外挂的玩家后,会将该玩家的账号、外挂类型、外挂名称、外挂证据等信息同步到易盾官网后台,可以登录到后台查询该部分数据,且支持导出文件。

    然而官网查询数据只保留七天,且人工操作登录与查询的步骤较为繁琐,因此游戏方可以选择接入易盾方提供的OpenAPI SDK,接入后只需要调用相应接口,即可查询到指定时间段内存在作弊行为的玩家信息,且可以将调用API查询数据的逻辑与游戏自身的处罚措施相结合。

    OpenAPI的接入方式另见openapi接口文档OpenAPI相关文档

    SDK接入调用说明

    NEPLauncher接口说明(C++)

    (1)【静态库 & 动态库】账号初始化

    接口用途:

    初始化当前游戏进程登录的玩家角色信息,包括角色UID、账号、服务器、人物等级数据等。

    接入须知:

    在合适的时机(一般为玩家输入账号或选择角色登录游戏时)调用接口; 接口中传递的字符串统一使用Unicode编码。其中用来作为玩家唯一标识的 szUid和游戏 szAppId 不能为空(AppId请咨询易盾技术支持或者客服获取)。

    函数原型:
    bool NEP_SetAccountInfo(
    	IN LPCWSTR szAccount,			// 玩家账号
    	IN LPCWSTR szUid,				// 玩家uid
    	IN LPCWSTR szServerName,		// 所在服务器名称
    	IN int nServerId,				// 所在服务器id
    	IN LPCWSTR szRoleName,			// 角色名
    	IN int nLevel,					// 角色等级
    	IN LPCWSTR szAppId,				// 游戏 appid
    	IN unsigned int msgType         // 仅记录账号(0) 角色登录(1) 登出(2)
    );
    
    参数说明:
    参数 说明
    szAccount 玩家账号
    szUid 必填,不可为空,玩家角色唯一标识ID
    szServerName 游戏角色所在服务器名称
    nServerId 游戏角色所在服务器ID
    szRoleName 游戏角色名
    nLevel 角色等级
    szAppId 必填,指定端游反外挂产品ID,可在易盾官网后台查询到,或联系技术支持获取
    msgType 初始化类型,1表示角色登录;2表示角色登出;0表示不记录登录登出行为,仅做记录
    返回值说明:
    返回值 说明
    true 初始化角色信息成功
    false 初始化角色信息失败
    示例代码:
    // 初始化账号接口
    CStringW account;
    GetDlgItem(IDC_EDIT_ACCOUNT)->GetWindowTextW(account);
    std::wstring uid = GenerateUID(account.GetString()).c_str();  // 角色唯一ID
    std::wstring serverName = L"测试服01";  // 服务器名
    int serverId = 30001;  // 服务器ID
    std::wstring roleName = L"测试角色名";  // 角色名
    int roleLevel = 80;  // 角色等级
    std::wstring appId = L"W004901234";  // 易盾后端创建产品对应的APP_ID
    bool initAccountResult = NEP_SetAccountInfo(account.GetString(),
    							uid.c_str(),
    							serverName.c_str(),
    							serverId,
    							roleName.c_str(),
    							roleLevel,
    							appId.c_str(),
    							1);  // 1-登录 2-登出 0-默认值,只记录用户
    
    if (initAccountResult) {
    	OutputDebugStringW(L"[+] 角色初始化接口调用成功\n");
    }
    

    (2)【静态库 & 动态库】拉取嫌疑数据

    接口用途

    用于透传3.0,从反外挂引擎中获取嫌疑数据或其他反外挂相关数据。

    接入须知

    游戏方主动调用,将嫌疑数据拉取到游戏客户端,建议循环调用,调用间隔为5-10分钟。游戏方在获得嫌疑数据或者其他反外挂相关数据后,需要自行实现函数进行数据上报,参考C原型:

    typedef void(__stdcall* SuspiciousUploadPointer)(MessageId messageId, const char* buffer, size_t size);
    

    游戏客户端将嫌疑数据发送到游戏服务器中转后,由游戏服务端对嫌疑数据进行封装上报,数据的封装形式以及上传路径见端游智能反外挂API(服务端)接入文档

    嫌疑数据数据封装的JSON格式示例如下,细节请参考反外挂嫌疑在线检测

    {
       	"appId": "xxx8888888",
        "timestamp": "${currentTime}",
        "nonce": "1111111",
        "token": "${sign}",
        "mrData":  "xxxxxxx",
        "ip":  "1.1.1.1",
        "roleId":  "yyyyyyy",
        "roleName":  "yyyyyyy",
        "roleServer":  "yyyyyyy",
        "extData": "zzzzzzz"
    }
    

    其他反外挂相关数据封装的JSON格式示例如下,细节请参考资源文件数据上传

    {
       	"appId": "xxx8888888",
        "timestamp": "${currentTime}",
        "nonce": "1111111",
        "token": "${sign}",
        "mrData":  "xxxxxxx",
        "transMsgType": 1,
        "ip":  "1.1.1.1",
        "extData": "zzzzzzz"
    }
    

    函数原型

    /// <summary>
    /// 嫌疑数据类型码
    /// </summary>
    enum MessageId {
        SuspiciousData = 100, // 可疑数据
        ResourceData = 101 // 其他反外挂相关数据
    };
    
    /// <summary>
    /// 拉取嫌疑数据
    /// </summary>
    /// <param name="messageId"></param>
    /// /// <param name="dataPtr"></param>
    /// /// <param name="dataLen"></param>
    /// <returns></returns>
    bool NEP_PullDoubtData(MessageId messageId, void*& dataPtr, size_t& dataLen);
    

    参数说明

    参数 说明
    messageId 数据类型码
    dataPtr 数据地址
    dataLen 数据长度

    数据类型码说明

    数据类型 说明
    SuspiciousData 可疑数据
    ResourceData 其他反外挂相关数据

    返回值说明

    返回值 说明
    true 成功
    false 失败

    示例代码

    void* buffer = nullptr;
    size_t len = 0;
    while (1) {
        //"please wait 5-10 minutes...
        auto status = NEP_PullDoubtData(MessageId::SuspiciousData, buffer, len);
        if(status){
            suspiciousUpload(MessageId::SuspiciousData, (char*)buffer, len);
        }
    }
    ....
    

    (3)【静态库 & 动态库】初始化反外挂状态检测

    接口用途:

    异步地检测反外挂引擎运行状态,检测到反外挂引擎运行异常时通知回调。

    接入须知:

    当接入SDK,但尚未加固时,会初始化失败,加固(置入反外挂引擎)后可正常; 当检测到异常调用回调函数时,会传入一个状态码,游戏客户端可以根据该状态码采取一定的措施,例如:警告弹框、踢下线、崩溃退出游戏等。

    函数原型:
    // 状态校验枚举
    enum NEPSTATUS {
    	eNEP_Status_Normal = 0,		// 正常
    	eNEP_Status_NotLoaded = 1,		// 反外挂核心未启动
    	eNEP_Status_FileNotFount = 2,	// 反外挂文件未找到
    	eNEP_Status_FileModified = 4,	// 反外挂文件被篡改
    	eNEP_Status_Suspended = 8,		// 反外挂功能停止
    	eNEP_Status_TiggerEvent = 16,	// 反外挂功能异常
    	eNEP_Status_InternalWardenError = 32, // 内部校验错误
        eNEP_Status_NetworkError = 64,  // 网络失败
    };
    
    // NEP状态校验回调函数
    typedef bool(_stdcall* NEPStatusCallback)(NEPSTATUS statusCode);
    
    // 接口调用返回值枚举
    enum INSTALLRESULT {
    	SUCCESS_INSTALLED = 0,      
    	FAIL_CALLBACK_INVALID = 1,  
    	FAIL_INTERVAL_INVALID = 2,  
    	FAIL_UNEXPECTED = 4        
    };
    
    // 状态检查初始化接口
    INSTALLRESULT NEP_InstallStatusChecker(
    	NEPStatusCallback callback,  // 回调函数
    	ULONG intervalSeconds = 60,  // 校验间隔,单位为秒,范围为(20, 3600)
    	bool isCallbackOnlyAbnormal = true  // true:仅在检测到异常时回调  false: 完成一轮检测即调用
    );
    
    参数说明:
    参数 说明
    callback 状态校验回调函数,用于接收检测状态码并做后续处理
    intervalSeconds 异步校验时间间隔,单位为秒,范围限定在(20, 3600)
    isCallbackOnlyAbnormal true:仅在检测到异常时调用回调函数 false: 每次检测完成后无论是否异常均调用回调函数
    返回值说明:

    函数返回值释义如下表

    返回值 说明
    SUCCESS_INSTALLED 初始化成功
    FAIL_CALLBACK_INVALID 回调函数非法
    FAIL_INTERVAL_INVALID 时间间隔非法
    FAIL_UNEXPECTED 内部错误(当接入SDK,未加固时,函数调用结果均为该值,加固后可正常),需联系易盾方

    回调传递的状态码释义如下表

    状态码 说明
    eNEP_Status_Normal 反外挂引擎工作正常
    eNEP_Status_NotLoaded 反外挂核心未启动
    eNEP_Status_FileNotFount 反外挂文件未找到
    eNEP_Status_FileModified 反外挂文件被篡改
    eNEP_Status_Suspended 反外挂功能停止
    eNEP_Status_TiggerEvent 反外挂功能异常
    eNEP_Status_InternalWardenError 内部校验错误
    eNEP_Status_NetworkError 网络请求失败
    示例代码:
    bool _stdcall AsyncCheck(NEPSTATUS statusCode) {
    	CStringW msg;
    	msg.Format(L"[*] %s: %lld\n", __FUNCTIONW__, static_cast<uint64_t>(statusCode));
    	OutputDebugStringW(msg);
    	return true;
    }
    ......
    INSTALLRESULT intallResult = NEP_InstallStatusChecker(AsyncCheck, 30, true);
    if (intallResult == SUCCESS_INSTALLED) {
    	OutputDebugStringW(L"[+] 安全校验接口调用成功\n");
    } else if (intallResult == FAIL_UNEXPECTED) {
    	OutputDebugStringW(L"[-] 安全校验接口调用异常:目标游戏未启动或游戏未加固\n");
    }
    

    (4)【静态库 & 动态库】同步检测反外挂状态

    接口用途:

    立即校验并获取反外挂引擎运行状态。

    接入须知:

    应当在开启异步检测后再调用该接口,该接口会在当前线程完成所有校验逻辑,同步地返回状态码。

    函数原型:
    NEPSTATUS NEP_GetSecurityStatus();
    
    参数说明:

    该接口无参数。

    返回值说明:

    同上文中的状态码释义表。

    示例代码:
    INSTALLRESULT intallResult = NEP_InstallStatusChecker(AsyncCheck, 30, true);
    ......
    NEPSTATUS nepStatus = NEP_GetSecurityStatus();
    if (nepStatus != eNEP_Status_Normal) {
        OutputDebugStringW(L"[-] 反外挂引擎运行状态异常\n");
    }
    

    (5)【静态库 & 动态库】停止检测反外挂状态

    接口用途:

    停止对反外挂引擎运行状态的异步检测,一般情况下不推荐这么做。

    接入须知:

    直接调用即可,会立即停止对反外挂引擎运行状态的异步检测; 若调用该函数前并未初始化,不会引起程序失败

    函数原型:
    void NEP_UninstallStatusChecker();
    
    参数说明:

    该接口无参数

    返回值说明:

    该接口无返回值。

    示例代码:
    NEP_UninstallStatusChecker();
    OutputDebugStringW(L"[*] 反外挂状态校验已停止\n");
    

    NEPLauncher接口说明(C#)

    (1)【Unity3D】账号初始化

    接口用途:

    初始化当前游戏进程登录的玩家角色信息,包括角色UID、账号、服务器、人物等级数据等。

    接入须知:

    在合适的时机(一般为玩家输入账号或选择角色登录游戏时)调用接口; 其中用来作为玩家唯一标识的 uid 不能为空(AppId请咨询易盾技术支持或者客服获取)。

    函数原型:
    /// <summary>
    /// 设置账号信息
    /// </summary>
    /// <param name="account"></param>
    /// <param name="uid"></param>
    /// <param name="serverName"></param>
    /// <param name="serverId"></param>
    /// <param name="roleName"></param>
    /// <param name="roleLevel"></param>
    /// <param name="appId"></param>
    /// <param name="state"></param>
    /// <returns></returns> 
    public static bool SetAccountProc(
    	string account,     // 账号
    	string uid,         // 玩家角色uid
        string serverName,  // 角色所在服务器名
        int serverId,       // 角色所在服务器ID
        string roleName,    // 角色名
        int roleLevel,      // 角色等级
        string appId,       // 反外挂产品APP_ID
        uint state          // 仅记录账号(0) 角色登录(1) 登出(2)
    );
    
    参数说明:
    参数 说明
    account 玩家账号
    uid 必填,不可为空,玩家角色唯一标识ID
    serverName 游戏角色所在服务器名称
    serverId 游戏角色所在服务器ID
    roleName 游戏角色名
    roleLevel 角色等级
    appId 必填,指定端游反外挂产品ID,可在易盾官网后台查询到,或联系技术支持获取
    state 初始化类型,1表示角色登录;2表示角色登出;0表示不记录登录登出行为,仅做记录
    返回值说明:
    返回值 说明
    true 初始化角色信息成功
    false 初始化角色信息失败
    示例代码:
    using NLPC;
    ......
    string account = "uc_account@163.com";
    string uid = account;
    string serverName = "uc_server_name";
    int serverId = 0x90001;
    string roleName = "uc_role_name";
    int roleLevel = 0x80;
    string appId = "W004901234";
    uint state   = 0x01;
    bool result = LaunchStub.SetAccountProc(
        account,
        uid,
        serverName,
        serverId,
        roleName,
        roleLevel,
        appId,
        state);
    UnityEngine.Debug.Log("角色初始化接口调用结果: " + result);
    

    (2)【Unity3D】数据透传

    接口用途

    用于透传3.0,从反外挂引擎中获取嫌疑数据或者其他反外挂相关数据。

    接入须知

    游戏方主动调用,将嫌疑数据拉取到游戏客户端,建议循环调用,调用间隔为5-10分钟。游戏方在获得嫌疑数据或者其他反外挂相关数据后,需要自行实现函数进行数据上报,参考C原型:

    typedef void(__stdcall* SuspiciousUploadPointer)(MessageId messageId, const char* buffer, size_t size);
    

    游戏客户端将嫌疑数据发送到游戏服务器中转后,由游戏服务端对嫌疑数据进行封装上报,数据的封装形式以及上传路径见端游智能反外挂API(服务端)接入文档

    嫌疑数据数据封装的JSON格式示例如下,详细请参考反外挂嫌疑在线检测

    {
       	"appId": "xxx8888888",
        "timestamp": "${currentTime}",
        "nonce": "1111111",
        "token": "${sign}",
        "mrData":  "xxxxxxx",
        "ip":  "1.1.1.1",
        "roleId":  "yyyyyyy",
        "roleName":  "yyyyyyy",
        "roleServer":  "yyyyyyy",
        "extData": "zzzzzzz"
    }
    

    其他反外挂相关数据封装的JSON格式示例如下,详细请参考资源文件数据上传

    {
       	"appId": "xxx8888888",
        "timestamp": "${currentTime}",
        "nonce": "1111111",
        "token": "${sign}",
        "mrData":  "xxxxxxx",
        "transMsgType": 1,
        "ip":  "1.1.1.1",
        "extData": "zzzzzzz"
    }
    

    函数原型

    /// <summary>
    /// 嫌疑数据类型码
    /// </summary>
    enum MessageId {
        SuspiciousData = 100, // 可疑数据
        ResourceData = 101  // 其他反外挂相关数据
    }
    /// <summary>
    /// 拉取可疑数据
    /// </summary>
    /// <param name="messageId"></param>
    /// <param name="dataBuffer"></param>
    /// <param name="dataLen"></param>
    /// <returns></returns>
    public static bool PullDoubtData(
    	MessageId messageId, 
        ref IntPtr dataBuffer, 
        ref uint dataLen
    );
    

    参数说明

    参数 说明
    messageId 数据类型码
    dataPtr 数据地址
    dataLen 数据长度

    数据类型码说明

    数据类型 说明
    SuspiciousData 可疑数据
    ResourceData 其他反外挂相关数据

    返回值说明

    返回值 说明
    true 成功
    false 失败

    示例代码

    uint dataLen = 0;
    bool status = false;
    IntPtr doubtData = IntPtr.Zero;
    while (1) {
        //"please wait 5-10 minutes...
        var status = PullDoubtData(MessageId.SuspiciousData, ref doubtData, ref dataLen);
        if(status){
            suspiciouscallback(MessageId.SuspiciousData, doubtData, dataLen);
        }
    }
    ......
    

    (3)【Unity3D】初始化反外挂状态检测

    接口用途:

    异步地检测反外挂引擎运行状态,检测到反外挂引擎运行异常时通知回调。

    接入须知:

    当接入SDK,但尚未加固时,会初始化失败,加固(置入反外挂引擎)后可正常; 当检测到异常调用回调函数时,会传入一个状态码,游戏客户端可以根据该状态码采取一定的措施,例如:警告弹框、踢下线、崩溃退出游戏等。

    函数原型:
    /// <summary>
    /// 反外挂状态(NEPStatusCallback)
    /// </summary>
    enum NEPSTATUS {
        eNEP_Status_Normal = 0,               // everything OK
        eNEP_Status_NotLoaded = 1,            // NEP2.dll 未加载
        eNEP_Status_FileNotFount = 2,         // NEP2.dll 文件未找到
        eNEP_Status_FileModified = 4,         // NEP2.dll 被修改
        eNEP_Status_Suspended = 8,            // 反外挂线程被暂停
        eNEP_Status_TiggerEvent = 16,         // 反外挂功能异常
        eNEP_Status_InternalWardenError = 32, // 内部校验错误
        eNEP_Status_NetworkError = 64,        // 网络请求失败
    }
    /// <summary>
    /// NEP_InstallStatusChecker 安装状态
    /// </summary>
    enum INSTALLRESULT {
        SUCCESS_INSTALLED = 0,
        FAIL_CALLBACK_INVALID = 1,
        FAIL_INTERVAL_INVALID = 2,
        FAIL_UNEXPECTED = 4
    }
    /// NEP状态校验回调函数,由游戏方自行实现   
    public delegate bool NEPStatusCallback(NEPSTATUS nepCode);
    
    /// <summary>
    /// 安装异常(异步)状态检查
    /// </summary>
    /// <param name="callback"></param>
    /// <param name="intervalSeconds"></param>
    /// <param name="isCallbackOnlyAbnormal"></param>
    /// <returns></returns>
    INSTALLRESULT InstallStatusChecker(
        NEPStatusCallback callback, // 回调函数
        int intervalSeconds = 60, // 校验间隔,单位为秒,范围为(20, 3600)
        bool isCallbackOnlyAbnormal = true // true:仅在检测到异常时回调  false: 完成一轮检测即调用
    ); 
    
    参数说明:
    参数 说明
    callback 状态校验回调函数,用于接收检测状态码并做后续处理
    intervalSeconds 异步校验时间间隔,单位为秒,范围限定在(20, 3600)
    isCallbackOnlyAbnormal true:仅在检测到异常时调用回调函数 false: 每次检测完成后无论是否异常均调用回调函数
    返回值说明:

    函数返回值释义如下表

    返回值 说明
    SUCCESS_INSTALLED 初始化成功
    FAIL_CALLBACK_INVALID 回调函数非法
    FAIL_INTERVAL_INVALID 时间间隔非法
    FAIL_UNEXPECTED 内部错误(当接入SDK,未加固时,函数调用结果均为该值,加固后可正常),需联系易盾方

    回调传递的状态码释义如下表

    状态码 说明
    eNEP_Status_Normal 反外挂引擎工作正常
    eNEP_Status_NotLoaded 反外挂核心未启动
    eNEP_Status_FileNotFount 反外挂文件未找到
    eNEP_Status_FileModified 反外挂文件被篡改
    eNEP_Status_Suspended 反外挂功能停止
    eNEP_Status_TiggerEvent 反外挂功能异常
    eNEP_Status_InternalWardenError 内部校验错误
    eNEP_Status_NetworkError 网络请求失败
    示例代码:
    /// <summary>
    /// 状态检查回调,由游戏方实现
    /// </summary>
    /// <param name="statusCode"></param>
    /// <returns></returns>
     public static bool asyncCheck(NEPSTATUS statusCode)
    {
         Console.WriteLine(statusCode.ToString());
         return true;
    }
    ....
    INSTALLRESULT intallResult = LaunchStub.InstallStatusChecker(asyncCheck, 25, true);
    if (intallResult == SUCCESS_INSTALLED) {
    	OutputDebugString("[+] 安全校验接口调用成功\n");
    } else if (intallResult == FAIL_UNEXPECTED) {
    	OutputDebugString("[-] 安全校验接口调用异常:目标游戏未启动或游戏未加固\n");
    }
    

    (4)【Unity3D】同步检测反外挂状态

    接口用途:

    立即校验并获取反外挂引擎运行状态。

    接入须知:

    应当在开启异步检测后再调用该接口,该接口会在当前线程完成所有校验逻辑,同步地返回状态码。

    函数原型:
    /// <summary>
    /// 立即获取反外挂状态
    /// </summary>
    /// <returns>0-status ok, others means status abnormal</returns>
    NEPSTATUS GetSecurityStatus();
    
    参数说明:

    该接口无参数。

    返回值说明:

    同上文中的状态码释义表。

    示例代码:
    INSTALLRESULT intallResult = InstallStatusChecker(AsyncCheck, 30, true);
    ......
    NEPSTATUS nepStatus = GetSecurityStatus();
    if (nepStatus != eNEP_Status_Normal) {
        OutputDebugString("[-] 反外挂引擎运行状态异常\n");
    }
    

    (5)【Unity3D】停止检测反外挂状态

    接口用途:

    停止对反外挂引擎运行状态的异步检测,一般情况下不推荐这么做。

    接入须知:

    直接调用即可,会立即停止对反外挂引擎运行状态的异步检测; 若调用该函数前并未初始化,不会引起程序失败

    函数原型:
    /// <summary>
    /// 停止状态检查
    /// </summary>
    void UninstallStatusChecker();
    
    参数说明:

    该接口无参数

    返回值说明:

    该接口无返回值。

    示例代码:
    UninstallStatusChecker();
    OutputDebugString("[*] 反外挂状态校验已停止\n");
    

    NEPSplash接口说明

    (1)展示加载动画

    接口用途:

    展示NEProtect启动动画,提高等待游戏进程启动的用户体验。

    接入须知:

    仅在必要情况下调用该接口;

    加载动画可以选择异步或同步,默认为异步加载,同步加载会阻塞当前线程。

    函数原型:
    /// <summary>
    /// 展示NEP启动动画
    /// </summary>
    /// <param name="isAsync">是否异步展示动画,默认为异步</param>
    void NEP_ShowSplash(bool isAsync);
    
    参数说明:
    参数 说明
    isAsync true-异步加载动画;false-同步加载动画
    返回值说明:

    该接口无返回值

    示例代码:
    NEP_ShowSplash(false);
    

    加固工具使用说明

    解开加固工具压缩包,可看到NHPProtect.jarconfig.ini两个文件;

    其中配置文件config.ini中请填写易盾后台关联的appKey,请勿泄漏或自行更改;

    加固工具为NHPProtect.jar, 依赖Java运行时环境(推荐Java版本为1.8)适用于 Windows、Linux以及Mac系统;

    以下均以Windows环境下描述,其他系统环境使用方法类似。

    命令行参数

    java -jar NHPProtect.jar -WinEnc [options] -input %path/to/input/file%
    

    参数说明

    参数 说明
    -WinEnc 必填项,用于标识加固对象为Windows平台上的应用或游戏
    [options] 可选项,用于标识加固开启的功能
    -input [file_path] 必填项,参数后跟待加固的zip包或PE文件的路径

    可选参数说明:

    参数 说明
    -yunconfig 推荐使用,用于开启易盾后台配置的反外挂功能,目前暂不支持本地配置反外挂功能,反外挂加固时该参数必选
    -target [pe_filename] 指定保护的PE文件,仅当input参数不为PE文件时需要指定,若input参数为单独PE文件,则无需再指定该参数
    -enginetype [type] type值可选DEFAULT, u3d_mono, u3d_il2cpp, cocos2d,不填该参数时默认为DEFAULT,表示常规应用,不接入游戏引擎保护功能
    -u3dastenc 加密Unity3D的Asset Bundle,仅在enginetype为u3d_mono或u3d_il2cpp时生效
    -u3dstaticasset 加密Unity3D的静态资源,仅在enginetype为u3d_mono或u3d_il2cpp时生效
    -dll [mono_dll_list....] 指定需要加密的mono dll文件名,可跟多个文件,仅支持用户自定义代码的dll,如Assembly-CSharp.dll和Assembly-CSharp-firstpass.dll和一些插件dll,仅在enginetype为u3d_mono时生效
    -SingleDllEnc 该参数单独使用,指定Unity3D MONO DLL单独加密
    -SingleAstEnc 该参数单独使用,指定Unity3D Asset Bundle单独加密
    -SingleStaticVM 该参数单独使用,指定PE文件单独加壳

    出于加固稳定性的考虑,目前反外挂与反破解的功能不支持在jar加固工具中指定开启或关闭,我们会为您在后台配置最为合适的功能

    请在执行反外挂加固时带上-yunconfig参数,否则将会缺失部分检测功能,甚至导致游戏引擎相关的保护失效。

    加固示例

    (1)游戏主程序接入反外挂

    java -jar NHPProtect.jar -WinEnc -yunconfig -input %path/to/game.exe%
    

    (2)Unity3D Mono整包加固

    参数中指定开启AssetBundle与静态资源加密,开启Mono代码保护

    java -jar NHPProtect.jar -WinEnc -target game.exe  -enginetype u3d_mono  -u3dastenc -u3dstaticasset -dll Assembly-CSharp.dll Assembly-CSharp-firstpass.dll -yunconfig -input %path/to/mono/game/zip%
    

    -input后接一个zip包的目录,zip包中必须包含3个文件(也可直接上传游戏整包):

    mono.dll 或 mono-2.0-bdwgc.dll(视游戏Unity3D版本而定) game.exe UnityPlayer.dll(低版本Unity无该文件时可不传)

    zip包是按照游戏正常的目录格式打包的,加固工具只会加固在game_Data目录下的静态资源与AssetBundle资源。

    (3)Unity3D IL2CPP整包加固

    参数中指定开启静态资源与ab资源保护,开启global-metadata.dat加密。

    java -jar NHPProtect.jar -WinEnc -yunconfig -enginetype u3d_il2cpp -u3dstaticasset -u3dastenc -target game.exe -input %path/to/il2cpp/game/zip%
    

    -input后接一个zip包的目录,zip包中必须包含4个文件(也可直接上传游戏整包):

    game_Data\il2cpp_data\Metadata\global-metadata.dat GameAssembly.dll game.exe UnityPlayer.dll(低版本Unity无该文件时可不传)

    zip包是按照游戏正常的目录格式打包的,加固工具只会加固在game_Data目录下的静态资源与AssetBundle资源。

    (4)单独PE加壳

    java -jar NHPProtect.jar -WinEnc -SingleStaticVM -input %path/to/pe/file%
    

    (5)单独Unity3D AssetBundle加密

    java -jar NHPProtect.jar -WinEnc -SingleAstEnc -input %path/to/asset/file%
    

    注意,该功能仅当资源存在更新,游戏整包未更新时使用; 解密逻辑依赖整包加固中的-u3dastenc参数,请先完整加固一次后再使用-SingleAstEnc参数单独加密。

    (6)单独Unity3D Mono DLL加密

    java -jar NHPProtect.jar -WinEnc -SingleDllEnc -input %path/to/mono/dll%
    

    注意,该功能仅当资源存在更新,游戏整包未更新时使用; 解密逻辑依赖整包加固中的-enginetype u3d_mono参数,请先完整加固一次后再使用-SingleDllEnc参数单独加密。

    兼容DRM方案

    端游反外挂的加固方案针对游戏需要使用其他DRM(数字版权管理)解决方案打包的情况做了兼容。

    在使用加固前,请先使用其他DRM方案进行打包,再使用易盾方提供的加固工具进行加固。

    如若要兼容Steam DRM方案,请先使用其DRM打包工具的兼容模式打包,打包完成后再使用易盾的加固工具。

    Steam DRM兼容模式的打包命令如下,详细请见Steam官方文档对这部分的说明:

    drm_wrap [appid] %path/to/input.exe% %path/to/output.exe% drmtoolp 6
    

    若有遇到其他DRM方案无法兼容的情况,请及时告知易盾方,相关技术人员会第一时间排查并给出解决方案。

    兼容性说明

    签名(重要)

    加固接入反外挂后,返回的文件中包含两个未签名的PE文件:游戏加固目标Game.exe与反外挂引擎核心模块NEP2.dll。

    由于加固过程中使用了PE加壳等技术,部分设备上会存在被部分杀毒软件误报的情况。因此这里必须对Game.exe与NEP2.dll进行签名。

    客户端兼容性

    目前支持的客户端平台有:

    • Windows Vista
    • Windows 7
    • Windows 8
    • Windows 8.1
    • Windows 10

    但考虑到游戏性能、不同的图形引擎支持等情况,NEP会根据产品方的需求对系统支持做相应调整。

    服务端兼容性

    以SaaS方式提供服务,需求方无需提供服务器资源。目前数据查询和统计均会放在易盾官网的管理后台( https://dun.163.com/ )。

    测试验证

    在完全接入易盾反外挂之后,上线之前,可以做下测试验证,主要的测试维度有:反外挂功能是否启用、外挂检测数据是否上报、兼容性、回归测试。

    功能启用情况测试

    验证反外挂功能已接入:

    1. 启动接入后的游戏
    2. 管理员模式打开ProcessExplorer或其他进程检测工具
    3. 观察游戏进程的模块列表,若包含NEP2.dll,则说明成功接入

    数据上报测试

    反外挂引擎检测的异常数据分为两种,一种是确认的风险行为或外挂数据,这部分数据会同步到易盾官网后台,可以直接查询到;

    另一种是疑似外挂的可疑数据,这部分会先上传至易盾私有后台,经过后台反外挂规则和易盾运营排查后,筛选出新的确认外挂数据再同步到易盾官网后台。

    如何验证官网后台数据上报正常:

    • 启动加固后的游戏(需要登录,否则无法同步到账号数据)

    • 启动Cheat Engine (后简称CE,一般常用来修改游戏内存、调试游戏进程,可篡改本地客户端的数据,达到作弊的效果)

    • 使用CE打开游戏进程(在菜单中点击File - Open Process,之后选择对应游戏)

    • 稍等片刻(约5分钟),前往易盾官网后台查询数据

    这里列举一些可能引起数据上报无法打通的问题,在自测无法查询到数据时,可以逐一排查比对:

    • 接入SDK所用APP_ID与加固时的APP_KEY不对应(官网后台查看)
    • 接入SDK时用户唯一标识UID为空
    • 游戏未登录,导致检测数据无法关联
    • 游戏启动后马上关闭,即游戏进程在检测数据上报之前已退出

    外挂样本测试

    游戏方若有平时积累的外挂样本,可以在此环节进行测试,开启游戏开启外挂,验证易盾反外挂的检测效果,检测效果可以在易盾官网后台查看。

    登录易盾官网后台,在左侧菜单选择“智能反外挂”,在展开项中选择“数据查询”,在“外挂检测”、“风险检测”、“应用环境检测”中不做勾选,点击“查询”按钮,可看到给定时间范围内所有的检测数据。

    请知悉,由于PC端外挂种类较多,外挂确认的方法较为复杂,为了避免误报,易盾官网展示的“外挂检测”数据都是完全确认的,也即会有一部分未确认的外挂数据未展示在易盾官网后台。

    因此若官网后台查询不到检测数据,请联系易盾方检查私有后台数据,若私有后台有数据,则易盾方录入特征后会将这部分数据同步至官网后台,无需升级方案;若私有后台未检测到数据,请将外挂样本及其测试方法一并反馈至易盾方,易盾方会进行相应的外挂分析,若有必要,会迭代反外挂引擎。

    兼容性测试

    易盾端游反外挂引擎已在第六章提及的系统中做了测试,确保上线的功能稳定有效。

    游戏方在接入后,进一步兼容性测试可以按照游戏本身锁需兼容的设备及系统进行验证测试。

    如果有因为引入易盾反外挂模块导致的问题,请将问题现象及复现步骤反馈给易盾,易盾方会第一时间排查并给出解决方案。

    其他回归性测试

    按照游戏的常规回归测试进行,如果发现有功能异常、卡顿、黑屏、CPU或内存占用过高等现象,请先进行原版自测,在确认是引入易盾反外挂模块导致的问题后,请将问题现象及复现步骤反馈给易盾,易盾方会第一时间排查并给出解决方案。

    常见问题

    编译报错:“不安全代码只会在使用/unsafe编译的情况下出现”

    解决方案:

    1、vs菜单“项目”中找到“(解决方案名称)属性”项,单击进入项目属性设置界面;

    2、在项目属性界面中找到“生成”选项卡

    3、在“生成”选项中找到“允许不安全代码”,勾选上

    image title

    4、U3D游戏请按照Unity引擎的提示开启“UnsafeCode”

    Online Chat Tel:95163223 Free trial