KiwiGuard SDK (Android)下载与接入文档

1.最新更新内容

更新版本:

上线KiwiGuard Android监测v1.8(SaaS平台侧)

上线KiwiGuard Android SDK v3.2.11(本页面第2节中可下载)

更新时间:

2021/9/16 12:00:00

更新内容:

① 优化了SaaS平台侧:KiwiGuard Android SDK的接入流程;

② 优化了SaaS平台侧:终端威胁异常的数据展示;

③ 优化了后端接入时:HTTP API的响应数据**(API升级至v2版本),旨在为企业提供可靠且全面的终端威胁数据源(为了更好的体验,请尽量使用v2版本的API,见5.2.1)**,

④ KiwiGuard Android SDK v3.2.11版本支持ameabi架构;

⑤ 修复了一些已知问题。

2 KiwiGuard SDK下载

**版本号:**KiwiGuard Android-v3.2.11(若无特殊要求,请下载集成最新SDK)

**发布时间:**2021/9/16 11:00:00

**版本描述:**① 优化了数据交互,旨在为企业提供可靠且全面的终端威胁数据源;② 支持ameabi架构

**版本号:**KiwiGuard Android-v3.2.10

**发布时间:**2021/7/21 18:00:00

**版本描述:**虚拟机环境监测,新增对51虚拟机和光速虚拟机的检测支持

**版本号:**KiwiGuard Android-v3.2.9

**发布时间:**2021/7/1 19:00:00

**版本描述:**修复虚拟机检测漏报VMOS pro bug ,修复其他已知bug

3 名称解释

序号 名词 描述
1 应用组 相同App(不同版本、不同渠道)的集合,便于更好的管理企业内的应用矩阵,首次使用时需创建应用组
3 appGroupID 应用组ID:POST请求参数,能够发送POST请求访问几维安全服务端接口,获取应用组下所有App的终端威胁信息,需搭配appGroupSecret使用
4 appGroupSecret 密钥:POST请求参数,能够发送POST请求访问几维安全服务端接口,获取应用的终端威胁信息,需搭配appGroupID或appID使用
5 appID AppID:POST请求参数,能够发送POST请求访问几维安全服务端接口,获取当前App名称、版本及渠道下的终端威胁信息,需搭配appGroupSecret使用

4 法规要求

您应向您的终端用户逐一明示您嵌入的第三方SDK收集使用个人信息的目的、方式和范围。

您应当在《隐私政策》中明确告知终端用户,您选择了成都盈海益讯科技有限公司作为合作方,并委托其收集、使用、加工和处理终端用户个人信息。成都盈海益讯科技有限公司建议您在《隐私政策》中的“我们如何共享、转让、公开披露您的个人信息”的表述条款中增加如下内容(关于个人信息共享给第三方说明的部分,强烈建议此部分由您专业的法务团队优化完善,详情可参考《KiwiGuard SDK隐私政策》):

为了识别客户端或终端用户的异常状态,为了对盗版应用、虚假设备、游戏外挂、环境风险、对抗事件等威胁场景进行监测与管控,我们的产品会集成第三方的SDK或类似应用程序,具体如下:

SDK名称 KiwiGuard SDK
所属公司名称 成都盈海益讯科技有限公司
SDK收集数据类型 个人常用设备信息:(1)设备MAC地址;(2)设备IMEI(3)安装软件列表;(4)唯一设备识别码(安卓ID、设备硬件序列号);(5)设备的基本配置信息(设备厂商、型号、CPU型号、系统版本、内核版本、系统语言、SDK版本)。
SDK用途 (1)计算设备唯一标识码(设备指纹)(2)识别终端威胁异常信息;(3)对威胁异常进行管控。

5 KiwiGuard SDK手动接入流程

5.1 KiwiGuard SDK前端接入

集成KiwiGuard SDK之前:请先在几维安全《移动应用安全管理平台》创建应用组、创建App,获取appID。

