C++接入教程
隐私说明
请参照网易易盾隐私政策,请将易盾隐私政策链接放到应用“用户协议”中。
接入说明
接入“智能风控”SDK,开发者需要完成以下步骤:
- 根据游戏开发平台,将SDK拷贝到指定的工程目录,并修改项目配置;接入步骤
- 接入风控SDK必接接口,根据业务需求接入建议接口;SDK接入调用说明
- 若需要接入驱动,则需要配置UAC;配置UAC
- 使用易盾加固工具对游戏进行加固保护,未加固的游戏风控逻辑不运行;加固工具使用说明&兼容性说明
- 验证风控SDK数据上报链路是否正常与防护效果;测试验证
- 按业务常规发版流程进行测试与发版
接入步骤
SDK 涉及到以下文件:
NEProtect.h
NEProtect.cpp
NEPLauncher.lib
SDK选择
NEPLauncher.lib区分32位或64位,编译选项MT/MD,Unicode/MultiByte,编译工具2003/v141/v142;最低支持的Visual Studio版本为2003。
NEProtect.h 在 `C++/NEPLauncherSDK-[版本号]/lib_version/include`文件夹下
NEProtect.cpp 在 `C++/NEPLauncherSDK-[版本号]/lib_version/include`文件夹下
NEPLauncher.lib 在 `C++/NEPLauncherSDK-[版本号]/lib_version/x86&x64`文件夹下
接入步骤:
- 根据游戏的位数和编译选项选择合适的lib文件,配置到VS工程属性-链接器-常规-附加库目录
- 将头文件配置到VS工程属性-C/C++-常规-附加包含目录
- 在合适的位置包含头文件:
#include "NEProtect.h"
- 将NEProtect.cpp添加到游戏工程中
- 链入静态lib:NEProtect.cpp文件中已使用
#pragma comment(lib, "NEPLauncher.lib")
链接静态库,如有问题,可配置到VS工程属性-链接器-输入-附加依赖项 - 调用SDK初始化接口
NEP_Init
,设置产品编号和透传回调函数 - 调用登录接口
NEP_SetRoleInfo
,设置当前游戏进程登录的玩家角色信息,以便对有恶意、风险行为的用户/角色进行相应的处置 - 调用同步/异步获取凭证接口
NEP_GetToken(Async)
,用于关键场景下获取检测唯一凭证 token,将token透过游戏服务端发送到易盾服务端
SDK接入调用说明
必须接入:
- 全局必须要接入的接口:初始化接口
- 在初始化设置透传回调接口,对抗屏蔽等对抗风险:透传回调函数&交互接口
- 游戏反外挂场景业务必须要接入的接口:设置用户信息接口
- 关键业务埋点时必须使用的接口:同步获取凭证/异步获取凭证
SDK初始化接口
接口用途:
用于初始化智能风控 SDK;接入数据透传功能,解决易盾域名被屏蔽而导致数据无法上报的问题。
接入须知:
使用其他接口之前,必须先调用初始化接口(Init
),建议游戏启动后调用。
函数原型:
bool NEP_Init(LPCWSTR productId, NEPConfig nepConfig, TRANSCALLBACK callback = NULL);
参数说明:
参数 | 说明 | 必要性 |
---|---|---|
productId | 易盾分配的productId,可登录易盾后台获取 | 必填 |
nepConfig | 与 NEP 相关的一些配置信息 | 必填 |
callback | 用于数据透传的回调函数 | 必填 |
NEPConfig 结构体
enum ServerType {
MAINLAND = 1, // 中国大陆地区
OVERSEAS = 2, // 其他地区
TAIWAN = 3 // 中国台湾
};
typedef struct _NEPConfig {
int server_type; //服务端所属地区 1:中国大陆 2:其他海外地区 3:中国台湾
char host_name[128]; //可设置私有化域名
void SetServerType(int server);//设置服务端所属地区
void SetHost(LPCSTR host);//设置私有化域名,若不需要开启私有化,则无需调用该函数
} NEPConfig, *PNEPConfig;
返回值说明:
返回值 | 说明 |
---|---|
true | 初始化 SDK 成功 |
false | 初始化 SDK 失败 |
示例代码:
// 调用初始化接口
NEPConfig config;
config.SetServerType(ServerType::MAINLAND); //设置服务端所属地区
//config.SetHost("private.domain.com"); //设置私有化域名,若不需要开启私有化,则无需调用该函数
bool bIsInit = NEP_Init(L"PRODUCTID12345670", config, transcallback);
if (bIsInit) {
OutputDebug("初始化接口调用成功\n");
}
回调函数
接口用途:
- 策略请求数据:
风控SDK -->> “策略请求数据”msg -->> 游戏客户端 -->> 游戏服务端 -->> 易盾安全服务端 -->> 返回策略数据configData -->> 游戏服务端 -->> 游戏客户端 -->> 风控SDK
接入须知:
函数原型:
typedef bool(__stdcall* TRANSCALLBACK)(LPCSTR msg, uint64_t len, int serviceType);
参数说明:
参数 | 说明 |
---|---|
msg | 风控SDK返回的数据,策略请求数据或外挂嫌疑数据 |
len | 用于数据透传的回调函数 |
serviceType | 服务类型:8 - 初始化配置、策略透传 |
示例代码
bool __stdcall transcallback(const char* msg, uint64_t len, int serviceType) {
if (serviceType == 8) {
// 服务类型8 - 策略请求透传服务
// 请将 msg 发送至贵方服务器,再由贵方服务器发送至易盾服务端,由易盾服务端响应,
// 返回结果,再将结果通过交互接口(NEP_Ioctl)反馈给智能风控sdk,serviceType应保持一致
NEP_Ioctl(configData, configData_size, 8);
return true;
}
return true;
}
设置用户信息接口
接口用途:
设置当前游戏进程登录的玩家角色信息,包括业务ID、角色UID、账号、服务器、人物等级数据等,以便对有恶意、风险行为的用户/角色进行相应的处置。
接入须知:
需在SDK初始化之后调用该接口; 接口中除了传递的json形式字符串,其他字符串统一使用Unicode编码。
函数原型:
bool NEP_SetRoleInfo(
LPCWSTR businessId, // 业务 ID
LPCWSTR account, // 玩家账号
LPCWSTR roleId, // 角色 ID
LPCWSTR roleName, // 角色名称
INT serverId, // 服务器 ID
LPCWSTR serverName, // 服务器名称
INT roleLevel, // 角色等级
INT state = 1, // 仅记录账号(0) 角色登录(1) 登出(2)
LPCSTR gameJson = NULL // 用户需要上传的额外信息,对应一个 json 字符串
);
参数说明:
参数 | 说明 | 必要性 |
---|---|---|
businessId | 当前业务 ID | 必填 |
account | 玩家账号 | 必填 |
roleId | 玩家角色唯一标识 ID,不可为空 | 必填 |
roleName | 游戏角色名 | 必填 |
serverId | 游戏角色所在服务器ID | 必填 |
serverName | 游戏角色所在服务器名称 | 可选 |
roleLevel | 角色等级 | 可选(用于嫌疑分析) |
state | 初始化类型,1-表示角色登录;2-表示角色登出;0-表示不记录登录登出行为,仅做记录;默认为 1 | 可选(用于团伙检测) |
gameJson | 游戏方想要上传的额外信息,对应一个 json 字符串,默认为空 | 可选(用于数据服务) |
返回值说明:
返回值 | 说明 |
---|---|
true | 初始化角色信息成功 |
false | 初始化角色信息失败 |
示例代码:
// 登录接口
std::wstring businessId = L"288aafc49af65987989fb57790513ac8c"; // 业务 ID
std::wstring account = L"yd@163.com" //玩家账号
std::wstring roleId = L"123456"; // 角色唯一ID
std::wstring serverName = L"游戏测试服"; // 服务器名
int serverId = 30001; // 服务器ID
std::wstring roleName = L"易小盾"; // 角色名
int roleLevel = 80; // 角色等级
auto packObj = cJSON_CreateObject();
cJSON_AddStringToObject(packObj, "gameVersion", "release_6.33");
cJSON_AddStringToObject(packObj, "ganster", "帮派");
char* packStr = cJSON_Print(packObj);
std::string jsonStr(packStr);
bool ret = NEP_SetRoleInfo(
businessId.c_str(),
account.GetString(),
roleId.c_str(),
roleName.c_str(),
serverId,
serverName.c_str(),
roleLevel,
1,
jsonStr.data());
if (ret) {
OutputDebug("登录成功\n");
}
cJSON_Delete(packObj);
free(packStr);
交互接口
接口用途
设置需要传递给 SDK 的数据(比如初始化配置内容、check 结果信息等),如透传数据等
接入须知
接口调用的前置条件是:调用了初始化接口
函数原型
std::string NEP_Ioctl(LPCSTR buffer, uint64_t len, int serviceType);
参数说明
参数 | 说明 |
---|---|
buffer | 要传递给 SDK 的数据 |
len | 数据长度 |
serviceType | 服务类型:8 - 初始化配置、策略透传 |
返回值说明
返回值 | 说明 |
---|---|
"succeed" | 成功 |
"failed" 或 其他错误说明 | 失败 |
示例代码
// 服务类型8 - 策略和初始化参数透传服务
// 请将 msg 发送至贵方服务器,再由贵方服务器发送至易盾服务端,由易盾服务端响应,
// 返回结果 configData,再将结果通过交互接口(NEP_Ioctl)反馈给智能风控sdk
NEP_Ioctl(configData, configData_size, 8);
同步获取凭证
接口用途
用于关键业务节点风险防控场景中,比如注册、登录、战斗结束等业务场景,或游戏方定时调用该接口,获取检测唯一凭证 token。业务服务端通过此凭证实时获取当前用户/玩家风险检测结果,并根据结果进行处置。
接入须知
SDK 5.3.4 及之后版本支持该接口
接口调用的前置条件是:调用了初始化接口。
内部存在网络请求,只允许在子线程上调用。
token的使用方法请参考“后端接入-智能风控数据服务接口-在线检测接口”。
函数原型
int NEP_GetToken(IN LPCSTR businessId, OUT std::string& token);
参数说明
参数 | 说明 |
---|---|
businessId | 必填,业务id,由易盾后台分配 |
token | 必填,存储返回的token。正常40个字节,若易盾网络不通,则返回离线token,大小9000字节左右 |
返回值说明
返回值 | 说明 |
---|---|
CODE_OK(200) | 获取TOKEN成功 |
CODE_ERROR_PRODUCT_INVALID(-200) | 无效产品id |
CODE_ERROR_NOT_INIT(-201) | SDK未初始化 |
CODE_ERROR_GEN_TOKEN(-204) | TOKEN生成失败,反外挂运行错误或被剥离 |
CODE_ERROR_PARAM(-205) | 无效传参,businessId不合法 |
CODE_ERROR_RESERVED(-210) | 保留值,反外挂主动拒绝生成token,不做任何处理 |
示例代码
//同步接口,必须在子线程中调用
std::thread([](){
std::string token;
int ret = NEP_GetToken("296aafc49ae6567869fb57790123ab7b", token);
if (ret == CODE_ERROR_NOT_INIT) {
printf("SDK未初始化");
} else if (ret == CODE_ERROR_PRODUCT_INVALID) {
printf("无效产品id");
} else if (ret == CODE_ERROR_PARAM) {
printf("无效传参,businessId不合法");
} else if (ret == CODE_ERROR_GEN_TOKEN) {
printf("TOKEN生成失败,反外挂运行错误或被剥离");
} else if (ret == CODE_OK && !token.empty()) {
printf("Token: %s size: %d", token.c_str(), token.size());
}
}).detach();
异步获取凭证
接口用途
同 同步获取凭证
接入须知
SDK 5.3.4 及之后版本支持该接口
接口调用的前置条件是:调用了初始化接口。
在主线程调用,回调也在主线程。
token的使用方法请参考“后端接入-智能风控数据服务接口-在线检测接口”。
函数原型
int NEP_GetTokenAsync(IN LPCSTR businessId, IN TOKENCALLBACK cb);
参数说明
参数 | 说明 |
---|---|
businessId | 必填,业务id,由易盾后台分配 |
cb | 必填,回调函数 |
返回值说明
返回值 | 说明 |
---|---|
CODE_OK(200) | 调用成功 |
CODE_ERROR_NOT_INIT(-201) | SDK未初始化 |
CODE_ERROR_PARAM(-205) | 无效传参,businessId不合法 |
CODE_ERROR_GEN_TOKEN(-204) | 调用失败,反外挂运行错误或被剥离 |
CODE_ERROR_RESERVED(-210) | 保留值,反外挂主动拒绝生成token,不做处理 |
示例代码
int ret = NEP_GetTokenAsync("296aafc49ae6598269fb57790513ab7b", tokencallback);
if (ret == CODE_ERROR_NOT_INIT) {
printf("SDK未初始化");
} else if (ret == CODE_ERROR_PARAM) {
printf("无效传参,businessId不合法");
} else if (ret == CODE_ERROR_GEN_TOKEN) {
printf("调用失败,反外挂运行错误或被剥离");
} else if (ret == CODE_OK) {
printf("调用成功");
}
TOKEN回调函数说明
void __stdcall tokencallback(const int status, const char* token, const int size);
参数说明
参数 | 说明 |
---|---|
status | token获取结果:(200)获取token成功;(-200)无效产品id;(-204)token生成失败 |
token | 获取到的token。正常40个字节,若易盾网络不通,则返回离线token,大小9000字节左右 |
size | token长度 |
示例代码
void __stdcall tokencallback(const int status, const char* token, const int size) {
if (status == -200) {
printf("无效产品id");
} else if (status == -204) {
printf("token生成失败");
} else if(status == 200 && token != NULL && size != 0){
printf("获取token成功: %s", token);
}
}
设置需要保护的第三方进程或白名单进程
接口用途
设置需要反外挂保护的第三方进程或者白名单进程
接入须知
SDK 5.3.6及之后版本支持该接口
接口调用的前置条件是:调用了初始化接口。
调用场景:
1.在游戏主程序无法接入风控sdk的场景下,可通过该接口将游戏主程序添加为受保护程序
2.如果有需要智能风控放行的白名单程序,亦可通过本接口添加
函数原型
void NEP_AddProtectedOrWhitelistProcess(int type, int processId);
参数说明
参数 | 说明 |
---|---|
type | 必填,操作类型:1 - 需要保护的第三方进程,2 - 白名单进程 |
processId | 必填,进程id |
示例代码
int n3rdPartyPid = GetProcessIdByName("MyDemo.exe");
NEP_AddThirdPartyProtectedOrWhitelistProcess(1, n3rdPartyPid);
int nWhitelistPid = GetProcessIdByName("MyWhite.exe");
NEP_AddThirdPartyProtectedOrWhitelistProcess(2, nWhitelistPid);
模拟点击AI识别
接口用途
批量的模拟点击极大的影响到游戏的正常,特别是工作室的参与,不仅影响到游戏的平台,还影响到游戏方的收入。易盾智能风控SDK提供相关的行为检测方案,使用模拟点击行为检测接口时,需要在游戏登录后,并且调用设置用户信息接口,设置role_id等信息后调用。
接入须知
SDK 5.3.5 及之后版本支持该接口
请在作弊情况较严重的玩法和场景下调用NEP_RegisterClickEvent和NEP_UnregisterClickEvent,开启和关闭点击数据的采集,初次接入建议设置一个玩法和场景id,并同步给易盾,如需接入多个玩法和场景需提前与易盾沟通。 开启NEP_RegisterClickEvent后,在该场景结束后必须调用NEP_UnregisterClickEvent关闭检测逻辑
(1)开启采集数据
函数原型
void NEP_RegisterClickEvent(unsigned int gamePlayId, unsigned int sceneId);
参数说明
参数 | 说明 |
---|---|
gamePlayId | 必填,玩法id |
sceneId | 必填,场景id |
(2)关闭采集数据
函数原型
void NEP_UnregisterClickEvent();
配置UAC
注:若需要开启驱动防护功能,则需要进行配置
NEP驱动的安装与卸载需要管理员权限,因此被加固的PE文件在运行时需要具备管理员权限,即用户双击程序打开游戏时,若没有管理员权限,会要求授予,否则将无法打开游戏。这里介绍通过Visual Studio 开启UAC配置的方式。
右键目标VS工程,选择属性,之后依次点击链接器-清单文件:
- 生成清单一栏选择 是 (/MANIFEST)
- 启用用户账户控制(UAC)一栏选择 是 (/MANIFESTUAC:)
- UAC执行级别一栏选择 requireAdministrator (/level='requireAdministrator')
配置完成后重新编译,再加固即可。
加固工具使用说明
解开加固工具压缩包,可看到NHPProtect.jar与config.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, cocos2d,u3d_mono, u3d_il2cpp 不填该参数时默认为DEFAULT,表示常规应用 |
-SingleStaticVM | 该参数单独使用,指定PE文件单独加壳 |
加固示例
- 游戏主程序
java -jar NHPProtect.jar -WinEnc -yunconfig -input %path/to/game.exe%
- 单独PE加壳
java -jar NHPProtect.jar -WinEnc -SingleStaticVM -input %path/to/pe/file%
兼容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进行签名,而NEP2.dll在加固过程中默认获取易盾方签名。
客户端兼容性
目前支持的客户端平台有:
- Windows 7 及以上
但考虑到游戏性能、不同的图形引擎支持等情况,NEP会根据产品方的需求对系统支持做相应调整。
测试验证
在完全接入易盾智能风控之后,上线之前,需做测试验证,主要的测试维度有:反外挂功能是否启用、外挂检测数据是否上报、兼容性、回归测试。
功能启用情况测试
验证反外挂功能已接入:
- 启动接入后的游戏
- 管理员模式打开ProcessExplorer或其他进程检测工具
- 观察游戏进程的模块列表,若包含NEP2.dll,则说明成功接入
数据上报测试
智能风控检测的异常数据分为两种,一种是确认的风险行为或外挂数据,这部分数据会同步到易盾官网后台,可以直接查询到;
另一种是疑似外挂的可疑数据,这部分会先上传至易盾私有后台,经过后台反外挂规则和运营同学排查后,筛选出新的确认外挂数据再同步到易盾官网后台。
如何验证官网后台数据上报正常:
-
启动加固后的游戏(需要登录,否则无法同步到账号数据)
-
启动Cheat Engine (后简称CE,一般常用来修改游戏内存、调试游戏进程,可篡改本地客户端的数据,达到作弊的效果)
-
使用CE打开游戏进程(在菜单中点击File - Open Process,之后选择对应游戏)
-
稍等片刻(约5分钟),前往易盾官网后台查询数据
这里列举一些可能引起数据上报无法打通的问题,在自测无法查询到数据时,可以逐一排查比对:
- 接入SDK所用APP_ID与加固时的APP_KEY不对应(官网后台查看)
- 接入SDK时用户唯一标识UID为空
- 游戏未登录,导致检测数据无法关联
- 游戏启动后马上关闭,即游戏进程在检测数据上报之前已退出
外挂样本测试
游戏方若有平时积累的外挂样本,可以在此环节进行测试,开启游戏开启外挂,验证易盾反外挂的检测效果,检测效果可以在易盾官网后台查看。
登录易盾官网后台,在左侧菜单选择“智能风控”,在展开项中选择“数据中心”,在“数据查询”中可看到给定时间范围内所有的检测数据。
请知悉,由于PC端外挂种类较多,外挂确认的方法较为复杂,为了避免误报,易盾官网展示的“外挂检测”数据都是完全确认的,也即会有一部分未确认的外挂数据未展示在易盾官网后台。
因此若官网后台查询不到检测数据,请联系易盾方检查私有后台数据,若私有后台有数据,则易盾方录入特征后会将这部分数据同步至官网后台,无需升级方案;若私有后台未检测到数据,请将外挂样本及其测试方法一并反馈至易盾方,易盾方会进行相应的外挂分析,若有必要,会迭代风控SDK。
兼容性测试
易盾端游智能风控已在兼容性说明提及的系统中做了测试,确保上线的功能稳定有效。
游戏方在接入后,进一步兼容性测试可以按照游戏本身锁需兼容的设备及系统进行验证测试。
如果有因为引入易盾智能风控导致的问题,请将问题现象及复现步骤反馈给易盾,易盾方会第一时间排查并给出解决方案。
其他回归性测试
按照游戏的常规回归测试进行,如果发现有功能异常、卡顿、黑屏、CPU或内存占用过高等现象,请先进行原版自测,在确认是引入易盾反外挂模块导致的问题后,请将问题现象及复现步骤反馈给易盾,易盾方会第一时间排查并给出解决方案。
常见问题
编译报错:“不安全代码只会在使用/unsafe编译的情况下出现”
解决方案:
1、vs菜单“项目”中找到“(解决方案名称)属性”项,单击进入项目属性设置界面;
2、在项目属性界面中找到“生成”选项卡
3、在“生成”选项中找到“允许不安全代码”,勾选上