├── .gitattributes
├── .github
└── workflows
│ ├── android.yml
│ └── release.yml
├── .gitignore
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── demo_release.jks
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── cn
│ │ └── tongdun
│ │ └── android
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── assets
│ │ └── PrivacyPolicy.html
│ ├── kotlin
│ │ └── cn
│ │ │ └── tongdun
│ │ │ └── android
│ │ │ ├── MyApplication.kt
│ │ │ ├── activitys
│ │ │ ├── ItemListActivity.kt
│ │ │ ├── MainActivity.kt
│ │ │ └── SplashActivity.kt
│ │ │ ├── adapters
│ │ │ ├── AppListRecyclerViewAdapter.kt
│ │ │ ├── BaseRecyclerViewAdapter.kt
│ │ │ ├── DeviceInfoItemAdapter.kt
│ │ │ └── ViewPagerAdapter.kt
│ │ │ ├── base
│ │ │ ├── BaseActivity.kt
│ │ │ └── BaseFragment.kt
│ │ │ ├── beans
│ │ │ ├── AppItemData.kt
│ │ │ ├── DetailsItemBean.kt
│ │ │ └── DeviceModuleItemBean.kt
│ │ │ └── fragments
│ │ │ ├── DeviceIdFragment.kt
│ │ │ └── DeviceInfoFragment.kt
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ ├── build_info_background.xml
│ │ ├── detail_item_divider.xml
│ │ ├── ic_back.xml
│ │ ├── ic_battery.xml
│ │ ├── ic_down_arrow.xml
│ │ ├── ic_installed_app.xml
│ │ ├── ic_internal_storage.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── ic_phone.xml
│ │ ├── ic_random_access_memory.xml
│ │ ├── ic_sensor_accelerometer.xml
│ │ ├── ic_sensor_all.xml
│ │ ├── ic_sensor_gravity.xml
│ │ ├── ic_sensor_gyroscope.xml
│ │ ├── ic_sensor_heartrate.xml
│ │ ├── ic_sensor_hinge.xml
│ │ ├── ic_sensor_humidity.xml
│ │ ├── ic_sensor_light.xml
│ │ ├── ic_sensor_magnetic_field.xml
│ │ ├── ic_sensor_motion.xml
│ │ ├── ic_sensor_next.xml
│ │ ├── ic_sensor_orientation.xml
│ │ ├── ic_sensor_pressure.xml
│ │ ├── ic_sensor_private.xml
│ │ ├── ic_sensor_proximity.xml
│ │ ├── ic_sensor_step.xml
│ │ ├── ic_sensor_temperature.xml
│ │ ├── ic_sensor_tilt.xml
│ │ ├── ic_setting.xml
│ │ ├── ic_up_arrow.xml
│ │ └── item_card_background.xml
│ │ ├── layout
│ │ ├── activity_app_list.xml
│ │ ├── activity_main.xml
│ │ ├── activity_splash.xml
│ │ ├── fragment_device_id.xml
│ │ ├── fragment_device_info.xml
│ │ ├── include_battery_info.xml
│ │ ├── include_build_info.xml
│ │ ├── include_installed_app_list.xml
│ │ ├── include_memory_info.xml
│ │ ├── include_sensor_list.xml
│ │ ├── include_setting_info.xml
│ │ ├── include_title_layout.xml
│ │ ├── item_app_list.xml
│ │ └── item_details.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ ├── values-night
│ │ ├── colors.xml
│ │ └── themes.xml
│ │ ├── values-zh-rCN
│ │ └── strings.xml
│ │ ├── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── themes.xml
│ │ └── xml
│ │ ├── backup_rules.xml
│ │ └── data_extraction_rules.xml
│ └── test
│ └── java
│ └── cn
│ └── tongdun
│ └── android
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── jitpack.yml
├── resources
├── demo.gif
├── demo_2.gif
├── logo_dark.png
└── logo_light.png
├── settings.gradle
└── trustdevice
├── .gitignore
├── build.gradle
├── consumer-rules.pro
├── proguard-rules.pro
└── src
├── androidTest
└── java
│ └── cn
│ └── tongdun
│ └── android
│ └── ExampleInstrumentedTest.java
├── main
├── AndroidManifest.xml
├── cpp
│ ├── CMakeLists.txt
│ ├── common
│ │ ├── logger.h
│ │ └── macro.h
│ ├── trustdevice.cpp
│ ├── trustdevice_risk.cpp
│ ├── trustdevice_risk.h
│ ├── trustdevice_utils.cpp
│ └── trustdevice_utils.h
├── java
│ └── cn
│ │ └── tongdun
│ │ └── mobrisk
│ │ ├── TDRisk.kt
│ │ ├── TDRiskCallback.kt
│ │ ├── TDRiskOption.kt
│ │ ├── beans
│ │ └── DeviceInfo.kt
│ │ ├── core
│ │ ├── FMCore.kt
│ │ ├── collectors
│ │ │ ├── AdvertisingIdClient.kt
│ │ │ ├── AppListCollector.kt
│ │ │ ├── BatteryInfoCollector.kt
│ │ │ ├── BuildInfoCollector.kt
│ │ │ ├── CpuInfoCollector.kt
│ │ │ ├── DebugInfoCollector.kt
│ │ │ ├── DeviceBaseInfoCollector.kt
│ │ │ ├── DeviceIdCollector.kt
│ │ │ ├── DeviceInfoTamperedCollector.kt
│ │ │ ├── DevicePersonalizationInfoCollector.kt
│ │ │ ├── EmulatorCollector.kt
│ │ │ ├── HookCollector.kt
│ │ │ ├── MagiskCollector.kt
│ │ │ ├── MemoryInfoCollector.kt
│ │ │ ├── RootCollector.kt
│ │ │ ├── SensorsInfoCollector.kt
│ │ │ ├── SettingInfoCollector.kt
│ │ │ ├── VpnCollector.kt
│ │ │ └── XposedCollector.kt
│ │ └── tools
│ │ │ ├── Constants.kt
│ │ │ ├── DeviceInfoUtils.kt
│ │ │ ├── EnvUtils.kt
│ │ │ ├── ExceptionSafeExecutor.kt
│ │ │ ├── FileUtils.kt
│ │ │ ├── JNIHelper.kt
│ │ │ ├── Logger.kt
│ │ │ ├── NetworkUtils.kt
│ │ │ └── StringUtils.kt
│ │ └── providers
│ │ ├── AppListsRawData.kt
│ │ ├── BatteryInfoRawData.kt
│ │ ├── BuildInfoRawData.kt
│ │ ├── CpuInfoRawData.kt
│ │ ├── DeviceIdRawData.kt
│ │ ├── DeviceInfoProvider.kt
│ │ ├── MemoryInfoRawData.kt
│ │ ├── RiskInfoRawData.kt
│ │ ├── SensorInfoRawData.kt
│ │ └── SettingInfoRawData.kt
└── resources
│ └── META-INF
│ └── com
│ └── trustdecision
│ └── android
│ └── mobrisk
│ └── verification.properties
└── test
└── java
└── cn
└── tongdun
└── android
└── ExampleUnitTest.java
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.js linguist-detectable=false
2 | *.css linguist-detectable=false
3 | *.html linguist-detectable=false
4 |
--------------------------------------------------------------------------------
/.github/workflows/android.yml:
--------------------------------------------------------------------------------
1 | name: Android CI
2 |
3 | on:
4 | push:
5 | branches: [ "main" ]
6 | pull_request:
7 | branches: [ "main" ]
8 |
9 | jobs:
10 | build:
11 |
12 | name: Build Release
13 | runs-on: ubuntu-latest
14 |
15 | steps:
16 | - name: Checkout code
17 | uses: actions/checkout@v3
18 | - name: Set up JDK
19 | uses: actions/setup-java@v3
20 | with:
21 | java-version: '17'
22 | distribution: 'temurin'
23 | cache: gradle
24 |
25 | - name: Grant execute permission for gradlew
26 | run: chmod +x gradlew
27 |
28 | - name: Get latest ninja
29 | uses: urkle/action-get-ninja@v1
30 |
31 | - name: Setup CMake
32 | uses: jwlawson/actions-setup-cmake@v1
33 | with:
34 | cmake-version: '3.22.1'
35 |
36 | - name: Lint
37 | run: ./gradlew trustdevice:lint
38 |
39 | - name: Test
40 | run: ./gradlew trustdevice:test
41 |
42 | - name: Build library
43 | run: ./gradlew trustdevice:assembleRelease
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | tags:
6 | - '*'
7 |
8 | jobs:
9 |
10 | release:
11 | name: Create Release
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | - name: Checkout code
16 | uses: actions/checkout@v3
17 | - name: Set up JDK
18 | uses: actions/setup-java@v3
19 | with:
20 | java-version: '17'
21 | distribution: 'temurin'
22 | cache: gradle
23 | - name: Grant execute permission for gradlew
24 | run: chmod +x gradlew
25 |
26 | - name: Lint
27 | run: ./gradlew trustdevice:lint
28 |
29 | - name: Test
30 | run: ./gradlew trustdevice:test
31 |
32 | - name: Build library
33 | run: ./gradlew trustdevice:assembleRelease
34 |
35 | - name: Build App
36 | run: ./gradlew app:assembleRelease
37 |
38 | - name: Display structure of downloaded files
39 | run: ls -R
40 |
41 | - name: Set release name
42 | run: echo RELEASE_NAME=${GITHUB_REF} >> $GITHUB_ENV
43 |
44 | - name: Get version
45 | id: get_version
46 | run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
47 |
48 | - name: Create Release
49 | id: create_release
50 | uses: actions/create-release@v1
51 | env:
52 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
53 | with:
54 | tag_name: ${{ github.ref }}
55 | release_name: ${{ env.RELEASE_NAME }}
56 | body:
57 | update demo app.
58 | draft: false
59 | prerelease: false
60 |
61 | - name: Upload aar to release
62 | uses: actions/upload-release-asset@v1.0.1
63 | env:
64 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
65 | with:
66 | upload_url: ${{ steps.create_release.outputs.upload_url }}
67 | asset_path: ./trustdevice/build/outputs/aar/trustdevice-release.aar
68 | asset_name: trustdevice-release-${{ steps.get_version.outputs.VERSION }}.aar
69 | # Common MIME types:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
70 | asset_content_type: application/zip
71 |
72 | - name: Upload apk to release
73 | uses: actions/upload-release-asset@v1.0.1
74 | env:
75 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
76 | with:
77 | upload_url: ${{ steps.create_release.outputs.upload_url }}
78 | asset_path: ./app/build/outputs/apk/release/TrustDevice-release-${{ steps.get_version.outputs.VERSION }}.apk
79 | asset_name: TrustDevice-release-${{ steps.get_version.outputs.VERSION }}.apk
80 | # Common MIME types:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
81 | asset_content_type: application/zip
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.gradle/
2 | /.idea/
3 | /build/
4 | local.properties
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 trustdecision
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | id 'org.jetbrains.kotlin.android'
4 | id 'kotlin-kapt'
5 | }
6 |
7 | android {
8 | namespace 'com.trustdevice.android.demo'
9 | compileSdk 34
10 |
11 | defaultConfig {
12 | applicationId "com.trustdevice.android.demo"
13 | minSdk 21
14 | targetSdk 34
15 | versionCode 12
16 | versionName "1.1.0"
17 | ndk {
18 | abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
19 | }
20 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
21 | }
22 |
23 | signingConfigs {
24 | release {
25 | storeFile file("demo_release.jks")
26 | storePassword 'TRUSTDEVICE'
27 | keyAlias 'TRUSTDEVICE_KEY_ALIAS'
28 | keyPassword 'TRUSTDEVICE'
29 | }
30 | }
31 |
32 | buildTypes {
33 | release {
34 | minifyEnabled false
35 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
36 | signingConfig signingConfigs.release
37 | }
38 | }
39 | applicationVariants.all { variant ->
40 | variant.outputs.all {
41 | outputFileName = "TrustDevice-${variant.name}-${variant.versionName}.apk"
42 | }
43 | }
44 | kotlinOptions {
45 | jvmTarget = '1.8'
46 | }
47 | buildFeatures {
48 | viewBinding true
49 | dataBinding true
50 | }
51 | }
52 |
53 | dependencies {
54 | // implementation fileTree(dir: "libs", include: ["*.jar", "*.aar"])
55 | implementation project(path: ':trustdevice')
56 | implementation 'com.tencent:mmkv:1.2.15'
57 | implementation 'androidx.appcompat:appcompat:1.5.1'
58 | implementation 'androidx.recyclerview:recyclerview:1.2.1'
59 | implementation 'com.google.android.material:material:1.5.0'
60 | implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
61 | testImplementation 'junit:junit:4.13.2'
62 | androidTestImplementation 'androidx.test.ext:junit:1.1.4'
63 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
64 | }
--------------------------------------------------------------------------------
/app/demo_release.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trustdecision/trustdevice-android/70c7f5454db1a95cb9e4cfaef766f90d831ce833/app/demo_release.jks
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/app/src/androidTest/java/cn/tongdun/android/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package cn.tongdun.android;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.platform.app.InstrumentationRegistry;
6 | import androidx.test.ext.junit.runners.AndroidJUnit4;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
24 | assertEquals("com.trustdevice.android", appContext.getPackageName());
25 | }
26 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
25 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/cn/tongdun/android/MyApplication.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.android
2 |
3 | import android.app.Application
4 | import cn.tongdun.mobrisk.TDRisk.init
5 | import com.tencent.mmkv.MMKV
6 |
7 | class MyApplication : Application() {
8 | override fun onCreate() {
9 | super.onCreate()
10 | MMKV.initialize(this)
11 | val isAgree = MMKV.defaultMMKV().decodeBool("isAgreePrivacyAgreement")
12 | if (isAgree) {
13 | init(this)
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/cn/tongdun/android/activitys/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.android.activitys
2 |
3 |
4 | import android.widget.TextView
5 | import androidx.viewpager2.widget.ViewPager2
6 | import cn.tongdun.android.adapters.ViewPagerAdapter
7 | import cn.tongdun.android.base.BaseActivity
8 | import com.google.android.material.tabs.TabLayout
9 | import com.google.android.material.tabs.TabLayoutMediator
10 | import com.trustdevice.android.demo.R
11 | import com.trustdevice.android.demo.databinding.ActivityMainBinding
12 |
13 |
14 | class MainActivity : BaseActivity() {
15 | private val mTabList: MutableList = ArrayList()
16 | private var mTabLayoutMediator: TabLayoutMediator? = null
17 | override fun getViewBinding(): ActivityMainBinding = ActivityMainBinding.inflate(layoutInflater)
18 |
19 | override fun initData() {
20 | mTabList.add(getString(R.string.tab_title_device_id))
21 | mTabList.add(getString(R.string.tab_title_device_info))
22 | }
23 |
24 | override fun initView() {
25 | val viewPagerAdapter =
26 | ViewPagerAdapter(mTabList.size, supportFragmentManager, lifecycle)
27 | binding.viewpager.offscreenPageLimit = ViewPager2.OFFSCREEN_PAGE_LIMIT_DEFAULT
28 | binding.viewpager.adapter = viewPagerAdapter
29 | mTabLayoutMediator = TabLayoutMediator(
30 | binding.tabLayout, binding.viewpager
31 | ) { tab: TabLayout.Tab, position: Int ->
32 | val tabView = TextView(this)
33 | tabView.text = mTabList[position]
34 | tabView.setTextColor(getResources().getColor(R.color.normal_text))
35 | tab.customView = tabView
36 | }
37 | // binding
38 | mTabLayoutMediator!!.attach()
39 | }
40 |
41 | override fun onDestroy() {
42 | mTabLayoutMediator!!.detach()
43 | super.onDestroy()
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/cn/tongdun/android/activitys/SplashActivity.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.android.activitys
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.Intent
5 | import android.webkit.WebView
6 | import android.webkit.WebViewClient
7 | import android.widget.Toast
8 | import cn.tongdun.android.base.BaseActivity
9 | import cn.tongdun.mobrisk.TDRisk.init
10 | import com.tencent.mmkv.MMKV
11 | import com.trustdevice.android.demo.R
12 | import com.trustdevice.android.demo.databinding.ActivitySplashBinding
13 |
14 | @SuppressLint("CustomSplashScreen")
15 | class SplashActivity() : BaseActivity() {
16 | override fun getViewBinding(): ActivitySplashBinding =
17 | ActivitySplashBinding.inflate(layoutInflater)
18 |
19 | override fun initData() {
20 | goToMainActivity()
21 | }
22 |
23 | @SuppressLint("SetJavaScriptEnabled")
24 | override fun initView() {
25 | val webSettings = binding.wvWebView.settings
26 | webSettings.apply {
27 | javaScriptCanOpenWindowsAutomatically =
28 | true //Setting js can directly open the window, such as window.open(), the default is false
29 | javaScriptEnabled =
30 | true //Whether to allow js execution, the default is false. When set to true, it will remind you that it may cause XSS vulnerabilities
31 | setSupportZoom(true) //Whether it can be zoomed, the default is true
32 | builtInZoomControls =
33 | true //Whether to display the zoom button, the default is false
34 | useWideViewPort =
35 | true //Set this property to scale at any scale. big view mode
36 | loadWithOverviewMode =
37 | true //Solve the web page adaptation problem together with setUseWideViewPort(true)
38 | domStorageEnabled = true //DOM Storage
39 | }
40 | binding.wvWebView.webViewClient = object : WebViewClient() {
41 | override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
42 | Toast.makeText(this@SplashActivity, url, Toast.LENGTH_SHORT).show()
43 | view.loadUrl(url)
44 | return true
45 | }
46 |
47 | override fun onReceivedError(
48 | view: WebView,
49 | errorCode: Int,
50 | description: String,
51 | failingUrl: String
52 | ) {
53 | super.onReceivedError(view, errorCode, description, failingUrl)
54 | Toast.makeText(this@SplashActivity, "error!!!", Toast.LENGTH_SHORT).show()
55 | }
56 | }
57 | binding.wvWebView.loadUrl("file:///android_asset/PrivacyPolicy.html")
58 |
59 | binding.setClickListener { view ->
60 | when (view.id) {
61 | R.id.bt_agree -> {
62 | MMKV.defaultMMKV().encode("isAgreePrivacyAgreement", true)
63 | init(this)
64 | goToMainActivity()
65 | }
66 |
67 | R.id.bt_reject -> finish()
68 | }
69 | }
70 | }
71 |
72 | private fun goToMainActivity() {
73 | val isAgree = MMKV.defaultMMKV().decodeBool("isAgreePrivacyAgreement")
74 | if (isAgree) {
75 | val intent = Intent(this@SplashActivity, MainActivity::class.java)
76 | startActivity(intent)
77 | finish()
78 | }
79 | }
80 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/cn/tongdun/android/adapters/AppListRecyclerViewAdapter.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.android.adapters
2 |
3 | import android.annotation.SuppressLint
4 | import android.widget.ImageView
5 | import android.widget.TextView
6 | import cn.tongdun.android.beans.AppItemData
7 | import com.trustdevice.android.demo.R
8 |
9 | /**
10 | * @description:
11 | * @author: wuzuchang
12 | * @date: 2023/5/16
13 | */
14 | class AppListRecyclerViewAdapter(private var _data: List) : BaseRecyclerViewAdapter(_data) {
15 |
16 | override fun getLayoutId(viewType: Int): Int {
17 | return R.layout.item_app_list
18 | }
19 |
20 | override fun convert(holder: BaseViewHolder, data: AppItemData?, position: Int) {
21 | val iv_icon: ImageView? = holder.getView(R.id.iv_app_icon)
22 | iv_icon?.setImageDrawable(data?.icon)
23 | val tv_app_name: TextView? = holder.getView(R.id.tv_app_name)
24 | tv_app_name?.text = data?.appName?:""
25 | val tv_application: TextView? = holder.getView(R.id.tv_application)
26 | tv_application?.text = data?.packageName?:""
27 | }
28 |
29 |
30 | fun updateData(data: List) {
31 | _data = data
32 | notifyDataSetChanged()
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/cn/tongdun/android/adapters/BaseRecyclerViewAdapter.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.android.adapters
2 |
3 | import android.util.SparseArray
4 | import android.view.LayoutInflater
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import android.widget.TextView
8 | import androidx.recyclerview.widget.RecyclerView
9 |
10 | /**
11 | * @description:
12 | * @author: wuzuchang
13 | * @date: 2023/5/16
14 | */
15 | abstract class BaseRecyclerViewAdapter(val data: List) : RecyclerView.Adapter() {
16 |
17 |
18 | abstract fun getLayoutId(viewType: Int): Int
19 |
20 | abstract fun convert(holder: BaseViewHolder, data: T, position: Int)
21 |
22 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
23 | return BaseViewHolder[parent, getLayoutId(viewType)]
24 | }
25 |
26 | override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
27 | convert(holder, data[position], position)
28 | }
29 |
30 | override fun getItemCount(): Int {
31 | return data.size
32 | }
33 |
34 | class BaseViewHolder private constructor(private val mConvertView: View) :
35 | RecyclerView.ViewHolder(
36 | mConvertView
37 | ) {
38 | private val mViews: SparseArray = SparseArray()
39 |
40 | fun getView(id: Int): T? {
41 | var v = mViews[id]
42 | if (v == null) {
43 | v = mConvertView.findViewById(id)
44 | mViews.put(id, v)
45 | }
46 | return v as T?
47 | }
48 |
49 | fun setText(id: Int, value: String) {
50 | val view = getView(id)
51 | view?.text = value
52 | }
53 |
54 | companion object {
55 | operator fun get(parent: ViewGroup, layoutId: Int): BaseViewHolder {
56 | val convertView =
57 | LayoutInflater.from(parent.context).inflate(layoutId, parent, false)
58 | return BaseViewHolder(convertView)
59 | }
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/cn/tongdun/android/adapters/DeviceInfoItemAdapter.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.android.adapters
2 |
3 | import android.text.TextUtils
4 | import android.util.Pair
5 | import android.view.View
6 | import android.widget.TextView
7 | import com.trustdevice.android.demo.R
8 |
9 |
10 | class DeviceInfoItemAdapter(data: List>) : BaseRecyclerViewAdapter>(data) {
11 | override fun getLayoutId(viewType: Int): Int {
12 | return R.layout.item_details
13 | }
14 |
15 | override fun convert(holder: BaseViewHolder, data: Pair, position: Int) {
16 | val name = holder.getView(R.id.tv_name)
17 | name?.text = data.first
18 | val value = holder.getView(R.id.tv_value)
19 | if (TextUtils.isEmpty(data.second)) {
20 | value?.visibility = View.GONE
21 | } else {
22 | value?.text = data.second
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/cn/tongdun/android/adapters/ViewPagerAdapter.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.android.adapters
2 |
3 | import androidx.fragment.app.Fragment
4 | import androidx.fragment.app.FragmentManager
5 | import androidx.lifecycle.Lifecycle
6 | import androidx.viewpager2.adapter.FragmentStateAdapter
7 | import cn.tongdun.android.fragments.DeviceIdFragment
8 | import cn.tongdun.android.fragments.DeviceInfoFragment
9 |
10 |
11 | class ViewPagerAdapter(
12 | private val itemCount: Int,
13 | fragmentManager: FragmentManager,
14 | lifecycle: Lifecycle
15 | ) :
16 | FragmentStateAdapter(fragmentManager, lifecycle) {
17 | override fun createFragment(position: Int): Fragment {
18 | if (position == 0) {
19 | return DeviceIdFragment()
20 | } else if (position == 1) {
21 | return DeviceInfoFragment()
22 | }
23 | return DeviceIdFragment()
24 | }
25 |
26 | override fun getItemCount(): Int {
27 | return itemCount
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/cn/tongdun/android/base/BaseActivity.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.android.base
2 |
3 | import android.content.Context
4 | import android.content.res.Configuration
5 | import android.os.Bundle
6 | import android.view.View
7 | import androidx.appcompat.app.AppCompatActivity
8 | import androidx.viewbinding.ViewBinding
9 |
10 | abstract class BaseActivity : AppCompatActivity() {
11 | private lateinit var _binding: T
12 | protected val binding get() = _binding
13 |
14 | protected lateinit var mContext: Context
15 | override fun onCreate(savedInstanceState: Bundle?) {
16 | super.onCreate(savedInstanceState)
17 | mContext = this
18 | _binding = getViewBinding()
19 | setContentView(_binding.root)
20 |
21 | if (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES) {
22 | window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
23 | } else {
24 | window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
25 | }
26 |
27 | initData()
28 | initView()
29 | }
30 |
31 | protected abstract fun getViewBinding(): T
32 |
33 | protected abstract fun initData()
34 | protected abstract fun initView()
35 | override fun onDestroy() {
36 | super.onDestroy()
37 | }
38 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/cn/tongdun/android/base/BaseFragment.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.android.base
2 |
3 | import android.os.Bundle
4 | import android.view.LayoutInflater
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import androidx.fragment.app.Fragment
8 | import androidx.viewbinding.ViewBinding
9 |
10 | abstract class BaseFragment : Fragment() {
11 | private lateinit var _binding: T
12 | protected val binding get() = _binding;
13 | override fun onCreateView(
14 | inflater: LayoutInflater,
15 | container: ViewGroup?,
16 | savedInstanceState: Bundle?
17 | ): View? {
18 | _binding = getViewBinding(inflater, container)
19 | return _binding.root
20 | }
21 |
22 | protected abstract fun getViewBinding(inflater: LayoutInflater, container: ViewGroup?): T
23 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/cn/tongdun/android/beans/AppItemData.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.android.beans
2 |
3 | import android.graphics.drawable.Drawable
4 |
5 |
6 | data class AppItemData(
7 | val icon: Drawable?,
8 | val appName: String,
9 | val packageName: String,
10 | val versionName: String?
11 | )
12 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/cn/tongdun/android/beans/DetailsItemBean.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.android.beans
2 |
3 |
4 | data class DetailsItemBean(
5 | val name: String, val value: String
6 | )
7 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/cn/tongdun/android/beans/DeviceModuleItemBean.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.android.beans
2 |
3 |
4 | data class DeviceModuleItemBean(
5 | val moduleName: String,
6 | val detailsItemBeans: List
7 | ) {
8 | constructor(
9 | moduleName: String,
10 | describe: String,
11 | detailsItemBeans: List
12 | ) : this(moduleName, detailsItemBeans)
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/cn/tongdun/android/fragments/DeviceIdFragment.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.android.fragments
2 |
3 | import android.os.Bundle
4 | import android.text.TextUtils
5 | import android.util.Log
6 | import android.view.LayoutInflater
7 | import android.view.View
8 | import android.view.ViewGroup
9 | import cn.tongdun.android.base.BaseFragment
10 | import cn.tongdun.mobrisk.TDRisk.getBlackbox
11 | import cn.tongdun.mobrisk.providers.DeviceInfoProvider
12 | import com.trustdevice.android.demo.databinding.FragmentDeviceIdBinding
13 | import org.json.JSONException
14 |
15 |
16 | class DeviceIdFragment : BaseFragment() {
17 | private var mDeviceInfoProvider: DeviceInfoProvider? = null
18 |
19 |
20 | override fun getViewBinding(
21 | inflater: LayoutInflater,
22 | container: ViewGroup?
23 | ): FragmentDeviceIdBinding = FragmentDeviceIdBinding.inflate(inflater, container, false)
24 |
25 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
26 | super.onViewCreated(view, savedInstanceState)
27 | getDeviceID()
28 | initView()
29 | }
30 |
31 | private fun getDeviceID() {
32 | val deviceInfo = getBlackbox()
33 | try {
34 | Log.d("TrustDevice", "deviceInfo = " + deviceInfo.toString(1))
35 | } catch (e: JSONException) {
36 | e.printStackTrace()
37 | }
38 | mDeviceInfoProvider = DeviceInfoProvider(deviceInfo)
39 | }
40 |
41 | private fun initView() {
42 | binding.run {
43 | mDeviceInfoProvider?.run {
44 | tvDeviceId.text = getDeviceInfo().deviceId
45 | tvAndroidId.text = getDeviceInfo().androidId
46 | if(getDeviceInfo().gsfId.isNotEmpty()) {
47 | tvGsfId.text = getDeviceInfo().gsfId.toLong().toString(16)
48 | }
49 | tvGadId.text = getDeviceInfo().gadId
50 | tvMediaDrmId.text = getDeviceInfo().mediaDrmId
51 | tvVmdId.text = getDeviceInfo().vbMetaDigest
52 | val riskLabels = getRiskInfo().toString()
53 | if (TextUtils.isEmpty(riskLabels)) {
54 | tvRiskLabelsTitle.visibility = View.GONE
55 | tvRiskLabels.visibility = View.GONE
56 | } else {
57 | tvRiskLabelsTitle.visibility = View.VISIBLE
58 | tvRiskLabels.visibility = View.VISIBLE
59 | tvRiskLabels.text = riskLabels
60 | }
61 | }
62 | }
63 | }
64 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/build_info_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/detail_item_divider.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_back.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_battery.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_down_arrow.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_installed_app.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_internal_storage.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_phone.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_random_access_memory.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sensor_accelerometer.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
12 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sensor_all.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sensor_gravity.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sensor_gyroscope.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sensor_heartrate.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sensor_hinge.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sensor_humidity.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sensor_light.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sensor_magnetic_field.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sensor_motion.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sensor_next.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sensor_orientation.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sensor_pressure.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sensor_private.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sensor_proximity.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sensor_step.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sensor_temperature.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sensor_tilt.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_setting.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_up_arrow.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/item_card_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_app_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
17 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
22 |
23 |
24 |
36 |
37 |
45 |
46 |
60 |
61 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_splash.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
11 |
18 |
19 |
27 |
28 |
38 |
39 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_device_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
21 |
22 |
31 |
32 |
41 |
42 |
51 |
52 |
61 |
62 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/include_battery_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
22 |
23 |
32 |
33 |
42 |
43 |
51 |
52 |
63 |
64 |
75 |
76 |
84 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/include_build_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
23 |
24 |
35 |
36 |
46 |
47 |
48 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/include_installed_app_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
19 |
20 |
31 |
32 |
39 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/include_sensor_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
19 |
20 |
31 |
32 |
39 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/include_setting_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
29 |
30 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/include_title_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
11 |
17 |
18 |
19 |
34 |
35 |
36 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_app_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
18 |
28 |
29 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_details.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
21 |
22 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trustdecision/trustdevice-android/70c7f5454db1a95cb9e4cfaef766f90d831ce833/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trustdecision/trustdevice-android/70c7f5454db1a95cb9e4cfaef766f90d831ce833/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trustdecision/trustdevice-android/70c7f5454db1a95cb9e4cfaef766f90d831ce833/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trustdecision/trustdevice-android/70c7f5454db1a95cb9e4cfaef766f90d831ce833/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trustdecision/trustdevice-android/70c7f5454db1a95cb9e4cfaef766f90d831ce833/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-night/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFBB86FC
4 | #FF6200EE
5 | #FF3700B3
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 | #222222
11 | #1B1B1B
12 | @color/white
13 | @color/white
14 | #232323
15 |
--------------------------------------------------------------------------------
/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh-rCN/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | TrustDevice Fingerprint
4 | 设备ID
5 | Android ID
6 | 风险标签
7 | 谷歌服务框架ID
8 | 谷歌广告ID
9 | 数字版权管理ID
10 | vbmeta摘要
11 | 设置
12 | 内部存储
13 | 运行内存
14 | 电池
15 | 应用
16 | 传感器
17 | 应用列表
18 | 显示系统应用
19 | 隐藏系统应用
20 | 传感器列表
21 | 设备ID
22 | 设备信息
23 | 实时的运行内存
24 | 剩余
25 | 总容量
26 | 健康状况
27 | 温度
28 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFBB86FC
4 | #FF6200EE
5 | #FF3700B3
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 | #52B456
11 | #F5F5F5
12 | @color/white
13 | @color/black
14 | @color/black
15 | #F2F2F2
16 | #FF6C5C
17 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | TrustDevice Fingerprint
3 | Your Device ID
4 | Android ID
5 | Risk Labels
6 | GSF ID
7 | GAD ID
8 | Media DRM ID
9 | vbmetaDigest
10 | Settings
11 | Internal Storage
12 | Random Access Memory
13 | Battery
14 | Apps
15 | Sensors
16 | App list
17 | show system apps
18 | hide system apps
19 | Sensor list
20 | Device id
21 | Device info
22 | The state at the time of collection
23 | Free
24 | total capacity
25 | health
26 | temperature
27 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/backup_rules.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/data_extraction_rules.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
12 |
13 |
19 |
--------------------------------------------------------------------------------
/app/src/test/java/cn/tongdun/android/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package cn.tongdun.android;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | plugins {
3 | id 'com.android.application' version '8.3.2' apply false
4 | id 'com.android.library' version '8.3.2' apply false
5 | id 'org.jetbrains.kotlin.android' version '2.1.0' apply false
6 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Enables namespacing of each library's R class so that its R class includes only the
19 | # resources declared in the library itself and none from the library's dependencies,
20 | # thereby reducing the size of the R class for that library
21 | android.nonTransitiveRClass=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trustdecision/trustdevice-android/70c7f5454db1a95cb9e4cfaef766f90d831ce833/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 | @rem SPDX-License-Identifier: Apache-2.0
17 | @rem
18 |
19 | @if "%DEBUG%"=="" @echo off
20 | @rem ##########################################################################
21 | @rem
22 | @rem Gradle startup script for Windows
23 | @rem
24 | @rem ##########################################################################
25 |
26 | @rem Set local scope for the variables with windows NT shell
27 | if "%OS%"=="Windows_NT" setlocal
28 |
29 | set DIRNAME=%~dp0
30 | if "%DIRNAME%"=="" set DIRNAME=.
31 | @rem This is normally unused
32 | set APP_BASE_NAME=%~n0
33 | set APP_HOME=%DIRNAME%
34 |
35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
37 |
38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
40 |
41 | @rem Find java.exe
42 | if defined JAVA_HOME goto findJavaFromJavaHome
43 |
44 | set JAVA_EXE=java.exe
45 | %JAVA_EXE% -version >NUL 2>&1
46 | if %ERRORLEVEL% equ 0 goto execute
47 |
48 | echo. 1>&2
49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
50 | echo. 1>&2
51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
52 | echo location of your Java installation. 1>&2
53 |
54 | goto fail
55 |
56 | :findJavaFromJavaHome
57 | set JAVA_HOME=%JAVA_HOME:"=%
58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
59 |
60 | if exist "%JAVA_EXE%" goto execute
61 |
62 | echo. 1>&2
63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
64 | echo. 1>&2
65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
66 | echo location of your Java installation. 1>&2
67 |
68 | goto fail
69 |
70 | :execute
71 | @rem Setup the command line
72 |
73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
74 |
75 |
76 | @rem Execute Gradle
77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
78 |
79 | :end
80 | @rem End local scope for the variables with windows NT shell
81 | if %ERRORLEVEL% equ 0 goto mainEnd
82 |
83 | :fail
84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
85 | rem the _cmd.exe /c_ return code!
86 | set EXIT_CODE=%ERRORLEVEL%
87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
89 | exit /b %EXIT_CODE%
90 |
91 | :mainEnd
92 | if "%OS%"=="Windows_NT" endlocal
93 |
94 | :omega
95 |
--------------------------------------------------------------------------------
/jitpack.yml:
--------------------------------------------------------------------------------
1 | before_install:
2 | - yes | sdkmanager "cmake;3.22.1"
3 | - sdk install java 17.0.1-open
4 | - sdk use java 17.0.1-open
5 | install:
6 | - ./gradlew clean
7 | - ./gradlew trustdevice:assembleRelease
8 | - ./gradlew trustdevice:publishMavenJavaPublicationToMavenLocal
--------------------------------------------------------------------------------
/resources/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trustdecision/trustdevice-android/70c7f5454db1a95cb9e4cfaef766f90d831ce833/resources/demo.gif
--------------------------------------------------------------------------------
/resources/demo_2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trustdecision/trustdevice-android/70c7f5454db1a95cb9e4cfaef766f90d831ce833/resources/demo_2.gif
--------------------------------------------------------------------------------
/resources/logo_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trustdecision/trustdevice-android/70c7f5454db1a95cb9e4cfaef766f90d831ce833/resources/logo_dark.png
--------------------------------------------------------------------------------
/resources/logo_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trustdecision/trustdevice-android/70c7f5454db1a95cb9e4cfaef766f90d831ce833/resources/logo_light.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | gradlePluginPortal()
4 | google()
5 | mavenCentral()
6 | maven { url 'https://jitpack.io' }
7 | }
8 | }
9 | dependencyResolutionManagement {
10 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
11 | repositories {
12 | google()
13 | mavenCentral()
14 | maven { url 'https://jitpack.io' }
15 | }
16 | }
17 | rootProject.name = "trustdevice-android"
18 | include ':app'
19 | include ':trustdevice'
20 |
--------------------------------------------------------------------------------
/trustdevice/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /.cxx
--------------------------------------------------------------------------------
/trustdevice/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.library'
3 | id 'org.jetbrains.kotlin.android'
4 | id 'maven-publish'
5 | id 'signing'
6 | }
7 |
8 | group = 'com.github.trustdecision'
9 |
10 | afterEvaluate {
11 | publishing {
12 | publications {
13 | mavenJava(MavenPublication) {
14 | groupId = 'com.github.trustdecision'
15 | artifactId = "trustdevice-android"
16 | version = '1.0.0'
17 | artifact("$buildDir/outputs/aar/trustdevice-release.aar")
18 | }
19 | }
20 | }
21 | }
22 |
23 | android {
24 | namespace 'cn.tongdun.mobrisk'
25 | compileSdk 34
26 |
27 | ndkVersion "25.2.9519653"
28 | defaultConfig {
29 | minSdk 21
30 | targetSdk 34
31 |
32 | externalNativeBuild{
33 | cmake {
34 | abiFilters 'arm64-v8a','armeabi-v7a','x86', 'x86_64'
35 | }
36 | }
37 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
38 | consumerProguardFiles "consumer-rules.pro"
39 | }
40 |
41 | externalNativeBuild {
42 | cmake {
43 | path file('src/main/cpp/CMakeLists.txt')
44 | version '3.22.1'
45 | }
46 | }
47 | buildTypes {
48 | release {
49 | minifyEnabled true
50 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
51 | }
52 |
53 | }
54 | kotlinOptions {
55 | jvmTarget = '1.8'
56 | }
57 | }
58 |
59 | dependencies {
60 | implementation 'androidx.appcompat:appcompat:1.5.1'
61 | testImplementation 'junit:junit:4.13.2'
62 | androidTestImplementation 'androidx.test.ext:junit:1.1.4'
63 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
64 | }
--------------------------------------------------------------------------------
/trustdevice/consumer-rules.pro:
--------------------------------------------------------------------------------
1 | -keep class cn.tongdun.**{*;}
--------------------------------------------------------------------------------
/trustdevice/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | -verbose
4 | -dontusemixedcaseclassnames
5 |
6 | #-dontskipnonpubliclibraryclasses
7 | -dontoptimize
8 | -dontnote java.**, javax.**, org.**
9 | -dontwarn android.support.**
10 | #-overloadaggressively
11 |
12 | #-allowaccessmodification
13 |
14 | #-useuniqueclassmembernames
15 |
16 | -keepattributes SourceFile, LineNumberTable, *Annotation*, Exceptions, InnerClasses
17 |
18 | -keep class cn.tongdun.mobrisk.TDRisk {
19 | public static *;
20 | public *;
21 | }
22 | -keep class cn.tongdun.mobrisk.TDRisk$Builder {
23 | public static *;
24 | public *;
25 | }
26 | -keep class cn.tongdun.mobrisk.beans.DeviceInfo {
27 | private *;
28 | }
29 | -keep class cn.tongdun.mobrisk.providers.** {
30 | public *;
31 | }
32 | -keep interface cn.tongdun.mobrisk.TDRiskCallback {*;}
33 |
34 | -keepclasseswithmembernames class * {
35 | native ;
36 | }
--------------------------------------------------------------------------------
/trustdevice/src/androidTest/java/cn/tongdun/android/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package cn.tongdun.android;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
23 | assertEquals("cn.tongdun.android.test", appContext.getPackageName());
24 | }
25 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/trustdevice/src/main/cpp/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.22.1)
2 |
3 | project("trustdevice")
4 |
5 | add_library(
6 | trustdevice
7 |
8 | SHARED
9 |
10 | trustdevice.cpp
11 | trustdevice_utils.cpp
12 | trustdevice_risk.cpp)
13 |
14 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror")
15 |
16 | find_library(
17 | log-lib
18 | log)
19 |
20 | message("Current build type: ${CMAKE_BUILD_TYPE}")
21 | if(CMAKE_BUILD_TYPE MATCHES Debug)
22 | # Debug build settings
23 | add_definitions(-DDEBUG)
24 | message("Open log & keep symbols")
25 | else()
26 | # Release build settings
27 | add_definitions(-DNDEBUG)
28 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
29 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
30 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--exclude-libs,ALL")
31 | message("Close log & strip symbols")
32 | endif()
33 |
34 | target_link_libraries(
35 | trustdevice
36 | ${log-lib})
--------------------------------------------------------------------------------
/trustdevice/src/main/cpp/common/logger.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by collam on 2023/6/21.
3 | //
4 |
5 | #ifndef TRUSTDEVICE_ANDROID_LOGGER_H
6 | #define TRUSTDEVICE_ANDROID_LOGGER_H
7 |
8 | #include
9 | #include "../trustdevice_utils.h"
10 |
11 | #define TAG "TrustDevice_native"
12 |
13 | #ifdef DEBUG
14 |
15 | #define LOG(_level,...) do { \
16 | char logBuffer[4096]; \
17 | snprintf(logBuffer, sizeof(logBuffer), __VA_ARGS__); \
18 | __android_log_print(_level,TAG,"[%s] %s",get_current_thread_name(),logBuffer); \
19 | } while(false)
20 |
21 | #define LOGI(...) LOG(ANDROID_LOG_INFO,__VA_ARGS__)
22 | #define LOGV(...) LOG(ANDROID_LOG_VERBOSE,__VA_ARGS__)
23 | #define LOGD(...) LOG(ANDROID_LOG_DEBUG, __VA_ARGS__)
24 | #define LOGW(...) LOG(ANDROID_LOG_WARN,__VA_ARGS__)
25 | #else
26 | #define LOGI(...)
27 | #define LOGV(...)
28 | #define LOGD(...)
29 | #define LOGW(...)
30 | #endif
31 |
32 | #endif //TRUSTDEVICE_ANDROID_LOGGER_H
33 |
--------------------------------------------------------------------------------
/trustdevice/src/main/cpp/common/macro.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by collam on 2023/6/21.
3 | //
4 |
5 | #ifndef TRUSTDEVICE_ANDROID_MACRO_H
6 | #define TRUSTDEVICE_ANDROID_MACRO_H
7 |
8 | #ifdef __LP64__
9 | typedef unsigned long long operation_type;
10 | static unsigned long trampoline_code = 0xd61f020058000050;
11 | #else
12 | typedef unsigned long operation_type;
13 | static unsigned long trampoline_code = 0x58000050;
14 | #endif
15 |
16 | #endif //TRUSTDEVICE_ANDROID_MACRO_H
17 |
--------------------------------------------------------------------------------
/trustdevice/src/main/cpp/trustdevice.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "trustdevice_risk.h"
3 | #include "trustdevice_utils.h"
4 |
5 | // Define JNI methods to be registered
6 | static JNINativeMethod jniMethods[] = {
7 | {"call0", "()I", (void *) detect_debug},
8 | {"call1", "()Ljava/lang/String;", (void *) detect_hook},
9 | {"call2", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", (void *) get_property},
10 | {"call3", "()Z", (void *) detectMagiskByMount},
11 | {"call4", "(Ljava/lang/String;)Z", (void *) checkBinInEnv}
12 | };
13 |
14 | // Define JNI library registration function
15 | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *__unused) {
16 | JNIEnv *env = nullptr;
17 | jclass clazz = NULL;
18 |
19 | if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
20 | goto err_exit;
21 | }
22 |
23 | clazz = env->FindClass("cn/tongdun/mobrisk/core/tools/JNIHelper");
24 |
25 | if (clazz == nullptr) {
26 | goto err_exit;
27 | }
28 | if (env->RegisterNatives(clazz, jniMethods, sizeof(jniMethods) / sizeof(jniMethods[0])) < 0) {
29 | goto err_exit;
30 | }
31 | LOGD("JNI_OnLoad called!");
32 |
33 | return JNI_VERSION_1_6;
34 | err_exit:
35 | return JNI_ERR;
36 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/cpp/trustdevice_risk.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zuchangwu on 2023/4/10.
3 | //
4 |
5 | #include "trustdevice_risk.h"
6 |
7 | int readTracePid(const char *file_path) {
8 | int tracerPid = 0;
9 | std::ifstream status_file(file_path);
10 | if (!status_file) {
11 | return tracerPid;
12 | }
13 | std::string line;
14 | while (std::getline(status_file, line)) {
15 | if (line.find("TracerPid:") == 0) {
16 | tracerPid = std::stoi(line.substr(11));
17 | break;
18 | }
19 | }
20 | status_file.close();
21 | return tracerPid;
22 | }
23 |
24 | bool detectTracePid() {
25 | const char *status_path = "/proc/self/status";
26 | int tracerPid = readTracePid(status_path);
27 | if (tracerPid != 0) {
28 | return true;
29 | }
30 | return false;
31 | }
32 |
33 | bool detectTaskTracerPid() {
34 | pid_t pid = getpid();
35 | char buffer[512];
36 | const char *format = "/proc/%d/task/%d/status";
37 | std::sprintf(buffer, format, pid, pid);
38 | int tracerPid = readTracePid(buffer);
39 | if (tracerPid != 0) {
40 | return true;
41 | }
42 | return false;
43 | }
44 |
45 | jint detect_debug(JNIEnv *__unused, jobject __unused) {
46 | int result = 0;
47 | if (detectTracePid()) {
48 | result |= 0x1 << 1;
49 | }
50 | if (detectTaskTracerPid()) {
51 | result |= 0x1 << 2;
52 | }
53 | return static_cast(result);
54 | }
55 |
56 | size_t detect_frida(char *hook_method, const size_t max_length) {
57 | const char *libc_method_names[] = {"strcat", "fopen", "open", "read", "strcmp", "strstr", "fgets",
58 | "access", "ptrace", "__system_property_get"};
59 |
60 | #ifdef __LP64__
61 | const char *libc_so_path = "/system/lib64/libc.so";
62 | #else
63 | const char *libc_so_path = "/system/lib/libc.so";
64 | #endif
65 | void *handler = dlopen(libc_so_path, RTLD_NOW);
66 | if (!handler) {
67 | return 0;
68 | }
69 | for (const char *method_name: libc_method_names) {
70 | void *method_sym = dlsym(handler, method_name);
71 | if (method_sym == nullptr) {
72 | continue;
73 | }
74 | auto *bytecode = reinterpret_cast(method_sym);
75 | int access = mem_read_access_by_maps(bytecode, 16);
76 | if (access == 0) {
77 | continue;
78 | }
79 | operation_type operation = *bytecode;
80 | if (operation == trampoline_code) {
81 | size_t remaining_length = max_length - strlen(method_name);
82 | snprintf(hook_method + strlen(hook_method), remaining_length, "%s,", method_name);
83 | }
84 | }
85 | dlclose(handler);
86 | void *internal_method_names[] = {(void *) detect_debug, (void *) detectTaskTracerPid,
87 | (void *) detectTracePid, (void *) readTracePid, (void *) detect_hook,
88 | (void *) detect_frida};
89 | size_t internal_method_len = sizeof(internal_method_names) / sizeof(internal_method_names[0]);
90 | for (size_t i = 0; i < internal_method_len; ++i) {
91 | auto *bytecode = reinterpret_cast(internal_method_names[i]);
92 | int access = mem_read_access_by_maps(bytecode, 16);
93 | if (access == 0) {
94 | continue;
95 | }
96 | operation_type operation = *bytecode;
97 | if (operation == trampoline_code) {
98 | std::string str = std::to_string(i);
99 | size_t remaining_length = max_length - str.size();
100 | snprintf(hook_method + strlen(hook_method), remaining_length, "%zu,", i);
101 | }
102 | }
103 | size_t str_len = strlen(hook_method);
104 | if (str_len > 0 && hook_method[str_len - 1] == ',') {
105 | hook_method[str_len - 1] = '\0';
106 | }
107 | LOGD("hook methods: %s",hook_method);
108 | return str_len;
109 | }
110 |
111 | jstring detect_hook(JNIEnv *env, jobject __unused) {
112 | const size_t max_length = 512;
113 | char frida_hook_method[max_length] = {};
114 | detect_frida(frida_hook_method, max_length);
115 | return env->NewStringUTF(frida_hook_method);
116 | }
117 |
118 | jboolean detectMagiskByMount(__unused JNIEnv *env, jobject __unused) {
119 | const char *mounts_path = "/proc/self/mounts";
120 | const char *mountinfo_path = "/proc/self/mountinfo";
121 | const char *mountstats_path = "/proc/self/mountstats";
122 |
123 | struct stat mounts_stat;
124 | stat(mounts_path,&mounts_stat);
125 |
126 | struct stat mountinfo_stat;
127 | stat(mountinfo_path,&mountinfo_stat);
128 |
129 | struct stat mountstats_stat;
130 | stat(mountstats_path,&mountstats_stat);
131 |
132 | if (!((mounts_stat.st_mtime == mountinfo_stat.st_mtime) &&
133 | (mountinfo_stat.st_mtime == mountstats_stat.st_mtime))) {
134 | LOGD("detectMagiskByMount found abnormality in mounted files");
135 | return JNI_TRUE;
136 | }
137 |
138 | return JNI_FALSE;
139 | }
140 |
141 | jboolean checkBinInEnv(JNIEnv *env, jobject __unused klass,jstring binName) {
142 | char *sys_env = getenv("PATH");
143 | if(env == nullptr){
144 | return false;
145 | }
146 | const char *binNameChs = env->GetStringUTFChars(binName,nullptr);
147 | const size_t ENV_PATH_LEN = 64;
148 | char *curPath;
149 | char envItemPath[ENV_PATH_LEN] = {0};
150 | char *envPath = strdup(sys_env);
151 | bool accessible = false;
152 | if (envPath != nullptr) {
153 | curPath = strtok(envPath, ":");
154 | while (curPath != nullptr) {
155 | memset(envItemPath,'\0',ENV_PATH_LEN);
156 | snprintf(envItemPath, ENV_PATH_LEN, "%s/%s", curPath, binNameChs);
157 |
158 | int accessStatus = access(envItemPath,X_OK);
159 |
160 | LOGD("%s path: %s,bin file access status: %d",__FUNCTION__ ,envItemPath, accessStatus);
161 |
162 | if (accessStatus != -1) {
163 | accessible = true;
164 | break;
165 | }
166 | curPath = strtok(nullptr, ":");
167 | }
168 | free(envPath);
169 | }
170 |
171 | env->ReleaseStringUTFChars(binName,binNameChs);
172 |
173 | return accessible;
174 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/cpp/trustdevice_risk.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zuchangwu on 2023/4/10.
3 | //
4 |
5 | #ifndef TRUSTDEVICE_ANDROID_TRUSTDEVICE_RISK_H
6 | #define TRUSTDEVICE_ANDROID_TRUSTDEVICE_RISK_H
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | #include "trustdevice_utils.h"
19 | #include "common/macro.h"
20 | #include "common/logger.h"
21 |
22 | jint detect_debug(JNIEnv *env, jobject clazz);
23 | jstring detect_hook(JNIEnv *env, jobject clazz);
24 | jboolean detectMagiskByMount(JNIEnv *env, jobject __unused);
25 | jboolean checkBinInEnv(JNIEnv *env, jobject __unused,jstring binName);
26 | #endif //TRUSTDEVICE_ANDROID_TRUSTDEVICE_RISK_H
27 |
--------------------------------------------------------------------------------
/trustdevice/src/main/cpp/trustdevice_utils.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zuchangwu on 2023/4/7.
3 | //
4 |
5 | #include "trustdevice_utils.h"
6 |
7 |
8 | char *get_current_thread_name() {
9 | static char thread_name[256] = {0};
10 | memset(thread_name,'\0',256);
11 | prctl(PR_GET_NAME, (unsigned long)thread_name);
12 | return (char *)thread_name;
13 | }
14 |
15 | jstring get_property(JNIEnv *env, jobject __unused, jstring _key, jstring _default_value) {
16 | const char *c_key = env->GetStringUTFChars(_key, nullptr);
17 | char value[128] = "";
18 | int length = __system_property_get(c_key, value);
19 | if (length < 0) {
20 | return _default_value;
21 | }
22 | return env->NewStringUTF(value);
23 | }
24 |
25 | /**
26 | * Parse every step of the map, observe the permission part, it is no permission
27 | * 0: not accessible; 1: accessibles
28 | */
29 | bool mem_read_access_by_maps(void *read_addr, size_t len) {
30 | if(read_addr == nullptr)
31 | return false;
32 | #if defined(__LP64__)
33 | uint64_t addr = (uint64_t)read_addr;
34 | uint64_t start_addr = 0, end_addr = 0, last_addr = 0;
35 | #else
36 | uint32_t addr = (uint32_t)read_addr;
37 | uint32_t start_addr = 0, end_addr = 0, last_addr = 0;
38 | #endif
39 | char access = 0, buff[1024];
40 | FILE *fmap;
41 | fmap = fopen("/proc/self/maps", "r");
42 | if(!fmap){
43 | LOGW("open /proc/self/maps file failed!");
44 | return false;
45 | }
46 |
47 | while(fgets(buff, sizeof(buff)-1, fmap) != nullptr) {
48 | #if defined(__LP64__)
49 | sscanf(buff, "%lx-%lx %c", &start_addr, &end_addr, &access);
50 | #else
51 | sscanf(buff, "%x-%x %c", &start_addr, &end_addr, &access);
52 | #endif
53 | if((addr >= start_addr) && (addr <= end_addr)){
54 | if('r' != access){
55 | fclose(fmap);
56 | return false;
57 | }
58 |
59 | if((addr + len) < end_addr){
60 | fclose(fmap);
61 | return true;
62 | }else {
63 | last_addr = end_addr;
64 | len = len - (end_addr - addr);
65 | addr = last_addr;
66 | }
67 | }
68 | }
69 |
70 | fclose(fmap);
71 | return false;
72 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/cpp/trustdevice_utils.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zuchangwu on 2023/4/7.
3 | //
4 |
5 | #ifndef TRUSTDEVICE_ANDROID_TRUSTDEVICE_UTILS_H
6 | #define TRUSTDEVICE_ANDROID_TRUSTDEVICE_UTILS_H
7 |
8 | #include
9 | #include
10 | #include
11 | #include "common/logger.h"
12 |
13 | jstring get_property(JNIEnv *env, jobject clazz, jstring _key, jstring _default_value);
14 | bool mem_read_access_by_maps(void *read_addr, size_t len);
15 | char *get_current_thread_name();
16 |
17 | #endif //TRUSTDEVICE_ANDROID_TRUSTDEVICE_UTILS_H
18 |
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/TDRisk.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk
2 |
3 | import android.content.Context
4 | import androidx.lifecycle.ViewModelProvider.NewInstanceFactory.Companion.instance
5 | import cn.tongdun.mobrisk.core.FMCore
6 | import org.json.JSONObject
7 |
8 |
9 | /**
10 | * @description: fingerprint entry class
11 | * @author: wuzuchang
12 | * @date: 2023/5/12
13 | */
14 | object TDRisk {
15 |
16 | @JvmStatic
17 | fun init(context: Context) {
18 | val builder = Builder()
19 | initWithOptions(context, builder)
20 | }
21 |
22 | @JvmStatic
23 | fun initWithOptions(context: Context, builder: Builder) {
24 | FMCore.instance.init(context,builder.build())
25 | }
26 |
27 | @JvmStatic
28 | fun getBlackbox(): JSONObject {
29 | return FMCore.instance.getDeviceInfo()
30 | }
31 |
32 | class Builder {
33 | private var partnerCode: String? = null
34 | private var callback: TDRiskCallback? = null
35 | fun partner(partner: String): Builder {
36 | partnerCode = partner
37 | return this
38 | }
39 |
40 | fun callback(TDRiskCallback: TDRiskCallback): Builder {
41 | callback = TDRiskCallback
42 | return this
43 | }
44 |
45 | fun build(): TDRiskOption {
46 | val options = TDRiskOption()
47 | options.partnerCode = partnerCode
48 | options.callback = callback
49 | return options
50 | }
51 | }
52 |
53 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/TDRiskCallback.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk
2 |
3 | import org.json.JSONObject
4 |
5 | /**
6 | * @description: TDRisk Callback
7 | * @author: wuzuchang
8 | * @date: 2023/5/12
9 | */
10 | interface TDRiskCallback {
11 | fun onEvent(deviceInfo: JSONObject)
12 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/TDRiskOption.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk
2 |
3 | /**
4 | * @description: Option
5 | * @author: wuzuchang
6 | * @date: 2023/5/12
7 | */
8 | class TDRiskOption {
9 |
10 | var partnerCode : String? = null
11 | var callback: TDRiskCallback? = null
12 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/beans/DeviceInfo.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.beans
2 |
3 | import cn.tongdun.mobrisk.core.tools.Constants
4 |
5 | @Target(AnnotationTarget.FIELD)
6 | annotation class DisplayName(val value: String)
7 |
8 | /**
9 | * @description: Device info
10 | * @author: wuzuchang
11 | * @date: 2023/5/12
12 | */
13 | class DeviceInfo {
14 | var androidId: String? = null
15 | var gsfId: String? = null
16 | var mediaDrmId: String? = null
17 | var vbMetaDigest: String? = null
18 | var googleAdId: String? = null
19 | var model: String? = null
20 | var manufacturer: String? = null
21 | var androidVersion: String? = null
22 | var sdkVersion: String? = null
23 | var kernelVersion: String? = null
24 | var fingerprint: String? = null
25 | var hardware: String? = null
26 | var product: String? = null
27 | var brand: String? = null
28 | var display: String? = null
29 | var host: String? = null
30 | var batteryHealthStatus: String? = null
31 | var batteryStatus: String? = null
32 | var batteryLevel: String? = null
33 | var batteryTemp: String? = null
34 | var batteryTotalCapacity: String? = null
35 | var cpuProcessor: String? = null
36 | var cpuHardware: String? = null
37 | var coresCount: String? = null
38 | var abiType: String? = null
39 | var debug = 0
40 | var root = false
41 | var xposed = false
42 | var magisk = false
43 | var vpn = false
44 | var emulator = false
45 | @DisplayName(Constants.KEY_DEVICE_INFO_TAMPERED)
46 | var deviceInfoTampered = false
47 | var hook: String? = null
48 | var country: String? = null
49 | var language: String? = null
50 | var timezone: String? = null
51 | var totalMemory: String? = null
52 | var availableMemory: String? = null
53 | var totalStorage: String? = null
54 | var availableStorage: String? = null
55 | var appList: String? = null
56 | var systemAppList: String? = null
57 | var sensorsInfo: String? = null
58 | var adbEnabled: String? = null
59 | var developmentSettingEnabled: String? = null
60 | var httpProxy: String? = null
61 | var dataRoaming: String? = null
62 | var allowMockLocation: String? = null
63 | var accessibilityEnabled: String? = null
64 | var defaultInputMethod: String? = null
65 | var touchExplorationEnabled: String? = null
66 | var screenBrightness: String? = null
67 | var screenOffTimeout: String? = null
68 | var screenResolution: String? = null
69 | var screenInches = 0.0
70 | var filesAbsolutePath: String? = null
71 | var packageName: String? = null
72 | var harmonyOS = false
73 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/AdvertisingIdClient.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.collectors
2 |
3 | import android.content.ComponentName
4 | import android.content.Context
5 | import android.content.Intent
6 | import android.content.ServiceConnection
7 | import android.os.*
8 | import java.util.concurrent.LinkedBlockingQueue
9 |
10 | /**
11 | * @description: get google ad id
12 | * @author: wuzuchang
13 | * @date: 2023/6/5
14 | */
15 | object AdvertisingIdClient {
16 | @Throws(Exception::class)
17 | fun getId(context: Context): String? {
18 | if (Looper.getMainLooper() == Looper.myLooper()) {
19 | return "Cannot call in the main thread"
20 | }
21 | val pm = context.packageManager
22 | pm.getPackageInfo("com.android.vending", 0)
23 | val connection = AdvertisingConnection()
24 | val intent = Intent("com.google.android.gms.ads.identifier.service.START")
25 | intent.setPackage("com.google.android.gms")
26 | return if (context.bindService(intent, connection, Context.BIND_AUTO_CREATE)) {
27 | try {
28 | val adInterface = AdvertisingInterface(
29 | connection.binder
30 | )
31 | adInterface.id
32 | } finally {
33 | context.unbindService(connection)
34 | }
35 | } else ""
36 | }
37 |
38 | private class AdvertisingConnection : ServiceConnection {
39 | var retrieved = false
40 | private val queue = LinkedBlockingQueue(1)
41 | override fun onServiceConnected(name: ComponentName, service: IBinder) {
42 | try {
43 | queue.put(service)
44 | } catch (_: InterruptedException) {
45 | }
46 | }
47 |
48 | override fun onServiceDisconnected(name: ComponentName) {}
49 |
50 | @get:Throws(InterruptedException::class)
51 | val binder: IBinder
52 | get() {
53 | check(!retrieved)
54 | retrieved = true
55 | return queue.take()
56 | }
57 | }
58 |
59 | private class AdvertisingInterface(private val binder: IBinder) : IInterface {
60 | override fun asBinder(): IBinder {
61 | return binder
62 | }
63 |
64 | @get:Throws(RemoteException::class)
65 | val id: String?
66 | get() {
67 | val data = Parcel.obtain()
68 | val reply = Parcel.obtain()
69 | val id: String? = try {
70 | data.writeInterfaceToken("com.google.android.gms.ads.identifier.internal.IAdvertisingIdService")
71 | binder.transact(1, data, reply, 0)
72 | reply.readException()
73 | reply.readString()
74 | } finally {
75 | reply.recycle()
76 | data.recycle()
77 | }
78 | return id
79 | }
80 |
81 | @Throws(RemoteException::class)
82 | fun isLimitAdTrackingEnabled(paramBoolean: Boolean): Boolean {
83 | val data = Parcel.obtain()
84 | val reply = Parcel.obtain()
85 | val limitAdTracking: Boolean = try {
86 | data.writeInterfaceToken("com.google.android.gms.ads.identifier.internal.IAdvertisingIdService")
87 | data.writeInt(if (paramBoolean) 1 else 0)
88 | binder.transact(2, data, reply, 0)
89 | reply.readException()
90 | 0 != reply.readInt()
91 | } finally {
92 | reply.recycle()
93 | data.recycle()
94 | }
95 | return limitAdTracking
96 | }
97 | }
98 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/AppListCollector.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.collectors
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.pm.ApplicationInfo
5 | import android.content.pm.PackageInfo
6 | import android.content.pm.PackageManager
7 | import android.text.TextUtils
8 | import cn.tongdun.mobrisk.core.tools.executeSafe
9 |
10 | /**
11 | * @description: App List
12 | * @author: wuzuchang
13 | * @date: 2023/5/12
14 | */
15 |
16 | interface AppListDataInterface {
17 | fun getAppList(): String
18 | fun getSystemAppList(): String
19 | }
20 |
21 | @SuppressLint("QueryPermissionsNeeded")
22 | class AppListCollector(packageManager: PackageManager) : AppListDataInterface {
23 | private val appList: MutableList = ArrayList()
24 | private val systemAppList: MutableList = ArrayList()
25 |
26 | init {
27 | executeSafe {
28 | packageManager.getInstalledPackages(PackageManager.GET_ACTIVITIES)
29 | .filter {
30 | isSystemApp(it)
31 | }.map {
32 | appList.add(it.packageName)
33 | }
34 | packageManager.getInstalledPackages(PackageManager.GET_META_DATA).fold(
35 | Pair(systemAppList, appList)
36 | ) { (systemList, appList), packageInfo ->
37 | if (isSystemApp(packageInfo)) {
38 | systemList.add(packageInfo.packageName)
39 | } else {
40 | appList.add(packageInfo.packageName)
41 | }
42 | Pair(systemList, appList)
43 | }
44 | }
45 | }
46 |
47 | @SuppressLint("QueryPermissionsNeeded")
48 | override fun getAppList(): String {
49 | return TextUtils.join(",", appList)
50 | }
51 |
52 | override fun getSystemAppList(): String {
53 | return TextUtils.join(",", systemAppList)
54 | }
55 |
56 | private fun isSystemApp(packageInfo: PackageInfo): Boolean {
57 | val isSysApp =
58 | packageInfo.applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM == ApplicationInfo.FLAG_SYSTEM
59 | val isSysUpd =
60 | packageInfo.applicationInfo.flags and ApplicationInfo.FLAG_UPDATED_SYSTEM_APP == ApplicationInfo.FLAG_UPDATED_SYSTEM_APP
61 | return isSysApp || isSysUpd
62 | }
63 |
64 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/BatteryInfoCollector.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.collectors
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.Context
5 | import android.content.Intent
6 | import android.content.IntentFilter
7 | import android.os.BatteryManager
8 | import cn.tongdun.mobrisk.core.tools.executeSafe
9 |
10 | /**
11 | * @description: Battery Info
12 | * @author: wuzuchang
13 | * @date: 2023/5/12
14 | */
15 | interface BatteryInfoInterface {
16 | fun getBatteryHealth(): String
17 | fun getBatteryStatus(): String
18 | fun getBatteryLevel(): Int
19 | fun getBatteryTemp(): Int
20 | fun getBatteryTotalCapacity(): String
21 | }
22 |
23 | private const val POWER_PROFILE_CLASS_NAME = "com.android.internal.os.PowerProfile"
24 | private const val BATTERY_CAPACITY_METHOD_NAME = "getBatteryCapacity"
25 |
26 | class BatteryInfoCollector(
27 | private val context: Context
28 | ) : BatteryInfoInterface {
29 |
30 | private var batteryHealth: Int? = 0
31 | private var batteryStatus: Int? = 0
32 | private var batteryLevel: Int? = 0
33 | private var batteryTemp: Int? = 0
34 |
35 | init {
36 | val intent: Intent? = context.registerReceiver(
37 | null,
38 | IntentFilter(Intent.ACTION_BATTERY_CHANGED),
39 | "com.permission.broadcast.td",
40 | null
41 | )
42 | batteryHealth = intent?.getIntExtra(BatteryManager.EXTRA_HEALTH, -1)
43 | batteryStatus = intent?.getIntExtra(BatteryManager.EXTRA_STATUS, 0)
44 | batteryLevel = intent?.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
45 | batteryTemp = intent?.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0)
46 | }
47 |
48 | override fun getBatteryHealth(): String {
49 | val type: String = when (batteryHealth) {
50 | BatteryManager.BATTERY_HEALTH_GOOD -> "good"
51 | BatteryManager.BATTERY_HEALTH_OVERHEAT -> "overheat"
52 | BatteryManager.BATTERY_HEALTH_COLD -> "cold"
53 | BatteryManager.BATTERY_HEALTH_DEAD -> "dead"
54 | BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE -> "over voltage"
55 | BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE -> "unspecified failure"
56 | else -> "unknown"
57 | }
58 | return type
59 | }
60 |
61 | override fun getBatteryStatus(): String {
62 | val statusStr: String = when (batteryStatus) {
63 | BatteryManager.BATTERY_STATUS_CHARGING -> "charging"
64 | BatteryManager.BATTERY_STATUS_DISCHARGING -> "discharging"
65 | BatteryManager.BATTERY_STATUS_NOT_CHARGING -> "not charging"
66 | BatteryManager.BATTERY_STATUS_FULL -> "full"
67 | else -> "unknown"
68 | }
69 | return statusStr
70 | }
71 |
72 | override fun getBatteryLevel(): Int = batteryLevel?:0
73 |
74 | override fun getBatteryTemp(): Int = batteryTemp?:0
75 |
76 | @SuppressLint("PrivateApi")
77 | override fun getBatteryTotalCapacity(): String {
78 | return executeSafe({
79 | val mPowerProfile = Class.forName(POWER_PROFILE_CLASS_NAME)
80 | .getConstructor(Context::class.java)
81 | .newInstance(context)
82 | val batteryCapacity = Class.forName(POWER_PROFILE_CLASS_NAME)
83 | .getMethod(BATTERY_CAPACITY_METHOD_NAME)
84 | .invoke(mPowerProfile) as Double
85 |
86 | batteryCapacity.toString()
87 | }, "")
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/BuildInfoCollector.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.collectors
2 |
3 | import android.os.Build
4 | import cn.tongdun.mobrisk.core.tools.executeSafe
5 |
6 | /**
7 | * @description: Build Info
8 | * @author: wuzuchang
9 | * @date: 2023/5/15
10 | */
11 | interface BuildInfoInterface {
12 | fun getModel(): String
13 | fun getManufacturer(): String
14 | fun getAndroidVersion(): String
15 | fun getSdkVersion(): String
16 | fun getKernelVersion(): String
17 | fun getFingerprint(): String
18 | fun getHardware(): String
19 | fun getBrand(): String
20 | fun getHost(): String
21 | fun getDisplay(): String
22 | fun getProduct(): String
23 | }
24 |
25 | class BuildInfoCollector : BuildInfoInterface {
26 | override fun getModel(): String = executeSafe({ Build.MODEL }, "")
27 |
28 | override fun getManufacturer(): String = executeSafe({ Build.MANUFACTURER }, "")
29 |
30 | override fun getAndroidVersion(): String = executeSafe({ Build.VERSION.RELEASE }, "")
31 |
32 | override fun getSdkVersion(): String = executeSafe({ Build.VERSION.SDK_INT.toString() }, "")
33 |
34 | override fun getKernelVersion(): String =
35 | executeSafe({ System.getProperty("os.version") ?: "" }, "")
36 |
37 | override fun getFingerprint(): String = executeSafe({ Build.FINGERPRINT }, "")
38 |
39 | override fun getHardware(): String = executeSafe({ Build.HARDWARE }, "")
40 |
41 | override fun getBrand(): String = executeSafe({ Build.BRAND }, "")
42 |
43 | override fun getHost(): String = executeSafe({ Build.HOST }, "")
44 |
45 | override fun getDisplay(): String = executeSafe({ Build.DISPLAY }, "")
46 |
47 | override fun getProduct(): String = executeSafe({ Build.PRODUCT }, "")
48 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/CpuInfoCollector.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.collectors
2 |
3 | import android.os.Build
4 | import android.text.TextUtils
5 | import cn.tongdun.mobrisk.core.tools.FileUtils
6 | import cn.tongdun.mobrisk.core.tools.executeSafe
7 |
8 | /**
9 | * @description:Cpu Info
10 | * @author: wuzuchang
11 | * @date: 2023/5/15
12 | */
13 |
14 | interface CpuInfoInterface {
15 |
16 | fun getCpuProcessor(): String
17 |
18 | fun getCpuHardware(): String
19 |
20 | fun getAbiType(): String
21 |
22 | fun availableProcessors(): String
23 | }
24 |
25 | private val keyList = listOf("Processor", "Hardware")
26 | private const val CPU_INFO_PATH = "/proc/cpuinfo"
27 | private const val KEY_VALUE_DELIMITER = ": "
28 | private var mCpuInfo: Map = mutableMapOf()
29 |
30 | class CpuInfoCollector : CpuInfoInterface {
31 |
32 | init {
33 | executeSafe {
34 | mCpuInfo = FileUtils.readFileByKey(CPU_INFO_PATH, keyList, KEY_VALUE_DELIMITER)
35 | }
36 | }
37 |
38 | override fun getCpuProcessor(): String = executeSafe({ mCpuInfo[keyList[0]] ?: "" }, "")
39 |
40 | override fun getCpuHardware(): String = executeSafe({ mCpuInfo[keyList[1]] ?: "" }, "")
41 |
42 | override fun getAbiType(): String =
43 | executeSafe({ TextUtils.join(",", Build.SUPPORTED_ABIS) }, "")
44 |
45 | override fun availableProcessors(): String =
46 | executeSafe({ Runtime.getRuntime().availableProcessors().toString() }, "")
47 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/DebugInfoCollector.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.collectors
2 |
3 | import android.os.Debug
4 | import cn.tongdun.mobrisk.core.tools.JNIHelper
5 | import cn.tongdun.mobrisk.core.tools.executeSafe
6 |
7 | /**
8 | * @description:Debug info
9 | * @author: wuzuchang
10 | * @date: 2023/5/15
11 | */
12 | interface DebugInfoInterface {
13 | fun getDebug(): Int
14 | }
15 |
16 | class DebugInfoCollector : DebugInfoInterface {
17 | override fun getDebug(): Int {
18 | var result = 0
19 | if (Debug.isDebuggerConnected()) {
20 | result = result or 0x1
21 | }
22 | val ret: Int = executeSafe({ JNIHelper.call0() }, 0)
23 | result = result or ret
24 | return result
25 | }
26 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/DeviceBaseInfoCollector.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.collectors
2 |
3 | import android.content.Context
4 | import android.util.DisplayMetrics
5 | import android.view.WindowManager
6 | import cn.tongdun.mobrisk.core.tools.executeSafe
7 | import java.math.BigDecimal
8 | import java.math.RoundingMode
9 | import kotlin.math.pow
10 | import kotlin.math.sqrt
11 |
12 | /**
13 | * @description:Device Base Info
14 | * @author: wuzuchang
15 | * @date: 2023/5/15
16 | */
17 | interface DeviceBaseInfoInterface {
18 | fun getScreenResolution(): String
19 | fun getScreenInches(): Double
20 | fun getFilesAbsolutePath(): String
21 | fun getPackageName(): String
22 | fun isHarmonyOS(): Boolean
23 | }
24 |
25 | class DeviceBaseInfoCollector(private val context: Context) : DeviceBaseInfoInterface {
26 |
27 | private lateinit var mScreenResolution: String
28 | private var mScreenInches = 0.0
29 |
30 | init {
31 | executeSafe {
32 | val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
33 | val outMetrics = DisplayMetrics()
34 | windowManager.defaultDisplay.getRealMetrics(outMetrics)
35 | mScreenResolution = "${outMetrics.widthPixels}x${outMetrics.heightPixels}"
36 | val x = (outMetrics.widthPixels / outMetrics.xdpi).toDouble().pow(2.0);
37 | val y = (outMetrics.heightPixels / outMetrics.ydpi).toDouble().pow(2.0);
38 | val inches = sqrt(x + y);
39 | val bigDecimal = BigDecimal(inches);
40 | mScreenInches = bigDecimal.setScale(2, RoundingMode.HALF_UP).toDouble();
41 | }
42 | }
43 |
44 | override fun getScreenResolution(): String = mScreenResolution
45 |
46 | override fun getScreenInches(): Double = mScreenInches
47 |
48 | override fun getFilesAbsolutePath(): String = executeSafe({ context.filesDir.absolutePath }, "")
49 |
50 | override fun getPackageName(): String = executeSafe({ context.packageName }, "")
51 |
52 | override fun isHarmonyOS(): Boolean = executeSafe({
53 | val clz = Class.forName("com.huawei.system.BuildEx")
54 | val method = clz.getMethod("getOsBrand")
55 | val os = method.invoke(clz) as String
56 | "harmony".equals(os, ignoreCase = true)
57 | }, false)
58 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/DeviceIdCollector.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.collectors
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.ContentResolver
5 | import android.content.Context
6 | import android.media.MediaDrm
7 | import android.net.Uri
8 | import android.os.Build
9 | import android.provider.Settings
10 | import android.text.TextUtils
11 | import cn.tongdun.mobrisk.core.tools.Constants.SHA256
12 | import cn.tongdun.mobrisk.core.tools.JNIHelper
13 | import cn.tongdun.mobrisk.core.tools.executeSafe
14 | import cn.tongdun.mobrisk.core.tools.hash
15 | import java.util.*
16 |
17 |
18 | /**
19 | * @description:DeviceId
20 | * @author: wuzuchang
21 | * @date: 2023/5/15
22 | */
23 | interface DeviceIdInterface {
24 | fun getDeviceId(): String
25 | fun getAndroidId(): String?
26 | fun getMediaDrmId(): String?
27 | fun getGsfId(): String?
28 | fun getVbMetaDigest(): String?
29 | fun getGoogleAdid(context: Context): String
30 | }
31 |
32 | private const val URI_GSF_CONTENT_PROVIDER = "content://com.google.android.gsf.gservices"
33 | private const val GSF_ID_KEY = "android_id"
34 |
35 | class DeviceIdCollector(private val contentResolver: ContentResolver) : DeviceIdInterface {
36 |
37 | private var androidId: String? = null
38 | private var gsfId: String? = null
39 | private var mediaDrmId: String? = null
40 |
41 | override fun getDeviceId(): String {
42 | if (androidId == null) {
43 | androidId = getAndroidId()
44 | }
45 | if (!TextUtils.isEmpty(androidId)) {
46 | return androidId!!.hash(SHA256)
47 | }
48 | if (gsfId == null) {
49 | gsfId = getGsfId()
50 | }
51 | if (!TextUtils.isEmpty(gsfId)) {
52 | return gsfId!!.hash(SHA256)
53 | }
54 | if (mediaDrmId != null) {
55 | mediaDrmId = getMediaDrmId()
56 | }
57 | if (!TextUtils.isEmpty(mediaDrmId)) {
58 | return mediaDrmId!!
59 | }
60 | return getVbMetaDigest().hash(SHA256)
61 | }
62 |
63 | @SuppressLint("HardwareIds")
64 | override fun getAndroidId(): String? =
65 | if (androidId !== null) {
66 | androidId
67 | } else
68 | executeSafe({
69 | androidId = Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
70 | androidId
71 | }, null)
72 |
73 | override fun getMediaDrmId(): String? {
74 | if (mediaDrmId !== null) {
75 | return mediaDrmId
76 | }
77 | var drm: MediaDrm? = null
78 | try {
79 | val uuid = UUID(-0x121074568629b532L, -0x5c37d8232ae2de13L)
80 | drm = MediaDrm(uuid)
81 | val bytes = drm.getPropertyByteArray(MediaDrm.PROPERTY_DEVICE_UNIQUE_ID)
82 | mediaDrmId = bytes.hash(SHA256)
83 | } catch (ignored: Throwable) {
84 | } finally {
85 | if (drm != null) {
86 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
87 | drm.close()
88 | } else {
89 | drm.release()
90 | }
91 | }
92 | }
93 | return mediaDrmId
94 | }
95 |
96 | override fun getGsfId(): String? {
97 | if (gsfId !== null) {
98 | return gsfId
99 | }
100 | executeSafe {
101 | val uri = Uri.parse(URI_GSF_CONTENT_PROVIDER)
102 | val cursor = contentResolver.query(uri, null, null, arrayOf(GSF_ID_KEY), null)
103 | ?: return@executeSafe
104 | if (!cursor.moveToFirst() || cursor.columnCount < 2) {
105 | cursor.close()
106 | return@executeSafe
107 | }
108 | try {
109 | gsfId = cursor.getString(1)
110 | cursor.close()
111 | } catch (e: Throwable) {
112 | cursor.close()
113 | }
114 | }
115 | return gsfId
116 | }
117 |
118 | override fun getVbMetaDigest(): String =
119 | executeSafe({ JNIHelper.call2("ro.boot.vbmeta.digest", "") }, "")
120 |
121 |
122 | override fun getGoogleAdid(context: Context): String =
123 | executeSafe({ AdvertisingIdClient.getId(context).toString() }, "")
124 |
125 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/DeviceInfoTamperedCollector.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.collectors
2 |
3 | import android.content.Context
4 | import android.os.Build
5 |
6 | interface DeviceInfoTamperedInterface {
7 | fun tampered(context: Context?): Boolean
8 | }
9 |
10 | class DeviceInfoTamperedCollector : DeviceInfoTamperedInterface {
11 | override fun tampered(context: Context?): Boolean {
12 | return !Build.FINGERPRINT.contains(Build.BRAND,true)
13 | }
14 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/DevicePersonalizationInfoCollector.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.collectors
2 |
3 | import java.util.*
4 |
5 | /**
6 | * @description:Device Personalization Info
7 | * @author: wuzuchang
8 | * @date: 2023/5/15
9 | */
10 | interface DevicePersonalizationInfoInterface {
11 | fun getLocaleCountry(): String?
12 | fun getDefaultLanguage(): String?
13 | fun getTimezone(): String?
14 | }
15 |
16 | class DevicePersonalizationInfoCollector : DevicePersonalizationInfoInterface {
17 | override fun getLocaleCountry(): String? {
18 | return Locale.getDefault().country
19 | }
20 |
21 | override fun getDefaultLanguage(): String? {
22 | return Locale.getDefault().language
23 | }
24 |
25 | override fun getTimezone(): String? {
26 | return TimeZone.getDefault().displayName
27 | }
28 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/EmulatorCollector.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.collectors
2 |
3 | import android.os.Build
4 | import cn.tongdun.mobrisk.core.collectors.EmulatorCollector
5 | import java.io.File
6 | import java.util.*
7 |
8 | /**
9 | * @description:
10 | * @author: wuzuchang
11 | * @date: 2023/5/15
12 | */
13 | interface EmulatorInterface {
14 | fun detectEmulator(): Boolean
15 | }
16 |
17 | class EmulatorCollector : EmulatorInterface {
18 |
19 | private val QEMU_FILES = listOf(
20 | "/dev/socket/genyd",
21 | "/dev/socket/baseband_genyd",
22 | "/dev/socket/qemud",
23 | "/dev/qemu_pipe",
24 | "/system/bin/nox-prop",
25 | "/system/bin/ttVM-prop",
26 | "/system/bin/droid4x-prop",
27 | "/data/.bluestacks.prop",
28 | "/system/bin/androVM-prop",
29 | "/system/bin/microvirt-prop",
30 | "/system/lib/libdroid4x.so",
31 | "/system/bin/windroyed",
32 | "system/lib/libnoxspeedup.so",
33 | "/system/bin/duosconfig",
34 | "/system/etc/xxzs_prop.sh",
35 | "/system/etc/mumu-configs/device-prop-configs/mumu.config",
36 | "/system/priv-app/ldAppStore",
37 | "system/bin/ldinit",
38 | "/system/app/AntStore",
39 | "vmos.prop",
40 | "fstab.titan",
41 | "x8.prop",
42 | "/system/lib/libc_malloc_debug_qemu.so"
43 | )
44 |
45 | private fun checkDevice(): Boolean = "nox" == Build.DEVICE
46 | || "vbox86p" == Build.DEVICE
47 | || "vbox86tp" == Build.DEVICE
48 | || "appplayer" == Build.DEVICE
49 | || "droid4x" == Build.DEVICE
50 | || "vbox" == Build.DEVICE
51 | || "virtual" == Build.DEVICE
52 | || "andywin" == Build.DEVICE
53 | || "andyosx" == Build.DEVICE
54 | || "generic" == Build.DEVICE
55 | || "generic_x86" == Build.DEVICE
56 | || "emu64a" == Build.DEVICE
57 | || Build.DEVICE.lowercase(Locale.getDefault()).contains("mumu")
58 | || Build.DEVICE.lowercase(Locale.getDefault()).contains("zerofltezc")
59 |
60 | private fun checkModel(): Boolean = "vmos" == Build.MODEL
61 | || "duos" == Build.MODEL
62 | || "amiduos" == Build.MODEL
63 | || "noxw" == Build.MODEL
64 | || "genymotion" == Build.MODEL
65 | || "bluestacks" == Build.MODEL
66 | || "tiantian" == Build.MODEL
67 | || "windroy" == Build.MODEL
68 | || Build.MODEL.contains("google_sdk")
69 | || Build.MODEL.lowercase(Locale.getDefault()).contains("droid4x")
70 | || Build.MODEL.contains("Emulator")
71 | || Build.MODEL.contains("Android SDK built for x86")
72 | || Build.MODEL.contains("Subsystem for Android(TM)")
73 |
74 | private fun checkFingerprint(): Boolean = Build.FINGERPRINT.startsWith("generic")
75 | || Build.FINGERPRINT.contains("vbox")
76 |
77 | private fun checkProduct(): Boolean = "sdk" == Build.PRODUCT
78 | || "google_sdk" == Build.PRODUCT
79 | || "sdk_x86" == Build.PRODUCT
80 | || "vbox86p" == Build.PRODUCT
81 | || "vbox86tp" == Build.PRODUCT
82 | || "genymotion" == Build.PRODUCT
83 | || "bluestacks" == Build.PRODUCT
84 | || "droid4x" == Build.PRODUCT
85 | || "ttvm_hdragon" == Build.PRODUCT
86 | || "duos_native" == Build.PRODUCT
87 | || "duos" == Build.PRODUCT
88 | || "vbox" == Build.PRODUCT
89 | || "android_x86" == Build.PRODUCT
90 | || Build.PRODUCT.lowercase(Locale.getDefault()).contains("nox")
91 |
92 | private fun checkHardware(): Boolean = "goldfish" == Build.HARDWARE
93 | || "vbox86" == Build.HARDWARE
94 |
95 | private fun checkOtherBuildInfo(): Boolean = Build.MANUFACTURER.contains("Genymotion")
96 | || Build.BOARD.lowercase(Locale.getDefault()).contains("nox")
97 | || Build.BOOTLOADER.lowercase(Locale.getDefault()).contains("nox")
98 | || Build.HARDWARE.lowercase(Locale.getDefault()).contains("nox")
99 | || Build.SERIAL.lowercase(Locale.getDefault()).contains("nox")
100 | || Build.HOST.lowercase(Locale.getDefault()).startsWith("bliss-os")
101 | || Build.HOST.lowercase(Locale.getDefault()).contentEquals("G1-SNIPER-B7")
102 | || Build.HOST.lowercase(Locale.getDefault()).contentEquals("Build2")
103 | || (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
104 |
105 | override fun detectEmulator(): Boolean {
106 | var isEmulator = checkBuildInfo()
107 | if (!isEmulator) {
108 | isEmulator = checkFiles()
109 | }
110 | return isEmulator
111 | }
112 |
113 | private fun checkBuildInfo(): Boolean =
114 | checkDevice() ||
115 | checkModel() ||
116 | checkFingerprint() ||
117 | checkProduct() ||
118 | checkHardware() ||
119 | checkOtherBuildInfo()
120 |
121 | private fun checkFiles(): Boolean {
122 | for (filePtah in QEMU_FILES) {
123 | if (File(filePtah).exists()) {
124 | return true
125 | }
126 | }
127 | return false
128 | }
129 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/HookCollector.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.collectors
2 |
3 | import cn.tongdun.mobrisk.core.tools.JNIHelper
4 | import cn.tongdun.mobrisk.core.tools.executeSafe
5 |
6 | /**
7 | * @description:
8 | * @author: wuzuchang
9 | * @date: 2023/5/15
10 | */
11 | interface HookInterface {
12 | fun detectHook(): String
13 | }
14 |
15 | class HookCollector : HookInterface {
16 | override fun detectHook(): String = executeSafe({ JNIHelper.call1() }, "")
17 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/MagiskCollector.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.collectors
2 |
3 | import cn.tongdun.mobrisk.core.tools.EnvUtils
4 | import cn.tongdun.mobrisk.core.tools.JNIHelper
5 |
6 | /**
7 | * @description:
8 | * @author: wuzuchang
9 | * @date: 2023/5/15
10 | */
11 | interface MagiskInterface {
12 | fun detectMagisk(): Boolean
13 | }
14 |
15 | class MagiskCollector : MagiskInterface {
16 |
17 | override fun detectMagisk(): Boolean {
18 | return detectMagiskByFile() || detectMagiskByLastModified()
19 | }
20 |
21 | private fun detectMagiskByLastModified(): Boolean {
22 | return JNIHelper.call3()
23 | }
24 |
25 | private fun detectMagiskByFile(): Boolean {
26 | return EnvUtils.fileInEnv("magisk")
27 | }
28 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/MemoryInfoCollector.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.collectors
2 |
3 | import android.app.ActivityManager
4 | import android.os.Environment
5 | import android.os.StatFs
6 | import cn.tongdun.mobrisk.core.tools.executeSafe
7 |
8 | /**
9 | * @description:MemoryInfo
10 | * @author: wuzuchang
11 | * @date: 2023/5/15
12 | */
13 | interface MemoryInfoInterface {
14 | fun getTotalMemory(): Long
15 | fun getAvailableMemory(): Long
16 | fun getAvailableStorage(): Long
17 | fun getTotalStorage(): Long
18 | }
19 |
20 | class MemoryInfoCollector(private val activityManager: ActivityManager) : MemoryInfoInterface {
21 | private var mAvailableMemory = 0L
22 | private var mTotalMemory = 0L
23 | private var mAvailableStorage = 0L
24 | private var mTotalStorage = 0L
25 |
26 | init {
27 | executeSafe {
28 | val memoryInfo = ActivityManager.MemoryInfo()
29 | activityManager.getMemoryInfo(memoryInfo)
30 | mAvailableMemory = memoryInfo.availMem
31 | mTotalMemory = memoryInfo.totalMem
32 |
33 | val path = Environment.getDataDirectory()
34 | val stat = StatFs(path.path)
35 | val blockSize = stat.blockSizeLong
36 | val availableBlocks = stat.availableBlocksLong
37 | val totalBlocks = stat.blockCountLong
38 | mTotalStorage = totalBlocks * blockSize
39 | mAvailableStorage = availableBlocks * blockSize
40 | }
41 | }
42 |
43 | override fun getTotalMemory(): Long {
44 | return mTotalMemory
45 | }
46 |
47 | override fun getAvailableMemory(): Long {
48 | return mAvailableMemory
49 | }
50 |
51 | override fun getAvailableStorage(): Long {
52 | return mAvailableStorage
53 | }
54 |
55 | override fun getTotalStorage(): Long {
56 | return mTotalStorage
57 | }
58 |
59 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/RootCollector.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.collectors
2 |
3 | import cn.tongdun.mobrisk.core.tools.EnvUtils
4 | import cn.tongdun.mobrisk.core.tools.JNIHelper
5 |
6 | /**
7 | * @description:
8 | * @author: wuzuchang
9 | * @date: 2023/5/15
10 | */
11 |
12 | interface RootInterface {
13 | fun getRoot(): Boolean
14 | }
15 |
16 | class RootCollector : RootInterface {
17 | override fun getRoot(): Boolean {
18 | return EnvUtils.fileInEnv("su") || checkProp()
19 | }
20 |
21 | private fun checkProp() = JNIHelper.call2("ro.secure","1") == "0"
22 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/SensorsInfoCollector.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.collectors
2 |
3 | import android.hardware.Sensor
4 | import android.hardware.SensorManager
5 | import cn.tongdun.mobrisk.core.tools.executeSafe
6 | import org.json.JSONArray
7 | import org.json.JSONObject
8 |
9 | /**
10 | * @description:Sensors Info
11 | * @author: wuzuchang
12 | * @date: 2023/5/15
13 | */
14 | interface SensorsInfoInterface {
15 | fun getSensorList(): String
16 | }
17 |
18 | class SensorsInfoCollector(private val sensorManager: SensorManager) : SensorsInfoInterface {
19 | override fun getSensorList(): String {
20 | val sensorArray = JSONArray()
21 | executeSafe {
22 | val sensorList: List = sensorManager.getSensorList(Sensor.TYPE_ALL)
23 | for (i in sensorList.indices) {
24 | val sensor = sensorList[i]
25 | val sensorInfo = JSONObject()
26 | sensorInfo.put("name", sensor.name)
27 | sensorInfo.put("vendor", sensor.vendor)
28 | sensorInfo.put("type", sensor.type)
29 | sensorArray.put(i, sensorInfo)
30 | }
31 | }
32 | return sensorArray.toString()
33 | }
34 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/SettingInfoCollector.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.collectors
2 |
3 | import android.content.ContentResolver
4 | import android.provider.Settings
5 | import cn.tongdun.mobrisk.core.tools.executeSafe
6 |
7 | /**
8 | * @description:Setting Info
9 | * @author: wuzuchang
10 | * @date: 2023/5/15
11 | */
12 | interface SettingInfoInterface {
13 | fun getAdbEnabled(): String
14 | fun getDevelopmentSettingEnabled(): String
15 | fun getHttpProxy(): String
16 | fun getDataRoaming(): String
17 | fun getAllowMockLocation(): String
18 | fun getAccessibilityEnabled(): String
19 | fun getDefaultInputMethod(): String
20 | fun getTouchExplorationEnabled(): String
21 | fun getScreenBrightness(): String
22 | fun getScreenOffTimeout(): String
23 | }
24 |
25 | class SettingInfoCollector(private val contentResolver: ContentResolver) : SettingInfoInterface {
26 |
27 | override fun getAdbEnabled(): String = extractGlobalSettingsParam(Settings.Global.ADB_ENABLED)
28 |
29 | override fun getDevelopmentSettingEnabled(): String =
30 | extractGlobalSettingsParam(Settings.Global.DEVELOPMENT_SETTINGS_ENABLED)
31 |
32 | override fun getHttpProxy(): String = extractGlobalSettingsParam(Settings.Global.HTTP_PROXY)
33 |
34 | override fun getDataRoaming(): String = extractGlobalSettingsParam(Settings.Global.DATA_ROAMING)
35 |
36 | override fun getAllowMockLocation(): String =
37 | extractSecureSettingsParam(Settings.Secure.ALLOW_MOCK_LOCATION)
38 |
39 | override fun getAccessibilityEnabled(): String =
40 | extractSecureSettingsParam(Settings.Secure.ACCESSIBILITY_ENABLED)
41 |
42 | override fun getDefaultInputMethod(): String =
43 | extractSecureSettingsParam(Settings.Secure.DEFAULT_INPUT_METHOD)
44 |
45 | override fun getTouchExplorationEnabled(): String =
46 | extractSecureSettingsParam(Settings.Secure.TOUCH_EXPLORATION_ENABLED)
47 |
48 | override fun getScreenBrightness(): String =
49 | extractSystemSettingsParam(Settings.System.SCREEN_BRIGHTNESS)
50 |
51 | override fun getScreenOffTimeout(): String =
52 | extractSystemSettingsParam(Settings.System.SCREEN_OFF_TIMEOUT)
53 |
54 | private fun extractGlobalSettingsParam(key: String): String =
55 | executeSafe({ Settings.Global.getString(contentResolver, key) }, "")
56 |
57 | private fun extractSecureSettingsParam(key: String): String =
58 | executeSafe({ Settings.Secure.getString(contentResolver, key) }, "")
59 |
60 | private fun extractSystemSettingsParam(key: String): String =
61 | executeSafe({ Settings.System.getString(contentResolver, key) }, "")
62 |
63 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/VpnCollector.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.collectors
2 |
3 | import android.content.Context
4 | import cn.tongdun.mobrisk.core.tools.NetworkUtils
5 |
6 |
7 | interface VpnInterface {
8 | fun detectVpn(context:Context?): Boolean
9 | }
10 |
11 | class VpnCollector : VpnInterface {
12 | override fun detectVpn(context:Context?): Boolean {
13 | return NetworkUtils.contain(context,NetworkUtils.TYPE_VPN)
14 | }
15 |
16 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/XposedCollector.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.collectors
2 |
3 | /**
4 | * @description:
5 | * @author: wuzuchang
6 | * @date: 2023/5/15
7 | */
8 | interface XposedInterface {
9 | fun findXposed(): Boolean
10 | }
11 |
12 | class XposedCollector : XposedInterface {
13 | override fun findXposed(): Boolean {
14 | val xposedClasses = arrayOf(
15 | "de.robv.android.xposed.XposedBridge",
16 | "de.robv.android.xposed.IXposedHookLoadPackage",
17 | "de.robv.android.xposed.DexposedBridge"
18 | )
19 | for (className in xposedClasses) {
20 | try {
21 | Class.forName(className, true, ClassLoader.getSystemClassLoader())
22 | return true
23 | } catch (ignore: Exception) {
24 | }
25 | }
26 | return false
27 | }
28 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/tools/Constants.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.tools
2 |
3 | /**
4 | * @description: Constants
5 | * @author: wuzuchang
6 | * @date: 2023/5/12
7 | */
8 | object Constants {
9 | const val KEY_DEVICE_ID = "device_id"
10 | const val KEY_DEVICE_RISK_LABEL = "device_risk_label"
11 | const val KEY_DEVICE_DETAIL = "device_detail"
12 | const val KEY_ANDROID_ID = "androidId"
13 | const val KEY_GSF_ID = "gsfId"
14 | const val KEY_GAD_ID = "googleAdId"
15 | const val KEY_MEDIA_DRM_ID = "mediaDrmId"
16 | const val KEY_VB_META_DIGEST = "vbMetaDigest"
17 | const val KEY_MODEL = "model"
18 | const val KEY_MANUFACTURER = "manufacturer"
19 | const val KEY_ANDROID_VERSION = "androidVersion"
20 | const val KEY_SDK_VERSION = "sdkVersion"
21 | const val KEY_KERNEL_VERSION = "kernelVersion"
22 | const val KEY_FINGERPRINT = "fingerprint"
23 | const val KEY_HARDWARE = "HARDWARE"
24 | const val KEY_DISPLAY = "display"
25 | const val KEY_HOST = "host"
26 | const val KEY_BRAND = "brand"
27 | const val KEY_PRODUCT = "product"
28 | const val KEY_BATTERY_HEALTH_STATUS = "batteryHealthStatus"
29 | const val KEY_BATTERY_STATUS = "batteryStatus"
30 | const val KEY_BATTERY_LEVEL = "batteryLevel"
31 | const val KEY_BATTERY_TEMP = "batteryTemp"
32 | const val KEY_BATTERY_TOTAL_CAPACITY = "batteryTotalCapacity"
33 | const val KEY_CPU_PROCESSOR = "cpuProcessor"
34 | const val KEY_CPU_HARDWARE = "cpuHardware"
35 | const val KEY_CORES_COUNT = "coresCount"
36 | const val KEY_ABI_TYPE = "abiType"
37 |
38 | // risk label
39 | const val KEY_DEBUG = "debug"
40 | const val KEY_MULTIPLE = "multiple"
41 | const val KEY_ROOT = "root"
42 | const val KEY_XPOSED = "xposed"
43 | const val KEY_MAGISK = "magisk"
44 | const val KEY_EMULATOR = "emulator"
45 | const val KEY_HOOK = "hook"
46 | const val KEY_VPN = "vpn"
47 | const val KEY_DEVICE_INFO_TAMPERED = "device_info_tampered"
48 |
49 | const val KEY_COUNTRY = "country"
50 | const val KEY_LANGUAGE = "language"
51 | const val KEY_TIMEZONE = "timezone"
52 | const val KEY_TOTAL_MEMORY = "totalMemory"
53 | const val KEY_AVAILABLE_MEMORY = "availableMemory"
54 | const val KEY_TOTAL_STORAGE = "totalStorage"
55 | const val KEY_AVAILABLE_STORAGE = "availableStorage"
56 | const val KEY_APP_LIST = "appList"
57 | const val KEY_SYSTEM_APP_LIST = "systemAppList"
58 | const val KEY_SENSORS_INFO = "sensorsInfo"
59 | const val KEY_ADB_ENABLED = "adbEnabled"
60 | const val KEY_DEVELOPMENT_SETTING_ENABLED = "developmentSettingEnabled"
61 | const val KEY_HTTP_PROXY = "httpProxy"
62 | const val KEY_DATA_ROAMING = "dataRoaming"
63 | const val KEY_ALLOW_MOCK_LOCATION = "allowMockLocation"
64 | const val KEY_ACCESSIBILITY_ENABLED = "accessibilityEnabled"
65 | const val KEY_DEFAULT_INPUTMETHOD = "defaultInputMethod"
66 | const val KEY_TOUCH_EXPLORATION_ENABLED = "touchExplorationEnabled"
67 | const val KEY_SCREEN_BRIGHTNESS = "screenBrightness"
68 | const val KEY_SCREEN_OFF_TIMEOUT = "screenOffTimeout"
69 | const val KEY_SCREEN_RESOLUTION = "screenResolution"
70 | const val KEY_SCREEN_INCHES = "screenInches"
71 | const val KEY_FILES_ABSOLUTE_PATH = "filesAbsolutePath"
72 | const val KEY_PACKAGE_NAME = "packageName"
73 |
74 | const val SHA256 = "SHA-256"
75 |
76 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/tools/DeviceInfoUtils.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.tools
2 |
3 | import cn.tongdun.mobrisk.beans.DeviceInfo
4 | import cn.tongdun.mobrisk.beans.DisplayName
5 | import org.json.JSONObject
6 | import java.io.File
7 |
8 | /**
9 | * @description: DeviceInfoUtils
10 | * @author: wuzuchang
11 | * @date: 2023/5/12
12 | */
13 |
14 | object DeviceInfoUtils {
15 | fun format(deviceId: String, deviceInfo: DeviceInfo): JSONObject {
16 | val result = JSONObject()
17 | val detail = JSONObject()
18 | val fields = deviceInfo.javaClass.declaredFields
19 | for (field in fields) {
20 | executeSafe {
21 | field.isAccessible = true
22 | var key = field.name
23 | for (annotation in field.declaredAnnotations) {
24 | if(annotation is DisplayName) {
25 | key = annotation.value
26 | break
27 | }
28 | }
29 | val value = field.get(deviceInfo)
30 | detail.put(key, value?.toString())
31 | }
32 | }
33 | executeSafe {
34 | result.put(Constants.KEY_DEVICE_ID, deviceId)
35 | result.put(Constants.KEY_DEVICE_RISK_LABEL, deviceRisk(detail))
36 | result.put(Constants.KEY_DEVICE_DETAIL, detail)
37 | }
38 | return result
39 | }
40 |
41 | private fun deviceRisk(data: JSONObject): JSONObject {
42 | val risk = JSONObject()
43 | executeSafe {
44 | risk.put(Constants.KEY_ROOT, data.optString(Constants.KEY_ROOT))
45 | risk.put(Constants.KEY_DEBUG, (data.optInt(Constants.KEY_DEBUG)>0).toString())
46 | risk.put(Constants.KEY_MULTIPLE, getMultiple(data))
47 | risk.put(Constants.KEY_XPOSED, data.optString(Constants.KEY_XPOSED))
48 | risk.put(Constants.KEY_MAGISK, data.optString(Constants.KEY_MAGISK))
49 | risk.put(Constants.KEY_HOOK, getHookStatus(data))
50 | risk.put(Constants.KEY_EMULATOR, getEmulatorStatus(data))
51 | risk.put(Constants.KEY_VPN, getVpnStatus(data))
52 | risk.put(Constants.KEY_DEVICE_INFO_TAMPERED, getDeviceInfoTamperedStatus(data))
53 | }
54 | return risk
55 | }
56 |
57 | private fun getMultiple(data: JSONObject): String {
58 | val filePath = data.optString(Constants.KEY_FILES_ABSOLUTE_PATH)
59 | val packageName = data.optString(Constants.KEY_PACKAGE_NAME)
60 | val filePaths = filePath.split(packageName.toRegex()).dropLastWhile { it.isEmpty() }
61 | .toTypedArray()
62 | if (filePaths.isEmpty()) {
63 | return "false"
64 | }
65 | val dir = filePaths[0]
66 | var riskLength = 3
67 | if (dir.startsWith(File.separator)) {
68 | riskLength = 4
69 | }
70 | val dirs = dir.split(File.separator.toRegex()).dropLastWhile { it.isEmpty() }
71 | .toTypedArray()
72 | if (dirs.size > riskLength) {
73 | return "true"
74 | }
75 | return if ("0" != dirs[dirs.size - 1]) {
76 | "true"
77 | } else "false"
78 | }
79 |
80 | private fun getHookStatus(data: JSONObject): String {
81 | return if (data.optString(Constants.KEY_HOOK).isEmpty()) "false" else "true"
82 | }
83 |
84 | private fun getEmulatorStatus(data: JSONObject): String {
85 | return data.optString(Constants.KEY_EMULATOR)
86 | }
87 |
88 | private fun getVpnStatus(data: JSONObject): String {
89 | return data.optString(Constants.KEY_VPN)
90 | }
91 |
92 | private fun getDeviceInfoTamperedStatus(data: JSONObject): String {
93 | return data.optString(Constants.KEY_DEVICE_INFO_TAMPERED)
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/tools/EnvUtils.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.tools
2 |
3 | import android.text.TextUtils
4 | import java.io.File
5 |
6 | /**
7 | * @description:
8 | * @author: wuzuchang
9 | * @date: 2023/5/12
10 | */
11 | object EnvUtils {
12 | fun fileInEnv(fileName: String) = JNIHelper.call4(fileName)
13 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/tools/ExceptionSafeExecutor.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.tools
2 |
3 | import java.lang.Exception
4 |
5 | fun executeSafe(code: () -> T) {
6 | try {
7 | code()
8 | } catch (_: Exception) {
9 | }
10 | }
11 |
12 | fun executeSafe(code: () -> T, defaultValue: T): T {
13 | return try {
14 | code()
15 | } catch (exception: Exception) {
16 | defaultValue
17 | }
18 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/tools/FileUtils.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.tools
2 |
3 | import java.io.*
4 | import java.nio.charset.StandardCharsets
5 |
6 | /**
7 | * @description:
8 | * @author: wuzuchang
9 | * @date: 2023/5/12
10 | */
11 | object FileUtils {
12 | fun readFileByKey(fileName: String, keys: List, sep: String): Map {
13 | val info: MutableMap = mutableMapOf()
14 | val file = File(fileName)
15 | if (!file.exists()) {
16 | return info
17 | }
18 | file.readLines().forEach { line->
19 | if (line.isEmpty()) {
20 | return@forEach
21 | }
22 | val params: List = line.splitNonRegex(sep)
23 | var paramName = ""
24 | if (params.isNotEmpty() && params[0].trim().also {
25 | paramName = it
26 | }.isNotEmpty()) {
27 | if (keys.contains(paramName)) {
28 | if (params.size > 1) {
29 | info[paramName] = params[1].trim()
30 | }
31 | }
32 | }
33 | }
34 | return info
35 | }
36 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/tools/JNIHelper.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.tools
2 |
3 | import androidx.annotation.Keep
4 |
5 | /**
6 | * @description:
7 | * @author: wuzuchang
8 | * @date: 2023/5/12
9 | */
10 | @Keep
11 | object JNIHelper {
12 | //detect debug
13 | external fun call0(): Int
14 | //detect hook
15 | external fun call1(): String
16 | //get property
17 | external fun call2(key: String, defaultValue: String): String
18 | //mount files time compare
19 | external fun call3(): Boolean
20 | //check bin on environment variables
21 | external fun call4(binName: String): Boolean
22 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/tools/Logger.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.tools
2 |
3 | import android.util.Log
4 |
5 | /**
6 | * @description:
7 | * @author: wuzuchang
8 | * @date: 2023/5/12
9 | */
10 | object Logger {
11 | private const val LOG_TAG = "TrustDevice"
12 |
13 | fun d(message: String) {
14 | Log.d(LOG_TAG, message)
15 | }
16 |
17 | fun e(message: String) {
18 | Log.e(LOG_TAG, message)
19 | }
20 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/tools/NetworkUtils.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.tools
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.Context
5 | import android.net.ConnectivityManager
6 |
7 | object NetworkUtils {
8 | const val TYPE_UNKNOWN = 0
9 | const val TYPE_MOBILE = 1
10 | const val TYPE_WIFI = 2
11 | const val TYPE_VPN = 3
12 | const val TYPE_ETHERNET = 4
13 |
14 | fun contain(context: Context?,type: Int):Boolean {
15 | return getNetworkTypes(context).contains(type)
16 | }
17 |
18 | @SuppressLint("MissingPermission")
19 | fun getNetworkTypes(context: Context?): List {
20 |
21 | val list = ArrayList()
22 | if (null == context) {
23 | return list
24 | }
25 | val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
26 | try {
27 | val networks = cm.allNetworks
28 | if (networks.isEmpty()) {
29 | return list
30 | }
31 |
32 | for (network in networks) {
33 | var networkInfo = cm.getNetworkInfo(network)
34 | list.add(when(networkInfo?.type) {
35 | ConnectivityManager.TYPE_MOBILE -> TYPE_MOBILE
36 | ConnectivityManager.TYPE_WIFI -> TYPE_WIFI
37 | ConnectivityManager.TYPE_ETHERNET -> TYPE_ETHERNET
38 | ConnectivityManager.TYPE_VPN -> TYPE_VPN
39 | else -> {
40 | TYPE_UNKNOWN
41 | }
42 | })
43 |
44 | }
45 |
46 | } catch (ignored: Throwable) {
47 | }
48 | return list
49 | }
50 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/core/tools/StringUtils.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.core.tools
2 |
3 | import java.nio.charset.StandardCharsets
4 | import java.security.MessageDigest
5 |
6 | /**
7 | * @description:
8 | * @author: wuzuchang
9 | * @date: 2023/5/15
10 | */
11 |
12 | fun String.hash(algorithm: String): String {
13 | return executeSafe({
14 | val md = MessageDigest.getInstance(algorithm)
15 | md.update(this.toByteArray(StandardCharsets.UTF_8))
16 | md.digest().toUppercaseHexString()
17 | }, "")
18 | }
19 |
20 | fun String.splitNonRegex(delimiter: String): List {
21 | val list: MutableList = mutableListOf()
22 | var input = this
23 | if (input.isEmpty()) {
24 | return list
25 | }
26 | if (delimiter.isEmpty()) {
27 | list.add(input)
28 | return list
29 | }
30 | if (input == delimiter) {
31 | return list
32 | }
33 | while (true) {
34 | val index: Int = input.indexOf(delimiter)
35 | if (index == -1) {
36 | if (input.isNotEmpty()) {
37 | list.add(input)
38 | }
39 | return list
40 | }
41 | if (index != 0) {
42 | list.add(input.substring(0, index))
43 | }
44 | input = input.substring(index + delimiter.length)
45 | }
46 | }
47 |
48 | fun ByteArray.hash(algorithm: String): String {
49 | return executeSafe({
50 | val md = MessageDigest.getInstance(algorithm)
51 | md.update(this)
52 | md.digest().toUppercaseHexString()
53 | }, "")
54 | }
55 |
56 | fun ByteArray.toUppercaseHexString(): String {
57 | val hex = StringBuilder()
58 | // Iterating through each byte in the array
59 | for (i in this) {
60 | hex.append(String.format("%02X", i))
61 | }
62 | return hex.toString()
63 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/AppListsRawData.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.providers
2 |
3 |
4 | /**
5 | * @description:
6 | * @author: wuzuchang
7 | * @date: 2023/5/15
8 | */
9 | data class AppListsRawData(val appList: String,
10 | val systemAppList: String) {
11 |
12 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/BatteryInfoRawData.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.providers
2 |
3 | /**
4 | * @description:BatteryInfoRawData
5 | * @author: wuzuchang
6 | * @date: 2023/5/15
7 | */
8 | data class BatteryInfoRawData(
9 | val health: String,
10 | val status: String,
11 | val temp: Int,
12 | val level: Int,
13 | val totalCapacity: String
14 | )
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/BuildInfoRawData.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.providers
2 |
3 | import android.util.Pair
4 |
5 | /**
6 | * @description:
7 | * @author: wuzuchang
8 | * @date: 2023/5/15
9 | */
10 | data class BuildInfoRawData(
11 | val model: String,
12 | val brand: String,
13 | val manufacturer: String,
14 | val androidVersion: String,
15 | val sdkVersion: String,
16 | val kernelVersion: String,
17 | val fingerprint: String,
18 | val host: String,
19 | val screenResolution: String,
20 | val screenInches: String,
21 | val screenBrightness: String,
22 | val screenOffTimeout: String
23 | ) {
24 | fun getRawData(): List> = mutableListOf>().apply {
25 | add(Pair("model", model))
26 | add(Pair("brand", brand))
27 | add(Pair("manufacturer", manufacturer))
28 | add(Pair("android version", androidVersion))
29 | add(Pair("sdk version", sdkVersion))
30 | add(Pair("kernel version", kernelVersion))
31 | add(Pair("fingerprint", fingerprint))
32 | add(Pair("host", host))
33 | add(Pair("screen resolution", screenResolution))
34 | add(Pair("screen inches", screenInches))
35 | add(Pair("screen brightness", screenBrightness))
36 | }
37 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/CpuInfoRawData.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.providers
2 |
3 | import android.util.Pair
4 |
5 | /**
6 | * @description:CpuInfoRawData
7 | * @author: wuzuchang
8 | * @date: 2023/5/15
9 | */
10 | data class CpuInfoRawData(
11 | val cpuHardware: String,
12 | val cpuProcessor: String,
13 | val abiType: String,
14 | val coresCount: String
15 | ) {
16 | fun getRawData(): List> = mutableListOf>().apply {
17 | add(Pair("hardware", cpuHardware))
18 | add(Pair("processor", cpuProcessor))
19 | add(Pair("abi type", abiType))
20 | add(Pair("cores count", coresCount))
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/DeviceIdRawData.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.providers
2 |
3 | /**
4 | * @description:DeviceIdRawData
5 | * @author: wuzuchang
6 | * @date: 2023/5/16
7 | */
8 | data class DeviceIdRawData(
9 | val deviceId: String,
10 | val androidId: String,
11 | val gsfId: String,
12 | val gadId: String,
13 | val mediaDrmId: String,
14 | val vbMetaDigest: String
15 | )
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/DeviceInfoProvider.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.providers
2 |
3 | import cn.tongdun.mobrisk.core.tools.Constants
4 | import org.json.JSONObject
5 |
6 | /**
7 | * @description:DeviceInfoProvider
8 | * @author: wuzuchang
9 | * @date: 2023/5/15
10 | */
11 |
12 | class DeviceInfoProvider(private val deviceJson: JSONObject) {
13 | private var deviceDetail: JSONObject =
14 | deviceJson.optJSONObject(Constants.KEY_DEVICE_DETAIL) ?: JSONObject()
15 | private var riskLabel: JSONObject =
16 | deviceJson.optJSONObject(Constants.KEY_DEVICE_RISK_LABEL) ?: JSONObject()
17 |
18 | fun getDeviceInfo(): DeviceIdRawData = DeviceIdRawData(
19 | deviceJson.optString(Constants.KEY_DEVICE_ID),
20 | deviceDetail.optString(Constants.KEY_ANDROID_ID),
21 | deviceDetail.optString(Constants.KEY_GSF_ID),
22 | deviceDetail.optString(Constants.KEY_GAD_ID),
23 | deviceDetail.optString(Constants.KEY_MEDIA_DRM_ID),
24 | deviceDetail.optString(Constants.KEY_VB_META_DIGEST)
25 | )
26 |
27 | fun getRiskInfo(): RiskInfoRawData = RiskInfoRawData(
28 | riskLabel.optBoolean(Constants.KEY_ROOT),
29 | riskLabel.optBoolean(Constants.KEY_DEBUG),
30 | riskLabel.optBoolean(Constants.KEY_MULTIPLE),
31 | riskLabel.optBoolean(Constants.KEY_XPOSED),
32 | riskLabel.optBoolean(Constants.KEY_MAGISK),
33 | riskLabel.optBoolean(Constants.KEY_HOOK),
34 | riskLabel.optBoolean(Constants.KEY_EMULATOR),
35 | riskLabel.optBoolean(Constants.KEY_VPN),
36 | riskLabel.optBoolean(Constants.KEY_DEVICE_INFO_TAMPERED)
37 | )
38 |
39 | fun getAppListInfo(): AppListsRawData = AppListsRawData(
40 | deviceDetail.optString(Constants.KEY_SYSTEM_APP_LIST),
41 | deviceDetail.optString(Constants.KEY_APP_LIST)
42 | )
43 |
44 | fun getBatteryInfo(): BatteryInfoRawData = BatteryInfoRawData(
45 | deviceDetail.optString(Constants.KEY_BATTERY_HEALTH_STATUS),
46 | deviceDetail.optString(Constants.KEY_BATTERY_STATUS),
47 | deviceDetail.optInt(Constants.KEY_BATTERY_TEMP),
48 | deviceDetail.optInt(Constants.KEY_BATTERY_LEVEL),
49 | deviceDetail.optString(Constants.KEY_BATTERY_TOTAL_CAPACITY)
50 | )
51 |
52 | fun getBuildInfo(): BuildInfoRawData = BuildInfoRawData(
53 | deviceDetail.optString(Constants.KEY_MODEL),
54 | deviceDetail.optString(Constants.KEY_BRAND),
55 | deviceDetail.optString(Constants.KEY_MANUFACTURER),
56 | deviceDetail.optString(Constants.KEY_ANDROID_VERSION),
57 | deviceDetail.optString(Constants.KEY_SDK_VERSION),
58 | deviceDetail.optString(Constants.KEY_KERNEL_VERSION),
59 | deviceDetail.optString(Constants.KEY_FINGERPRINT),
60 | deviceDetail.optString(Constants.KEY_HOST),
61 | deviceDetail.optString(Constants.KEY_SCREEN_RESOLUTION),
62 | deviceDetail.optString(Constants.KEY_SCREEN_INCHES),
63 | deviceDetail.optString(Constants.KEY_SCREEN_BRIGHTNESS),
64 | deviceDetail.optString(Constants.KEY_SCREEN_OFF_TIMEOUT)
65 | )
66 |
67 | fun getCpuInfo(): CpuInfoRawData = CpuInfoRawData(
68 | deviceDetail.optString(Constants.KEY_CPU_HARDWARE),
69 | deviceDetail.optString(Constants.KEY_CPU_PROCESSOR),
70 | deviceDetail.optString(Constants.KEY_ABI_TYPE),
71 | deviceDetail.optString(Constants.KEY_CORES_COUNT)
72 | )
73 |
74 | fun getMemoryInfo(): MemoryInfoRawData = MemoryInfoRawData(
75 | deviceDetail.optLong(Constants.KEY_TOTAL_MEMORY),
76 | deviceDetail.optLong(Constants.KEY_AVAILABLE_MEMORY),
77 | deviceDetail.optLong(Constants.KEY_TOTAL_STORAGE),
78 | deviceDetail.optLong(Constants.KEY_AVAILABLE_STORAGE)
79 | )
80 |
81 | fun getSensorInfo(): SensorInfoRawData =
82 | SensorInfoRawData(deviceDetail.optString(Constants.KEY_SENSORS_INFO))
83 |
84 | fun getSettingInfo(): SettingInfoRawData = SettingInfoRawData(
85 | deviceDetail.optString(Constants.KEY_ADB_ENABLED),
86 | deviceDetail.optString(Constants.KEY_DEVELOPMENT_SETTING_ENABLED),
87 | deviceDetail.optString(Constants.KEY_HTTP_PROXY),
88 | deviceDetail.optString(Constants.KEY_DATA_ROAMING),
89 | deviceDetail.optString(Constants.KEY_ALLOW_MOCK_LOCATION),
90 | deviceDetail.optString(Constants.KEY_ACCESSIBILITY_ENABLED),
91 | deviceDetail.optString(Constants.KEY_DEFAULT_INPUTMETHOD),
92 | deviceDetail.optString(Constants.KEY_TOUCH_EXPLORATION_ENABLED),
93 | deviceDetail.optString(Constants.KEY_SCREEN_OFF_TIMEOUT)
94 | )
95 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/MemoryInfoRawData.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.providers
2 |
3 | /**
4 | * @description:MemoryInfoRawData
5 | * @author: wuzuchang
6 | * @date: 2023/5/16
7 | */
8 | data class MemoryInfoRawData(
9 | val totalMemory: Long,
10 | val availableMemory: Long,
11 | val totalStorage: Long,
12 | val availableStorage: Long,
13 | )
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/RiskInfoRawData.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.providers
2 |
3 | import cn.tongdun.mobrisk.core.tools.Constants
4 |
5 | /**
6 | * @description:RiskInfoRawData
7 | * @author: wuzuchang
8 | * @date: 2023/5/16
9 | */
10 | data class RiskInfoRawData(
11 | val root: Boolean,
12 | val debug: Boolean,
13 | val multiple: Boolean,
14 | val xposed: Boolean,
15 | val magisk: Boolean,
16 | val hook: Boolean,
17 | val emulator: Boolean,
18 | val vpn: Boolean,
19 | val deviceInfoTampered: Boolean
20 | ) {
21 |
22 | override fun toString(): String {
23 | val risks = arrayOf(
24 | root.takeIf { it }?.let { Constants.KEY_ROOT },
25 | debug.takeIf { it }?.let { Constants.KEY_DEBUG },
26 | multiple.takeIf { it }?.let { Constants.KEY_MULTIPLE },
27 | xposed.takeIf { it }?.let { Constants.KEY_XPOSED },
28 | magisk.takeIf { it }?.let { Constants.KEY_MAGISK },
29 | hook.takeIf { it }?.let { Constants.KEY_HOOK },
30 | emulator.takeIf { it }?.let { Constants.KEY_EMULATOR },
31 | vpn.takeIf { it }?.let { Constants.KEY_VPN },
32 | deviceInfoTampered.takeIf { it }?.let { Constants.KEY_DEVICE_INFO_TAMPERED }
33 | )
34 | return risks.filterNotNull().joinToString()
35 | }
36 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/SensorInfoRawData.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.providers
2 |
3 | import android.text.TextUtils
4 | import cn.tongdun.mobrisk.core.tools.executeSafe
5 | import org.json.JSONArray
6 |
7 | /**
8 | * @description:SensorInfoRawData
9 | * @author: wuzuchang
10 | * @date: 2023/5/16
11 | */
12 | data class SensorInfoRawData(val sensorInfo: String) {
13 | fun getSensorTotal(): Int {
14 | if (TextUtils.isEmpty(sensorInfo)) {
15 | return 0
16 | }
17 | var sensorArray: JSONArray? = null
18 | executeSafe { sensorArray = JSONArray(sensorInfo) }
19 | return sensorArray?.length() ?: 0
20 | }
21 | }
--------------------------------------------------------------------------------
/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/SettingInfoRawData.kt:
--------------------------------------------------------------------------------
1 | package cn.tongdun.mobrisk.providers
2 |
3 | /**
4 | * @description:
5 | * @author: wuzuchang
6 | * @date: 2023/5/16
7 | */
8 | data class SettingInfoRawData(
9 | val adb: String,
10 | val developmentSetting: String,
11 | val httpProxy: String,
12 | val dataRoaming: String,
13 | val allowMockLocation: String,
14 | val accessibility: String,
15 | val defaultInputMethod: String,
16 | val touchExplorationEnabled: String,
17 | val screenOffTimeout: String
18 | )
--------------------------------------------------------------------------------
/trustdevice/src/main/resources/META-INF/com/trustdecision/android/mobrisk/verification.properties:
--------------------------------------------------------------------------------
1 | #This is the verification token for the com.trustdecision.android:mobrisk SDK.
2 | #Thu Aug 15 01:53:45 PDT 2024
3 | token=SFRFGDU5DFHEPA24CLIK7WIVEE
4 |
--------------------------------------------------------------------------------
/trustdevice/src/test/java/cn/tongdun/android/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package cn.tongdun.android;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------