5.1.1 集成KiwiGuard SDK

(1)下载KiwiGuard SDK

下载KiwiGuard SDK,下载之后得到一个KiwiGuard-SDK-v3.x.y.zip 的一个文件,解压后文件中包含.aar 和 .lic两个文件。

(2)Android Studio 集成

① 把kiwiguard.aar放到相应模块的libs目录下;

② 把kiwiguard.lic放到相应模块的assets目录下;

③ 在该模块的build.gradle中如下配置;

android {
    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }
    repositories{
        flatDir{
            dirs 'libs'
        }
    }
}
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.aar'])
    implementation files('libs/kiwiguard.aar')
}

(3)添加SDK所需权限

编辑AndroidManifest.xml 文件,添加如下权限。

<!-- 网络权限(必选) -->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- IMEI获取(必选) -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

(4)Proguard混淆配置

编辑Proguard 配置文件,所在位置一般为 app/src/proguard-rules.pro。

-dontwarn com.kiwisec.**
-keep class com.kiwisec.**{*;}

(5)API 6.0或以上动态权限申请说明

Android 6.0 及以上对于敏感权限需要弹窗申请,所以上面所需权限中的READ_PHONE_STATE 需要动态申请,申请时可按如下示例进行。

public void requestPermission() {
        //权限检查
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.READ_PHONE_STATE
) != PackageManager.PERMISSION_GRANTED) {
            //申请权限
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.READ_PHONE_STATE
}, 1);
        }
    }

5.1.2 接口使用说明

(1)初始化SDK( 该步骤不可省略,setAppID()、setup() 都必须调用 )

初始化建议放到应用Application中的onCreate( ) 方法中进行。

import com.kiwisec.KiwiGuard;

public class MyApplication extends Application
{
    @Override
    public void onCreate()
    {
        super.onCreate();

        // 设置KiwiGuard 必要的项目关联信息
        // 在调用SDK 之前需要调用该接口设置appID

        // @param appID - 从几维平台创建项目时获取
        // @throws RuntimeException - appID为空或者空字串则抛出异常
        KiwiGuard.setAppID("在平台创建KiwiGuard手动SDK项目的AppID");

        // 初始化KiwiGuard
        // 初始化 KiwiGuard SDK
        KiwiGuard.setup();
    }
}

(2)获取deviceToken

整个过程由于是耗时操作,必须要在非主线程上执行,否则会crash。

 private void requestDeviceToken(){
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                HashMap<String,String> options = new HashMap<>();
                String deviceToken = KiwiGuard.getDeviceToken(options);
                //TODO: 把 deviceToken 结合其他参数,发送POST请求,可以获取设备风险信息 (参考KiwiGuard HTTP接口接入)
            }
        });
        thread.start();
    }

在需要进行风险识别时调用上述的getDeviceToken,例如:

  • 新用户注册后,进行风险画像查询,用于新人红包、注册礼物的差异化投放;
  • 存量用户登录后,进行风险画像查询,用于日常活动运营的差异化投放;
  • 活动奖励下发前,进行风险画像查询,例如随机红包、抽奖等概率性活动;
  • 每日的例行查询,进行画像库或风控引擎的数据更新。 (3)异常说明
    调用 setAppID()时,appID 设置不正确 
    RuntimeException("appID can't be null or empty!");
    调用 setup() 前,未调用setAppID()
    RuntimeException("You need call KiwiGuard.setAppID() before setup KiwiGuard SDK");
    调用 getDeviceToken()时,未开子线程调用
    RuntimeException("Can't call KiwiGuard.getToken in MainUI thread");
    ----------- native 层会抛出以下两个异常 ----------
    初始化SDK时,appID 未设置
    NullPointerException("options can't be null!");
    初始化SDK时,未获取到appID 
    RuntimeException("fetch appID exception!");
    

5.2 KiwiGuard SDK后端接入

