## **一、隐私说明**
请参照[网易易盾隐私政策](https://dun.163.com/clause/privacy)，请将易盾隐私政策链接放到应用“用户协议”中。




## **二、接入说明**

### **1、前言**
端游智能反外挂的接入，从流程上分为三大部分，依次为：

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

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

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

![交互流程图示](https://nos.netease.com/cloud-website-bucket/7e4db3ecf25432834a291e6911b62413.png)





## **三、SDK接入步骤**

需要接入的SDK有：
- NEPLauncher（必接，游戏客户端接入，用于初始化角色信息）
- NEPSplash（可选，游戏客户端接入，用于展示易盾加载动画）
- OpenAPI（可选，游戏服务端接入，用于自动化查询检测数据）



### **1、接入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。

接入步骤依次为：
- 根据游戏的位数和编译选项选择合适的lib文件，配置到VS工程属性-链接器-常规-附加库目录
- 将头文件配置到VS工程属性-C/C++-常规-附加包含目录
- 在合适的位置包含头文件与静态lib
- 调用角色信息初始化接口`NEP_SetAccountInfo`
- （可选）调用反外挂状态检查初始化接口`NEP_InstallStatusChecker`，用于异步地检查反外挂引擎的工作状态是否正常
- （可选）调用反外挂状态同步检查接口`NEP_GetSecurityStatus`，用于同步地检查反外挂引擎工作状态，立即返回检查结果
- （可选）调用停止异步检查接口`NEP_UninstallStatusChecker`，用于停止异步检查反外挂引擎工作状态

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




#### **Unity3D接入NEPLauncher**

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

> NEPLauncher-[version].unitypackage

接入步骤依次为：

- 在Unity3D工程中导入该unitypackage
- 导入后，SDK代码位于NLPC目录下
- 在游戏登录逻辑相关代码处 `using NLPC;`
- 调用`LaunchStub.SetAccountProc`接口初始化角色信息。

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



### **2、接入NEPSplash（可选）**

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

![闪屏页图示](https://nos.netease.com/cloud-website-bucket/56097a07f9516b14601636daec110310.png)

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

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



#### **静态库接入NEPSplash**

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

> NEPSplash.h
> libNEPSplashWindow.lib
> libNEPSplashWindow.res

接入步骤（一般建议在游戏启动器中接入并调用）：

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

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



#### **直接加载NEPSplash**

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

具体步骤为：

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


### **3、服务端接入OpenAPI（可选）**

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

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

OpenAPI的接入方式另见OpenAPI相关文档，文档请向易盾技术支持同学索要。


## **四、SDK接入调用说明**

### **1、NEPLauncher接口说明**

#### **（1）【静态库】账号初始化**

##### **接口用途：**

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

##### **接入须知：**

在合适的时机（一般为玩家输入账号或选择角色登录游戏时）调用接口；
接口中传递的字符串统一使用Unicode编码。其中用来作为玩家唯一标识的 **szUid**和游戏 **szAppId** 不能为空（AppId请咨询易盾技术支持或者客服获取）， 游戏进程**nGameProcessId** 必须设置为真实游戏进程 ID。

##### **函数原型：**

```c++
bool NEP_SetAccountInfo(
IN LPCWSTR szAccount,			// 玩家账号
IN LPCWSTR szUid,				// 玩家uid
IN LPCWSTR szServerName,		// 所在服务器名称
IN int nServerId,				// 所在服务器id
IN LPCWSTR szRoleName,			// 角色名
IN int nLevel,					// 角色等级
IN unsigned int nGameProcessId, // 游戏 pid(0为当前进程)
IN LPCWSTR szAppId,				// 游戏 appid
IN unsigned int msgType         // 仅记录账号(0) 角色登录(1) 登出(2)
);
```

##### **参数说明：**

参数 | 说明
------------- | -------------
szAccount | 玩家账号
szUid | 必填，不可为空，玩家角色唯一标识ID
szServerName | 游戏角色所在服务器名称
nServerId | 游戏角色所在服务器ID
szRoleName | 游戏角色名
nLevel | 角色等级
nGameProcessId | 必填，游戏进程 ID（传0视为当前进程）
szAppId | 必填，指定端游反外挂产品ID，可在易盾官网后台查询到，或联系技术支持获取
msgType | 初始化类型，1表示角色登录；2表示角色登出；0表示不记录登录登出行为，仅做记录

##### **返回值说明：**

返回值 | 说明
------------- | -------------
true  | 初始化角色信息成功
false |  初始化角色信息失败


##### **示例代码：**

```c++
	// 初始化账号接口
	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;  // 角色等级
	unsigned int gamePID = 0;  // 接入SDK的进程与游戏进程为同一个可填0 否则填游戏PID
	std::wstring appId = L"W004901234";  // 易盾后端创建产品对应的APP_ID
	bool initAccountResult = NEP_SetAccountInfo(account.GetString(),
												uid.c_str(),
												serverName.c_str(),
												serverId,
												roleName.c_str(),
												roleLevel,
												gamePID,
												appId.c_str(),
												1);  // 1-登录 2-登出 0-默认值，只记录用户

	if (initAccountResult) {
		OutputDebugStringW(L"[+] 角色初始化接口调用成功\n");
	}
```

#### **（2）【静态库】初始化反外挂状态检测**

##### **接口用途：**

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

##### **接入须知：**

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

##### **函数原型：**

```c++
// 状态校验枚举
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, // 内部校验错误
};

// NEP状态校验回调函数
using NEPStatusCallback = bool(_stdcall*)(NEPSTATUS statusCode);

// 接口调用返回值枚举
enum INSTALLRESULT {
	SUCCESS_INSTALLED = 0,      
	FAIL_CALLBACK_INVALID = 1,  
	FAIL_INTERVAL_INVALID = 2,  
	FAIL_UNEXPECTED = 4        
};

// 状态检查初始化接口
uint64_t NEP_InstallStatusChecker(
	NEPStatusCallback callback,  // 回调函数
	DWORD gameProcessId = 0,  // 游戏主进程ID，0视为与Launcher同进程
	ULONG intervalSeconds = 60,  // 校验间隔，单位为秒，范围为(20, 3600)
	bool isCallbackOnlyAbnormal = true  // true:仅在检测到异常时回调  false: 完成一轮检测即调用
);
```

##### **参数说明：**

参数 | 说明
------------- | -------------
callback | 状态校验回调函数，用于接收检测状态码并做后续处理
gameProcessId | 游戏主进程ID，默认为0，0视为当前进程
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 | 内部校验错误


##### **示例代码：**

```c++
bool _stdcall AsyncCheck(NEPSTATUS statusCode) {
	CStringW msg;
	msg.Format(L"[*] %s: %lld\n", __FUNCTIONW__, static_cast<uint64_t>(statusCode));
	OutputDebugStringW(msg);
	return true;
}
....
    unsigned int gamePID = 0;  // 接入SDK的进程与游戏进程为同一个可填0 否则填游戏PID
	uint64_t intallResult = NEP_InstallStatusChecker(AsyncCheck, gamePID, 30, true);
	if (intallResult == SUCCESS_INSTALLED) {
		OutputDebugStringW(L"[+] 安全校验接口调用成功\n");
	} else if (intallResult == FAIL_UNEXPECTED) {
		OutputDebugStringW(L"[-] 安全校验接口调用异常：目标游戏未启动或游戏未加固\n");
	}
```

#### **（3）【静态库】同步检测反外挂状态**

##### **接口用途：**

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

##### **接入须知：**

与异步校验不同，该接口会在当前线程完成所有校验逻辑，同步地返回状态码。

##### **函数原型：**

```c++
NEPSTATUS NEP_GetSecurityStatus();
```

##### **参数说明：**

该接口无参数。

##### **返回值说明：**

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

##### **示例代码：**

```c++
NEPSTATUS nepStatus = NEP_GetSecurityStatus();
if (nepStatus != eNEP_Status_Normal) {
    OutputDebugStringW(L"[-] 反外挂引擎运行状态异常\n");
}
```


#### **（4）【静态库】停止检测反外挂状态**

##### **接口用途：**

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

##### **接入须知：**

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

##### **函数原型：**

```c++
void NEP_UninstallStatusChecker();
```

##### **参数说明：**

该接口无参数

##### **返回值说明：**

该接口无返回值。

##### **示例代码：**

```c++
NEP_UninstallStatusChecker();
OutputDebugStringW(L"[*] 反外挂状态校验已停止\n");
```

#### **（5）【动态库】账号初始化**

##### **接口用途：**

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

##### **接入须知：**

在合适的时机（一般为玩家输入账号或选择角色登录游戏时）调用接口；
接口中传递的字符串统一使用Unicode编码。其中用来作为玩家唯一标识的 **szUid**和游戏 **szAppId** 不能为空（AppId请咨询易盾技术支持或者客服获取）， 游戏进程**nGameProcessId** 必须设置为真实游戏进程 ID。

##### **函数原型：**

```c++
enum NEP_MSG_TYPE {
	NEP_MSG_MIN = 0,
	NEP_MSG_LOGIN = 1, //登录
	NEP_MSG_LOGOUT = 2, //登出
	NEP_MSG_MAX
};

bool SetAccountInfo(
	IN LPCWSTR szAccount,			// 玩家账号
	IN LPCWSTR szUid,				// 玩家uid
	IN LPCWSTR szServerName,		// 所在服务器名称
	IN int nServerId,				// 所在服务器id
	IN LPCWSTR szRoleName,			// 角色名
	IN int nLevel,					// 角色等级
	IN unsigned int nGameProcessId, // 游戏 pid
	IN LPCWSTR szAppId,				// 游戏 appid
	IN NEP_MSG_TYPE eMsgType		// 登录、登出 传0代表仅记录账号
    );
```

##### **参数说明：**

参数 | 说明
------------- | -------------
szAccount | 玩家账号
szUid | 必填，不可为空，玩家角色唯一标识ID
szServerName | 游戏角色所在服务器名称
nServerId | 游戏角色所在服务器ID
szRoleName | 游戏角色名
nLevel | 角色等级
nGameProcessId | 必填，游戏进程 ID（传0视为当前进程）
szAppId | 必填，指定端游反外挂产品ID，可在易盾官网后台查询到，或联系技术支持获取
msgType | 初始化类型，1表示角色登录；2表示角色登出；0表示不记录登录登出行为，仅做记录

##### **返回值说明：**

返回值 | 说明
------------- | -------------
true  | 初始化角色信息成功
false |  初始化角色信息失败


##### **示例代码：**

```c++
	// 初始化账号接口
	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;  // 角色等级
	unsigned int gamePID = 0;  // 接入SDK的进程与游戏进程为同一个可填0 否则填游戏PID
	std::wstring appId = L"W004901234";  // 易盾后端创建产品对应的APP_ID
	bool initAccountResult = SetAccountInfo(account.GetString(),
											uid.c_str(),
											serverName.c_str(),
											serverId,
											roleName.c_str(),
											roleLevel,
											gamePID,
											appId.c_str(),
											NEP_MSG_LOGIN);  // 1-登录 2-登出 0-默认值，只记录用户

	if (initAccountResult) {
		OutputDebugStringW(L"[+] 角色初始化接口调用成功\n");
	}
```

#### **（6）【静态库】透传设置接口**
##### **接口用途：**
设置透传服务器
##### **接入须知：**
接口会阻塞当前线程，建议在新线程调用。
##### **函数原型：**
```c++
bool NEP_SetBakIP(IN LPCWSTR szIpAddress,
                  IN unsigned int dwPort,
                  IN unsigned int nGameProcessId,
                  IN LPCWSTR szAppId);
```
##### **参数说明：**
参数 | 说明
------------- | -------------
szIpAddress | ip地址宽字符串
dwPort | 端口号
nGameProcessId | 游戏进程ID
szAppId | APPID宽字符串

##### **返回值说明：**
返回值 | 说明
------------- | -------------
true  | 透传接口设置成功
false | 透传接口设置失败
##### **示例代码：**
```c++
bool bRet = NEP_SetBakIP(L"1.2.3.4", 1234, 0, L"W12345678");
if (!bRet) {
    OutputDebugStringW(L"[-] 反外挂引擎运行状态异常\n");
}
```



#### **（7）【Unity3D】账号初始化C#接口**

##### **接口用途：**

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

##### **接入须知：**

在合适的时机（一般为玩家输入账号或选择角色登录游戏时）调用接口；
其中用来作为玩家唯一标识的 **uid**和游戏 **appID** 不能为空（AppId请咨询易盾技术支持或者客服获取）， 游戏进程**gamePid** 必须设置为真实游戏进程 ID。

##### **函数原型：**

```c#
 public static bool SetAccountProc(
 		string account,     // 账号
 		string uid,         // 玩家角色uid
        string serverName,  // 角色所在服务器名
        int serverId,       // 角色所在服务器ID
        string roleName,    // 角色名
        int roleLevel,      // 角色等级
        uint gamePid,       // 游戏进程ID，0视为当前进程
        string appId,       // 反外挂产品APP_ID
        uint state          // 仅记录账号(0) 角色登录(1) 登出(2)
        );
```

##### **参数说明：**

参数 | 说明
------------- | -------------
account | 玩家账号
uid | 必填，不可为空，玩家角色唯一标识ID
serverName | 游戏角色所在服务器名称
serverId | 游戏角色所在服务器ID
roleName | 游戏角色名
roleLevel | 角色等级
gamePid | 必填，游戏进程 ID（传0视为当前进程）
appId | 必填，指定端游反外挂产品ID，可在易盾官网后台查询到，或联系技术支持获取
state | 初始化类型，1表示角色登录；2表示角色登出；0表示不记录登录登出行为，仅做记录

##### **返回值说明：**

返回值 | 说明
------------- | -------------
true  | 初始化角色信息成功
false |  初始化角色信息失败


##### **示例代码：**

```c#
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;
//uint gamePID = (uint)Process.GetCurrentProcess().Id;
uint gamePID = 1;
string appId = "W004901234";

bool result = LaunchStub.SetAccountProc(
    account,
    uid,
    serverName,
    serverId,
    roleName,
    roleLevel,
    gamePID,
    appId,
    LaunchStub.STATE_LOGIN);

UnityEngine.Debug.Log("角色初始化接口调用结果: " + result);
```


### **2、NEPSplash接口说明**

#### **（1）展示加载动画**

##### **接口用途：**

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

##### **接入须知：**

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

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

##### **函数原型：**

```c++
/// <summary>
/// 展示NEP启动动画
/// </summary>
/// <param name="isAsync">是否异步展示动画，默认为异步</param>
void NEP_ShowSplash(bool isAsync);
```

##### **参数说明：**
参数 | 说明
------------- | -------------
isAsync | true-异步加载动画；false-同步加载动画

##### **返回值说明：**
该接口无返回值

##### **示例代码：**
```c++
NEP_ShowSplash(false);
```





## **五、加固工具使用说明**

解开加固工具压缩包，可看到**NHPProtect.jar**与**config.ini**两个文件；

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

加固工具为**NHPProtect.jar**， 依赖Java运行时环境（推荐Java版本为1.8）适用于 Windows、Linux以及Mac系统；

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


### **1、命令行参数**

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



### **2、参数说明**

| 参数               | 说明                                                |
| ------------------ | --------------------------------------------------- |
| -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参数，否则将会缺失部分检测功能，甚至导致游戏引擎相关的保护失效。



### **3、加固示例**

#### **（1）游戏主程序接入反外挂**

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


#### **（2）Unity3D Mono整包加固**
参数中指定开启AssetBundle与静态资源加密，开启Mono代码保护

```bash
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加密

```bash
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加壳**

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


#### **（5）单独Unity3D AssetBundle加密**

```bash
java -jar NHPProtect.jar -WinEnc -SingleAstEnc -input %path/to/asset/file%
```
注意，该功能仅当资源存在更新，游戏整包未更新时使用；
解密逻辑依赖整包加固中的`-u3dastenc`参数，请先完整加固一次后再使用`-SingleAstEnc`参数单独加密。


#### **（6）单独Unity3D Mono DLL加密**

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

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

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

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

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

Steam DRM兼容模式的打包命令如下，详细请见[Steam官方文档](https://partner.steamgames.com/doc/features/drm#other_drm)对这部分的说明：

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

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






## **六、兼容性说明**
### **1、签名（重要）**
加固接入反外挂后，返回的文件中包含两个未签名的PE文件：游戏加固目标Game.exe与反外挂引擎核心模块NEP2.dll。

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

### **2、客户端兼容性**
目前支持的客户端平台有：

- Windows Vista
- Windows 7
- Windows 8
- Windows 8.1
- Windows 10

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

### **3、服务端兼容性**
以SaaS方式提供服务，需求方无需提供服务器资源。目前数据查询和统计均会放在易盾官网的管理后台（ https://dun.163.com/ ）。





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

### **1、功能启用情况测试**
验证反外挂功能已接入：

1. 启动接入后的游戏
2. 管理员模式打开[ProcessExplorer](https://docs.microsoft.com/en-us/sysinternals/downloads/process-explorer)或其他进程检测工具
3. 观察游戏进程的模块列表，若包含NEP2.dll，则说明成功接入


### **2、数据上报测试**

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

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

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

- 启动加固后的游戏（需要登录，否则无法同步到账号数据）

- 启动[Cheat Engine](https://www.cheatengine.org/) （后简称CE，一般常用来修改游戏内存、调试游戏进程，可篡改本地客户端的数据，达到作弊的效果）
- 使用CE打开游戏进程（在菜单中点击File - Open Process，之后选择对应游戏）
- 稍等片刻（约5分钟），前往[易盾官网后台](https://dun.163.com/)查询数据



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

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


### **3、外挂样本测试**

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

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

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

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


### **4、兼容性测试**

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

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

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


### **5、其他回归性测试**

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