备注:本节可通过访问几维安全服务端API获取终端威胁数据源;可在App测试环节与上线后进行操作。

5.2.1 HTTP接口接入方法

(1) 接口地址(v2)

encrypt_key = 'secret:{AppGroupSecret}*{deviceToken}*{timestamp}:encrypt'.format(AppGroupSecret=AppGroupSecret, deviceToken=deviceToken, timestamp=timestamp)

备注:2021/9/16 11:00:00已将API升级至v2版本,旨在为企业提供可靠且全面的终端威胁数据源**(为了更好的体验,请尽量使用v2版本的API)**,点击查看v1版本API地址及响应的数据

(2) 请求参数

字段 类型 传入说明 描述
deviceToken string 必传参数 用户前端获取的deviceToken
timestamp string 必传参数 调用服务的秒级时间戳 (例如:“1650934578”)
sign string 必传参数 查询数据时服务端校验数据是否篡改的字段(通过appGroupSecret,deviceToken,timestamp指定规则字符串后通过md5字符串加密生成的32位加密后的字符串,见下方代码示例)
appGroupID string 请求参数中两者必须选填一个 几维安全SaaS平台获取(用来获取应用组下所有接入SDK的应用终端威胁信息)
appID string 前往几维安全Saas平台获取(用来获取当前应用的终端威胁信息)

*如何生成参数sign?

【Python实例】

① 构建待加密的指定规则字符串 ;

AppGroupSecret: 几维安全SaaS平台获取( KiwiGuard > 应用管理 > 应用组AppGroupSecret )

encrypt_key = 'secret:{AppGroupSecret}*{deviceToken}*{timestamp}:encrypt'.format(AppGroupSecret=AppGroupSecret, deviceToken=deviceToken, timestamp=timestamp)

② 使用md5加密,获取加密后的数据传递给sign字段;

import hashlib
m = hashlib.md5()
m.update(encrypt_key.encode())
sign = m.hexdigest()

【Java实例】

// 封装的计算sign函数    
public String getStrArrMd5Sign(String []strArr){
        StringBuilder sb = new StringBuilder();
        String signStr = null, signMd5 = null;
        if(strArr != null && strArr.length > 0){
            sb.append("secret:");
            for(int i=0; i<strArr.length; i++){
                sb.append(strArr[i]);
                if(i != (strArr.length-1))
                    sb.append("*");
            }
            sb.append(":encrypt");
            signStr = sb.toString();
            Log.d(TAG,signStr);
            if(!signStr.isEmpty()){
                MessageDigest md = null;
                try{
                    md = MessageDigest.getInstance("MD5");
                    // 计算md5函数
                    md.update(signStr.getBytes());


                    signMd5 = new BigInteger(1, md.digest()).toString(16);
                                        // (fix)不满32位前面添加0
                    while(signMd5.length() < 32 ){
                        signMd5 = "0" + signMd5;
                    }
                }catch (Exception e){
                    Log.d(TAG,"no such MD5 algorithm"+e.getMessage());
                }
            }
        }

        return signMd5;
    }
// 调用上面封装的函数获取sign 
String sign = getStrArrMd5Sign(new String[]{AppGroupSecret
,deviceToken,"时间戳"});//请严格按照该拼接顺序(时间戳例如:"16509345787")

// 封装json 请求体
// appGroupID 和 appID 至少任意填一个
JSONObject jsonBody = new JSONObject();
                    jsonBody.put("deviceToken",deviceToken);
                    jsonBody.put("appGroupID","");
                    jsonBody.put("sign",sign);
                    jsonBody.put("timestamp","时间戳");
                    jsonBody.put("appID","");

// TODO 发起网络请求

*如何发送POST请求?

【Java实例】

public class HttpUtils {
    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    private static OkHttpClient client = new OkHttpClient();

    public static Response post(String url, String json) throws IOException {
        RequestBody body = RequestBody.create(JSON, json);
        Request request = new Request.Builder()
                .url(url)      //填写接口地址
                .post(body)    //填写请求参数
                .build();
        Response response = client.newCall(request).execute();
        return response;
    }
}

【Python实例】

import hashlib, requests, pprint, json


def md5_convert(string):
    """
    计算字符串md5值
    :param string: 输入字符串
    :return: 字符串md5
    """
    m = hashlib.md5()
    m.update(string.encode())
    return m.hexdigest()

if __name__ == '__main__':
    appSecretKey = '****'  # 应用管理应用组所对应的 SecretKey
    deviceToken = '****'  # deviceID
    ts = ****  # 时间戳

    md5_key = 'secret:{appSecretKey}*{deviceToken}*{ts}:encrypt'.format(appSecretKey=appSecretKey, deviceToken=deviceToken, ts=ts)
    sign = md5_convert(md5_key)

    body = {
        "appGroupID": "****",  # 应用组id
,web端获取
        "appID": "****",  # appID,web端获取
        "deviceToken": deviceToken,
        "sign": sign,
        "timestamp": ts
    }

    pprint.pprint(json.loads(requests.post(url='****', json=body).text), depth=4)

(备注:若没有查看appGroupSecret的权限,请联系几维安全工作人员。)

(3)成功响应

字段 类型 描述
code int 状态码
message String 状态描述
data Json 返回设备指纹deviceID及设备风险数据

成功示例:

{
    "message": "success!",
    "code": 1,
    "data": {
            "deviceID":"xxx",
            "fakeRiskDevice":{        
                "virtualEnv":{               
                key1:value1,
                key2:value2
            }
            },
            "environmentRiskDevice":{
                "root":{
                key1:value1
            }       
            },
            "fightRiskDevice":{
                "debug":{
                key1:value1
            }
            },
            "suspiciousRiskDevice":{
                "gameScriptTools": {
                key1:value1,
                key2:value2
            } 
            }
        }
}

(4)错误响应

字段 类型 描述
code int 状态码
message String 状态描述

失败示例:

{
    "message": '缺少查询参数!', 
    "code": 1880001
}
错误码 描述
1005 缺少认证信息,接口请求失败!请核对url
1880001 缺少查询参数。详情看请求参数说明
1880002 sign校验失败,md5生成的加密字符串错误
1880003 appID 不存在,请检查
1880004 appGroupID 不存在,请检查
1880005 设备指纹不存在,请检查

5.2.2 HTTP接口返回参数明细说明

成功响应时候,data字段Json类型的内容为:

字段 类型 描述
deviceID String 设备指纹
uploadTime int 服务端的处理时间
fakeRiskDevice Json 虚假设备相关标签信息
environmentRiskDevice Json 环境风险相关的标签信息
fightRiskDevice Json 对抗风险相关的标签信息
suspiousRiskDevice Json 可疑设备相关的标签信息

(1)fakeRiskDevice详细内容

① 模拟器检测:

字段 类型 描述
emulator Json 模拟器检测

emulator详细内容:

字段 类型 描述
checked bool 应用是否运行在模拟器中
emulatorBrand String 模拟器厂商

② 虚拟机检测:

字段 类型 描述
virtualEnv Json 虚拟机检测

virtualEnv详细内容:

字段 类型 描述
checked bool 应用是否运行在虚拟机中
virtualBrand String 虚拟机包名
virtualPackage String 虚拟机厂商

③ 云真机检测:

字段 类型 描述
cloudMachine Json 云真机检测

cloudMachine详细内容:

字段 类型 描述
checked bool 应用是否运行在云真机中
cloudMachineBrand String 云真机厂商

(2)environmentRiskDevice详细内容

① ROOT检测

字段 类型 描述
ROOT Json ROOT环境检测

ROOT环境详细内容:

字段 类型 描述
checked bool 设备运行的终端是否为ROOT环境

② VPN检测

字段 类型 描述
VPN Json VPN检测

VPN详细内容:

字段 类型 描述
checked bool 是否安装VPN
vpnPackages array 已安装的VPN的应用包名数组,以英文逗号分割

(3)fightRiskDevice详细内容

字段 类型 描述
debug Json 调试风险检测

debug详细内容:

字段 类型 描述
checked bool 是否存在调试行为
dbgJava bool 是否存在Java调试
dbgNative bool 是否存在Native调试

(4)suspiciousRiskDevice详细内容

① GG修改器检测

字段 类型 描述
gameGuard Json GG修改器检测

gameGuard详细内容:

字段 类型 描述
checked bool 设备是否安装GG修改器

② 八门神器检测

字段 类型 描述
xdGame Json 八门神器检测

xdGame详细内容:

字段 类型 描述
checked bool 设备是否安装八门神器

③ SIM卡状态检测

字段 类型 描述
SIM Json SIM卡状态检测

SIM详细内容:

字段 类型 描述
checked bool 设备SIM卡状态是否异常
simStateDesc String 设备SIM卡异常状态描述

④ 调试模式检测

字段 类型 描述
debugMode Json 调试模式检测

debugMode详细内容:

字段 类型 描述
checked bool 设备是否开启调试模式

⑤ 自动点击工具检测

字段 类型 描述
automaticTools Json 自动点击工具检测

automaticTools详情内容:

字段 类型 描述
checked bool 设备是否安装自动点击工具
aidPackages array 已安装的自动点击工具的应用包名数组,以英文逗号分割

⑥ 辅助服务检测

字段 类型 描述
accessibilityService Json 辅助服务检测

accessibilityService详细内容:

字段 类型 描述
checked bool 设备是否开启辅助服务

⑦ 多开工具检测

字段 类型 描述
multipleTools Json 多开工具检测

multipleTools详细内容:

字段 类型 描述
checked bool 设备是否安装了多开工具
multiPackages array 已安装的多开工具的应用包名数组,以英文逗号分割

⑧ Hook检测

字段 类型 描述
hookDevice Json Hook检测

hookDevice详细内容:

字段 类型 描述
checked bool 进程是否被注入其他代码或库
hookTool String Hook框架

⑨ 工程模式检测

字段 类型 描述
engineeringMode Json 工程模式检测

engineeringMode详细内容:

字段 类型 描述
checked bool 设备是否进入工程模式

⑩ 远程操作工具检测

字段 类型 描述
controlTools Json 远程操作工具检测

controlTools详细内容:

字段 类型 描述
checked bool 设备是否安装远程操作工具
remoteCtrlPackages array 已安装的远程操作工具的应用包名数组,以英文逗号分割

⑪ 云设备控制工具检测

字段 类型 描述
cloudDeviceControlTools Json 云设备控制工具检测

cloudDeviceControlTools详细内容:

字段 类型 描述
checked bool 设备是否安装了云设备控制工具
cloudCtrlPackages array 已安装的云设备控制工具的应用包名数组,以英文逗号分割

⑫ 程序脚本辅助工具检测

字段 类型 描述
gameScriptTools Json 程序脚本辅助工具检测

gameScriptTools详细内容:

字段 类型 描述
checked bool 设备是否安装了程序脚本辅助工具
gameScriptPackages array 已安装的游戏程序辅助工具的应用包名数组,以英文逗号分割

6 FAQ

6.1 Cleartext HTTP traffic to xxx.xxx.xxx.xxx not permitted

这个问题一般是apk 中使用了http 通信,高版本手机中默认只允许https 通信。所以如果要使用http通信,需要在AndroidManifest.xml 中添加一行配置:

android:usesCleartextTraffic="true"

在AndroidManifest.xml 中如下:

<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:name=".MyApplication"

android:usesCleartextTraffic="true"
android:theme="@style/AppTheme">
最后更新时间: 2024-11-20 17:34:45

results matching ""

    No results matching ""