├── module ├── .gitignore ├── src │ ├── META-INF │ │ └── com │ │ │ └── google │ │ │ └── android │ │ │ ├── updater-script │ │ │ └── update-binary │ ├── bin │ │ ├── cmd │ │ └── tseed │ ├── banner.png │ ├── webui.apk │ ├── module.prop │ ├── webroot │ │ └── index.html │ ├── action.sh │ ├── lib │ │ ├── state.sh │ │ ├── action.sh │ │ └── util_functions.sh │ ├── post-fs-data.sh │ ├── service.sh │ ├── uninstall.sh │ ├── verify.sh │ ├── keybox.xml │ └── customize.sh └── build.gradle.kts ├── dex ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── ts │ │ └── enhancer │ │ └── xtr │ │ ├── Main.java │ │ ├── ModifyExcute.java │ │ ├── Logger.java │ │ └── ConflictCheck.java ├── gradle.properties ├── proguard-rules.pro └── build.gradle.kts ├── .gitattributes ├── .gitignore ├── app ├── gradle.properties ├── proguard-rules.pro ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── io │ │ └── github │ │ └── xtrlumen │ │ └── vbmeta │ │ ├── Provider.kt │ │ └── execute │ │ └── Execute.kt └── build.gradle.kts ├── gradle ├── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties └── libs.versions.toml ├── gradle.properties ├── tseed ├── Cargo.toml ├── src │ └── main.rs ├── build.gradle.kts └── Cargo.lock ├── sealer ├── Cargo.toml ├── build.gradle.kts ├── src │ └── lib.rs └── Cargo.lock ├── settings.gradle.kts ├── CHANGELOG.md ├── .github └── workflows │ └── build.yml ├── README4zh-Hans.md ├── README4zh-Hant.md ├── gradlew.bat ├── README.md ├── gradlew └── LICENSE /module/.gitignore: -------------------------------------------------------------------------------- 1 | public_key 2 | private_key -------------------------------------------------------------------------------- /dex/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /module/src/META-INF/com/google/android/updater-script: -------------------------------------------------------------------------------- 1 | #MAGISK 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | 3 | *.bat text eol=crlf 4 | *.jar binary 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | target 3 | .gradle 4 | .kotlin 5 | .DS_Store 6 | /local.properties -------------------------------------------------------------------------------- /module/src/bin/cmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XtrLumen/TS-Enhancer-Extreme/HEAD/module/src/bin/cmd -------------------------------------------------------------------------------- /app/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.configuration-cache=true 2 | org.gradle.configuration-cache.parallel=true -------------------------------------------------------------------------------- /dex/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.configuration-cache=true 2 | org.gradle.configuration-cache.parallel=true -------------------------------------------------------------------------------- /module/src/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XtrLumen/TS-Enhancer-Extreme/HEAD/module/src/banner.png -------------------------------------------------------------------------------- /module/src/webui.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XtrLumen/TS-Enhancer-Extreme/HEAD/module/src/webui.apk -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XtrLumen/TS-Enhancer-Extreme/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | android.useAndroidX=true 2 | org.gradle.configureondemand=true 3 | org.gradle.caching=true 4 | org.gradle.parallel=true 5 | org.gradle.jvmargs=-Xmx2048m 6 | -------------------------------------------------------------------------------- /tseed/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tseedemo" 3 | edition = "2021" 4 | 5 | [dependencies] 6 | libloading = "0.8" 7 | 8 | [profile.release] 9 | lto = true 10 | strip = true 11 | debug = false 12 | panic = "abort" 13 | opt-level = "z" -------------------------------------------------------------------------------- /dex/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | -keepclasseswithmembers class ts.enhancer.xtr.Main { 2 | public static void main(java.lang.String[]); 3 | public static native boolean jsealer(); 4 | } 5 | 6 | -repackageclasses 7 | -allowaccessmodification 8 | -overloadaggressively 9 | -renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /sealer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sealer" 3 | edition = "2021" 4 | 5 | [lib] 6 | name = "sealer" 7 | crate-type = ["cdylib"] 8 | 9 | [dependencies] 10 | hex = "0.4" 11 | jni = "0.21" 12 | blake3 = "1.8" 13 | ed25519-compact = "2.0" 14 | 15 | [profile.release] 16 | lto = true 17 | strip = true 18 | debug = false 19 | panic = "abort" 20 | opt-level = "z" -------------------------------------------------------------------------------- /module/src/module.prop: -------------------------------------------------------------------------------- 1 | id=${moduleId} 2 | name=${moduleName} 3 | version=${versionName} 4 | versionCode=${versionCode} 5 | author=XtrLumen 6 | description=[🔄]提升TrickyStore的使用体验,同时极致隐藏由解锁引导加载程序产生的相关检测点.│Enhances the TrickyStore experience, while providing extreme hiding of detection points introduced by bootloader unlocking. 7 | updateJson=https://xtrlumen.github.io/TS-Enhancer-Extreme/update.json 8 | banner=banner.png -------------------------------------------------------------------------------- /tseed/src/main.rs: -------------------------------------------------------------------------------- 1 | use libloading::{Library, Symbol}; 2 | 3 | fn main() { 4 | let libpath = unsafe { Library::new("/data/adb/modules/ts_enhancer_extreme/lib/libsealer.so") }.unwrap(); 5 | let verify: Symbol bool> = unsafe { libpath.get(b"rsealer\0") }.unwrap(); 6 | 7 | if !unsafe { verify() } { 8 | std::process::exit(1); 9 | } 10 | 11 | println!("Hello World!"); 12 | } -------------------------------------------------------------------------------- /gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | # This file was generated by the Gradle 'init' task. 2 | # https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format 3 | 4 | [versions] 5 | guava = "33.4.6-jre" 6 | junit-jupiter = "5.12.1" 7 | 8 | [libraries] 9 | guava = { module = "com.google.guava:guava", version.ref = "guava" } 10 | junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" } 11 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | -allowaccessmodification 2 | -repackageclasses 3 | 4 | -assumenosideeffects class kotlin.jvm.internal.Intrinsics { 5 | public static void check*(...); 6 | public static void throw*(...); 7 | } 8 | 9 | -assumenosideeffects class java.util.Objects{ 10 | ** requireNonNull(...); 11 | } 12 | 13 | -assumenosideeffects class android.util.Log { 14 | public static *** v(...); 15 | public static *** d(...); 16 | public static *** i(...); 17 | public static *** w(...); 18 | public static *** e(...); 19 | } -------------------------------------------------------------------------------- /module/src/webroot/index.html: -------------------------------------------------------------------------------- 1 | TSEE 2 |
3 |

下版本一定更新WebUI

4 |

目前没做,不要再反馈白屏了,我承认告知的不够明确.

5 |

如遇到问题请优先查看zip内的README.md文件大概率有答案.

6 |
7 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 15 | 16 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | plugins { 7 | id("com.android.application") version "8.13.0" 8 | id("org.jetbrains.kotlin.android") version "2.1.0" 9 | } 10 | } 11 | 12 | dependencyResolutionManagement { 13 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 14 | repositories { 15 | google() 16 | mavenCentral() 17 | } 18 | } 19 | 20 | rootProject.name = "TS-Enhancer-Extreme" 21 | include( 22 | ":app", 23 | ":dex", 24 | ":tseed", 25 | ":sealer", 26 | ":module" 27 | ) -------------------------------------------------------------------------------- /module/src/META-INF/com/google/android/update-binary: -------------------------------------------------------------------------------- 1 | #!/sbin/sh 2 | 3 | ################# 4 | # Initialization 5 | ################# 6 | 7 | umask 022 8 | 9 | # echo before loading util_functions 10 | ui_print() { echo "$1"; } 11 | 12 | require_new_magisk() { 13 | ui_print "*******************************" 14 | ui_print " Please install Magisk v20.4+! " 15 | ui_print "*******************************" 16 | exit 1 17 | } 18 | 19 | ######################### 20 | # Load util_functions.sh 21 | ######################### 22 | 23 | OUTFD=$2 24 | ZIPFILE=$3 25 | 26 | mount /data 2>/dev/null 27 | 28 | [ -f /data/adb/magisk/util_functions.sh ] || require_new_magisk 29 | . /data/adb/magisk/util_functions.sh 30 | [ $MAGISK_VER_CODE -lt 20400 ] && require_new_magisk 31 | 32 | install_module 33 | exit 0 34 | -------------------------------------------------------------------------------- /sealer/build.gradle.kts: -------------------------------------------------------------------------------- 1 | tasks.register("clean") { 2 | group = "build" 3 | executable("cargo") 4 | args("clean") 5 | workingDir(projectDir) 6 | } 7 | listOf("Debug", "Release").forEach { variantName -> 8 | val variantCapped = variantName.replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() } 9 | val variantLowered = variantName.lowercase() 10 | 11 | tasks.register("buildLib$variantCapped") { 12 | group = "build" 13 | executable("cargo") 14 | args("ndk", "--target", "aarch64-linux-android", "build") 15 | if (variantLowered == "release") { 16 | args("--release") 17 | } 18 | } 19 | } 20 | tasks.register("buildLib") { 21 | group = "build" 22 | 23 | dependsOn( 24 | "buildLibDebug", 25 | "buildLibRelease" 26 | ) 27 | } -------------------------------------------------------------------------------- /tseed/build.gradle.kts: -------------------------------------------------------------------------------- 1 | tasks.register("clean") { 2 | group = "build" 3 | executable("cargo") 4 | args("clean") 5 | workingDir(projectDir) 6 | } 7 | listOf("Debug", "Release").forEach { variantName -> 8 | val variantCapped = variantName.replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() } 9 | val variantLowered = variantName.lowercase() 10 | 11 | tasks.register("buildBin$variantCapped") { 12 | group = "build" 13 | executable("cargo") 14 | args("ndk", "--target", "aarch64-linux-android", "build") 15 | if (variantLowered == "release") { 16 | args("--release") 17 | } 18 | } 19 | } 20 | tasks.register("buildBin") { 21 | group = "build" 22 | 23 | dependsOn( 24 | "buildBinDebug", 25 | "buildBinRelease" 26 | ) 27 | } -------------------------------------------------------------------------------- /tseed/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "cfg-if" 7 | version = "1.0.4" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" 10 | 11 | [[package]] 12 | name = "libloading" 13 | version = "0.8.9" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" 16 | dependencies = [ 17 | "cfg-if", 18 | "windows-link", 19 | ] 20 | 21 | [[package]] 22 | name = "tseedemo" 23 | version = "0.0.0" 24 | dependencies = [ 25 | "libloading", 26 | ] 27 | 28 | [[package]] 29 | name = "windows-link" 30 | version = "0.2.1" 31 | source = "registry+https://github.com/rust-lang/crates.io-index" 32 | checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" 33 | -------------------------------------------------------------------------------- /module/src/action.sh: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of TS-Enhancer-Extreme. 3 | # 4 | # TS-Enhancer-Extreme is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 5 | # 6 | # TS-Enhancer-Extreme is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 7 | # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 8 | # See the GNU General Public License for more details. 9 | # 10 | # You should have received a copy of the GNU General Public License along with TS-Enhancer-Extreme. 11 | # If not, see . 12 | # 13 | # Copyright (C) 2025 TheGeniusClub (Organization) 14 | # Copyright (C) 2025 XtrLumen (Developer) 15 | # 16 | 17 | cd ${0%/*} 18 | source "./lib/util_functions.sh" 19 | 20 | echo_cn "- 跳转配置页面" 21 | echo_en "- Start WebUI" 22 | $TSEEBIN/tseed --startwebui -------------------------------------------------------------------------------- /module/src/lib/state.sh: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of TS-Enhancer-Extreme. 3 | # 4 | # TS-Enhancer-Extreme is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 5 | # 6 | # TS-Enhancer-Extreme is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 7 | # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 8 | # See the GNU General Public License for more details. 9 | # 10 | # You should have received a copy of the GNU General Public License along with TS-Enhancer-Extreme. 11 | # If not, see . 12 | # 13 | # Copyright (C) 2025 TheGeniusClub (Organization) 14 | # Copyright (C) 2025 XtrLumen (Developer) 15 | # 16 | 17 | cd ${0%/*} 18 | [ -d "../modules/ts_enhancer_extreme" ] || rm -f "$0" 19 | source "../modules/ts_enhancer_extreme/lib/util_functions.sh" 20 | 21 | initwait 22 | invoke "刷新运行状态" "--staterefresh" -------------------------------------------------------------------------------- /module/src/lib/action.sh: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of TS-Enhancer-Extreme. 3 | # 4 | # TS-Enhancer-Extreme is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 5 | # 6 | # TS-Enhancer-Extreme is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 7 | # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 8 | # See the GNU General Public License for more details. 9 | # 10 | # You should have received a copy of the GNU General Public License along with TS-Enhancer-Extreme. 11 | # If not, see . 12 | # 13 | # Copyright (C) 2025 TheGeniusClub (Organization) 14 | # Copyright (C) 2025 XtrLumen (Developer) 15 | # 16 | 17 | cd ${0%/*} 18 | source "../ts_enhancer_extreme/lib/util_functions.sh" 19 | 20 | echo_cn -n "- 更新目标文件..." 21 | echo_en -n "- Update target file..." 22 | [ "$APATCH" = "true" ] || PARAMETER="-a" 23 | $TSEEBIN/tseed --packagelistupdate $PARAMETER 24 | detect -------------------------------------------------------------------------------- /module/src/post-fs-data.sh: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of TS-Enhancer-Extreme. 3 | # 4 | # TS-Enhancer-Extreme is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 5 | # 6 | # TS-Enhancer-Extreme is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 7 | # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 8 | # See the GNU General Public License for more details. 9 | # 10 | # You should have received a copy of the GNU General Public License along with TS-Enhancer-Extreme. 11 | # If not, see . 12 | # 13 | # Copyright (C) 2025 TheGeniusClub (Organization) 14 | # Copyright (C) 2025 XtrLumen (Developer) 15 | # 16 | 17 | cd ${0%/*} 18 | source "./lib/util_functions.sh" 19 | $TSEEBIN/tseed --rootdetect 20 | check 21 | 22 | invoke "移除冲突模块" "--conflictmodcheck" 23 | [ -f "$SD/$D" ] || { 24 | logp "复制状态检测脚本到自启文件夹" 25 | mkdir -p "$SD" 26 | cp -f "$TSEEMODDIR/lib/state.sh" "$SD/$D" 27 | chmod +x "$SD/$D" 28 | } -------------------------------------------------------------------------------- /module/src/service.sh: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of TS-Enhancer-Extreme. 3 | # 4 | # TS-Enhancer-Extreme is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 5 | # 6 | # TS-Enhancer-Extreme is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 7 | # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 8 | # See the GNU General Public License for more details. 9 | # 10 | # You should have received a copy of the GNU General Public License along with TS-Enhancer-Extreme. 11 | # If not, see . 12 | # 13 | # Copyright (C) 2025 TheGeniusClub (Organization) 14 | # Copyright (C) 2025 XtrLumen (Developer) 15 | # 16 | 17 | cd ${0%/*} 18 | source "./lib/util_functions.sh" 19 | check 20 | 21 | logs "启动后台服务" 22 | $TSEEBIN/tseed --tseectl -start 23 | initwait 24 | [[ $($TSEEBIN/tseed --tseectl -state) == "true" ]] || logs "服务启动失败" 25 | invoke "更新目标文件" "--packagelistupdate" 26 | invoke "卸载冲突软件" "--conflictappcheck" 27 | invoke "同步安全补丁级别到属性" "--securitypatchpropsync" 28 | invoke "伪装引导程序状态为锁定" "--passpropstate" 29 | invoke "修正已验证启动哈希属性" "--passvbhash" -------------------------------------------------------------------------------- /module/src/uninstall.sh: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of TS-Enhancer-Extreme. 3 | # 4 | # TS-Enhancer-Extreme is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 5 | # 6 | # TS-Enhancer-Extreme is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 7 | # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 8 | # See the GNU General Public License for more details. 9 | # 10 | # You should have received a copy of the GNU General Public License along with TS-Enhancer-Extreme. 11 | # If not, see . 12 | # 13 | # Copyright (C) 2025 TheGeniusClub (Organization) 14 | # Copyright (C) 2025 XtrLumen (Developer) 15 | # 16 | 17 | rm -rf /data/adb/ts_enhancer_extreme/ 18 | rm -f /data/adb/service.d/.tsee_state.sh 19 | find /data/adb/service.d -empty -delete 20 | rm -f /data/adb/modules/tricky_store/action.sh 21 | [ -d /data/adb/tricky_store ] && { 22 | cp -f /data/adb/tricky_store/keybox_backup/keybox.xml /data/adb/tricky_store/keybox.xml 23 | rm -rf /data/adb/tricky_store/keybox_backup 24 | [ ! -f /data/adb/tricky_store/keybox.xml ] && cp -f /data/adb/ts_enhancer_extreme/keybox.xml /data/adb/tricky_store/keybox.xml 25 | } -------------------------------------------------------------------------------- /dex/src/main/java/ts/enhancer/xtr/Main.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of TS-Enhancer-Extreme. 3 | * 4 | * TS-Enhancer-Extreme is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 5 | * 6 | * TS-Enhancer-Extreme is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 7 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 8 | * See the GNU General Public License for more details. 9 | * 10 | * You should have received a copy of the GNU General Public License along with TS-Enhancer-Extreme. If not, see . 11 | * 12 | * Copyright (C) 2025 TheGeniusClub (Organization) 13 | * Copyright (C) 2025 XtrLumen (Developer) 14 | */ 15 | 16 | package ts.enhancer.xtr; 17 | 18 | public class Main { 19 | public static native boolean jsealer(); 20 | 21 | static { 22 | System.loadLibrary("sealer"); 23 | if (!jsealer()) { 24 | throw new NullPointerException(); 25 | } 26 | } 27 | 28 | public static void main(String[] args) { 29 | Thread modifyThread = new Thread(new ModifyExcute()); 30 | modifyThread.start(); 31 | Thread conflictThread = new Thread(new ConflictCheck()); 32 | conflictThread.start(); 33 | Logger.logout("服务启动成功"); 34 | } 35 | } -------------------------------------------------------------------------------- /app/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.dsl.KotlinVersion 2 | 3 | plugins { 4 | id("com.android.application") 5 | id("org.jetbrains.kotlin.android") 6 | } 7 | 8 | dependencies { 9 | implementation("org.bouncycastle:bcprov-jdk18on:1.80") 10 | } 11 | 12 | val verName: String by rootProject.extra 13 | val verCode: Int by rootProject.extra 14 | 15 | android { 16 | namespace = "io.github.xtrlumen.vbmeta" 17 | buildToolsVersion = "35.0.0" 18 | compileSdk = 35 19 | defaultConfig { 20 | minSdk = 24 21 | targetSdk = 34 22 | versionCode = verCode 23 | versionName = verName 24 | } 25 | 26 | buildTypes { 27 | debug { 28 | versionNameSuffix = "-debug" 29 | } 30 | release { 31 | isMinifyEnabled = true 32 | vcsInfo.include = false 33 | proguardFiles("proguard-rules.pro") 34 | signingConfig = android.signingConfigs.getByName("debug") 35 | } 36 | } 37 | 38 | compileOptions { 39 | sourceCompatibility = JavaVersion.VERSION_21 40 | targetCompatibility = JavaVersion.VERSION_21 41 | } 42 | 43 | packaging { 44 | resources { 45 | excludes += setOf("**") 46 | } 47 | } 48 | 49 | lint { 50 | checkReleaseBuilds = false 51 | } 52 | } 53 | 54 | configurations.configureEach { 55 | exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-jdk7") 56 | exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-jdk8") 57 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # v0.8.2.1 2 | > 主要 3 | - 扩充冲突模块列表. 4 | - 修复machikado完整性校验不符合Shamiko模块原始算法致其罢工问题. 5 | - 修复crlf换行符导致release版customize.sh文件概率安装失败问题. 6 | - 由于YuriKeyManager模块的抓取有效密钥功能升级为二进制可执行文件,我无能为力,为抓取有效密钥后端功能修复来源B:换源到IntegrityBox模块. 7 | - **此版本为0.8.2的补丁,不符合0.8.2日志提到的更新计划.** 8 | 9 | # v0.8.2 10 | > 主要 11 | - 修复大量问题,优化大量逻辑. 12 | - 正式开源. 13 | - 扩充冲突模块列表. 14 | - 加回META-INF文件夹防止低版本Magisk无法解压. 15 | - 新增binaries文件夹,并将core重命名tseed放入其中. 16 | - 为抓取有效密钥后端功能扩充来源: [ tseed --stealkeybox < Basic |-a|-b| > ] 17 | - 显示多重共存具体信息,现在仅当Root实现同时安装在内核空间与用户空间才被判定存在. 18 | - 将GetVBHash服务精简并重写为Kotlin,使得支持FBE加密状态启动并提升成功率,更早执行. 19 | > 杂项 20 | - 修改横幅. 21 | - **下个版本会解决sed导致module.prop文件损坏问题,及加入WebUI.** 22 | 23 | # v0.8.1 24 | > 主要 25 | - 小幅优化结构. 26 | - cli中加入echo与日志输出,方便查看状况. 27 | - 优化AVB2.0被关闭等VerifiedBootHash状态异常时全自动修正后端功能启动逻辑,提高稳定性. 28 | 29 | # v0.8.0 30 | ## 由于本次属于重大更新,与之前0.0.2飞跃至0.5.0类似,版本号从0.6.1飞跃至0.8.0. 31 | > 主要 32 | - 修复无法识别Magisk30200版本问题 33 | - Dex后台服务中加入防抖机制,防止一秒内多次触发执行. 34 | - TrickyStore服务状态读取/控制后端功能支持TrickyStoreOSS分支. 35 | - 添加了AVB2.0被关闭等VerifiedBootHash状态异常时全自动修正后端功能:`core --passvbhash` 36 | > 杂项 37 | - 修改描述. 38 | 39 | # v0.6.1 40 | > 主要 41 | - 扩充冲突软件列表. 42 | - 彻底修复支持KPM功能的SukiSU出现多重共存误报问题,并增强精确度. 43 | 44 | # v0.6.0 45 | 46 | > 主要 47 | - 扩充冲突模块列表. 48 | - 彻底修复可用性检测的dmesg匹配. 49 | - 合并日志输出为单文件,优化启动逻辑. 50 | - 去除Inotifyd监听,仅保留JavaDex服务,以彻底修复CPU占用率高/异常耗电问题. 51 | > 杂项 52 | - 修改描述. 53 | 54 | # v0.5.9 55 | 56 | > 主要 57 | - 扩充了冲突模块列表. 58 | - 添加了抓取有效密钥后端功能:[ core --stealkeybox ] 59 | - 将可用性检测从查找指令集文件升级为dmesg匹配,并优化大量逻辑使得运行更高效. 60 | > 杂项 61 | - 添加了 README.md 自述文件. 62 | - 添加了 KernelSU-Next 支持的横幅图片. 63 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: '**' 6 | paths-ignore: 7 | - '**/*.md' 8 | tags-ignore: 9 | - '**' 10 | pull_request: 11 | paths-ignore: 12 | - '**/*.md' 13 | 14 | jobs: 15 | build: 16 | name: Build 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Check out 20 | uses: actions/checkout@v4 21 | with: 22 | fetch-depth: 0 23 | 24 | - name: Set up JDK 21 25 | uses: actions/setup-java@v4 26 | with: 27 | distribution: 'temurin' 28 | java-version: '21' 29 | 30 | - name: Setup Android SDK 31 | uses: android-actions/setup-android@v2 32 | 33 | - name: Setup Android NDK 34 | run: $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --install "ndk;29.0.14206865" 35 | 36 | - name: Setup Rust 37 | uses: actions-rust-lang/setup-rust-toolchain@v1 38 | with: 39 | target: aarch64-linux-android 40 | 41 | - name: Install cargo-ndk 42 | run: cargo install cargo-ndk 43 | 44 | - name: Setup Gradle 45 | uses: gradle/actions/setup-gradle@v4 46 | with: 47 | build-scan-publish: true 48 | build-scan-terms-of-use-url: "https://gradle.com/terms-of-service" 49 | build-scan-terms-of-use-agree: "yes" 50 | 51 | - name: Build with Gradle 52 | run: ./gradlew zip 53 | 54 | - name: Upload artifacts 55 | uses: actions/upload-artifact@v4 56 | with: 57 | name: TS-Enhancer-Extreme 58 | path: | 59 | module/build/outputs/release/*.zip 60 | module/build/outputs/debug/*.zip 61 | retention-days: 30 -------------------------------------------------------------------------------- /dex/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.android.application") 3 | } 4 | 5 | val verName: String by rootProject.extra 6 | val verCode: Int by rootProject.extra 7 | 8 | android { 9 | namespace = "ts.enhancer.xtr" 10 | compileSdk = 35 11 | defaultConfig { 12 | minSdk = 24 13 | targetSdk = 34 14 | versionCode = verCode 15 | versionName = verName 16 | multiDexEnabled = false 17 | } 18 | 19 | buildTypes { 20 | getByName("release") { 21 | isMinifyEnabled = true 22 | vcsInfo.include = false 23 | proguardFiles("proguard-rules.pro") 24 | } 25 | } 26 | 27 | compileOptions { 28 | sourceCompatibility = JavaVersion.VERSION_21 29 | targetCompatibility = JavaVersion.VERSION_21 30 | } 31 | 32 | lint { 33 | checkReleaseBuilds = false 34 | } 35 | } 36 | 37 | listOf("Debug", "Release").forEach { variantName -> 38 | val variantCapped = variantName.replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() } 39 | val variantLowered = variantName.lowercase() 40 | 41 | tasks.register("compileDex$variantCapped") { 42 | group = "build" 43 | 44 | dependsOn( 45 | ":dex:assemble$variantCapped" 46 | ) 47 | 48 | into(layout.buildDirectory.dir("outputs/dex/$variantLowered")) 49 | from("$projectDir/build/intermediates/dex/$variantLowered/minifyReleaseWithR8") { 50 | include( 51 | "classes.dex" 52 | ) 53 | rename( 54 | "classes.dex", 55 | "service.dex" 56 | ) 57 | } 58 | } 59 | } 60 | 61 | tasks.register("compileDex") { 62 | group = "build" 63 | 64 | dependsOn( 65 | "compileDexDebug", 66 | "compileDexRelease" 67 | ) 68 | } -------------------------------------------------------------------------------- /module/src/verify.sh: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of TS-Enhancer-Extreme. 3 | # 4 | # TS-Enhancer-Extreme is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 5 | # 6 | # TS-Enhancer-Extreme is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 7 | # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 8 | # See the GNU General Public License for more details. 9 | # 10 | # You should have received a copy of the GNU General Public License along with TS-Enhancer-Extreme. 11 | # If not, see . 12 | # 13 | # Copyright (C) 2025 TheGeniusClub (Organization) 14 | # Copyright (C) 2025 XtrLumen (Developer) 15 | # 16 | 17 | TMPDIR_FOR_VERIFY="$TMPDIR/.vunzip" 18 | mkdir -p "$TMPDIR_FOR_VERIFY" 19 | 20 | extract() { 21 | unpack() { 22 | local zip=$1 23 | local file=$2 24 | local dir=$3 25 | local quiet=$4 26 | local skip=$5 27 | unzip -o "$zip" "$file" -d "$dir" >&2 28 | file_path="$dir/$file" 29 | if [ -f "$file_path" ]; then 30 | unzip -o "$zip" "MANIFEST/$file.sha256" -d "$TMPDIR_FOR_VERIFY" >&2 31 | hash_path="$TMPDIR_FOR_VERIFY/MANIFEST/$file.sha256" 32 | if [ -f "$hash_path" ]; then 33 | (echo "$(cat "$hash_path") $file_path" | sha3sum -a 256 -c -s -) || { 34 | abort_cn "$file 被篡改!" 35 | abort_en "Failed to verify $file" 36 | } 37 | elif [ ! "$skip" = "-s" ]; then 38 | abort_cn "$file.sha256 不存在!" 39 | abort_en "$file.sha256 not exists" 40 | fi 41 | else 42 | abort_cn "$file 不存在!" 43 | abort_en "$file not exists" 44 | fi 45 | [ "$quiet" = "-q" ] || { 46 | print_cn "- $file 未篡改" 47 | print_en "- Verified $file" >&1 48 | } 49 | } 50 | if [[ "$2" == */\* ]]; then 51 | for files in $(unzip -l "$1" "$2" | awk 'NR>3 {print $4}' | grep -v '\.sha256$' | grep -v '/$' | grep -v '^$'); do 52 | unpack "$1" "$files" "$3" "$4" "$5" 53 | done 54 | else 55 | unpack "$@" 56 | fi 57 | } 58 | 59 | extract "$ZIPFILE" 'META-INF/com/google/android/*' "$TMPDIR_FOR_VERIFY" -q -s 60 | extract "$ZIPFILE" 'verify.sh' "$TMPDIR_FOR_VERIFY" -q 61 | extract "$ZIPFILE" 'customize.sh' "$TMPDIR_FOR_VERIFY" -q -------------------------------------------------------------------------------- /README4zh-Hans.md: -------------------------------------------------------------------------------- 1 | # Tricky Store Enhancer Extreme 2 | 提升TrickyStore的使用体验,同时极致隐藏由解锁引导加载程序产生的相关检测点。 3 | 4 | > [!TIP] 5 | > 「[English](README.md)」「[繁體中文](README4zh-Hant.md)」 6 | 7 | > [!IMPORTANT] 8 | > 本模块**专精**伪装引导加载程序状态,**而非**通过PlayIntegrity。 9 | 10 | ## 条件 11 | - 已安装 [TrickyStore](https://github.com/5ec1cff/TrickyStore) 或 [TrickyStoreOSS](https://github.com/beakthoven/TrickyStoreOSS) 模块 12 | 13 | ## 安装 14 | 1. 刷写模块并重新启动设备。 15 | 2. 手动配置(可选)。 16 | 3. 完成! 17 | 18 | ## 功能 19 | ### 主要 20 | - [x] 检测到冲突模块时对其添加移除标签/直接删除;检测到冲突软件时直接卸载,实时监控。 21 | - [x] 接管TrickyStore模块目标文件,实时更新,优先级高于任何类似模块。 22 | - [x] 全自动修正异常VerifiedBootHash属性 23 | - [x] 伪装引导加载程序状态为锁定 24 | - [x] 将安全补丁级别同步到属性 25 | - [x] 提供谷歌硬件认证根证书签名的keybox已吊销 26 | - [x] 在TrickyStore模块卡片上添加操作按钮,用于更新TrickyStore模块目标文件即将更改。 27 | 28 | ### 其他 29 | - [x] 监控并显示运行状态 30 | - [x] 根据系统语言分别提供zh-Hans/en-US提示: 运行状态/安装过程 31 | - [x] 安装时备份Keybox,于卸载时恢复备份。路径: `/data/adb/tricky_store/keybox_backup/keybox.xml` 32 | 33 | ### TSEE-CLI 34 | **WebUI仍在开发中,目前只能手动配置** 35 | - 调用功能 36 | - 于终端以Root身份执行`PATH="/data/adb/modules/ts_enhancer_extreme/bin:$PATH"` 37 | - 窃取谷歌硬件认证根证书签名的keybox: `tseed --stealkeybox` `[Basic |-a|-b|-c| ]`「[Tricky-Addon](https://github.com/KOWX712/Tricky-Addon-Update-Target-List)」「[Integrity-Box](https://github.com/MeowDump/Integrity-Box)」「[YuriKey-Manager](https://github.com/YurikeyDev/yurikey)」 38 | - 联网拉取Pixel更新公告的最新安全补丁级别: `tseed --securitypatchdatefetch` 39 | - TrickyStore服务状态读取/控制: `tseed --tsctl` `[Basic |-stop|-start|-state| ]` 40 | - TSEnhancerExtreme服务状态读取/控制: `tseed --tseectl` `[Basic |-stop|-start|-state| ]` 41 | - 配置模块 42 | - 配置目录路径: `/data/adb/ts_enhancer_extreme` 43 | - 在sys.txt中填入想添加到TrickyStore模块目标文件的系统软件的包名 44 | - 在usr.txt中填入想从TrickyStore模块目标文件去除的用户软件的包名 45 | - 日志位于`/data/adb/ts_enhancer_extreme/log`,若遇到问题请创建 issue 并附上日志。 46 | 47 | ### WebUI 48 | - [ ] 日志监控窗口 49 | - [ ] 快捷去除用户软件 50 | - [ ] 快捷勾选系统软件 51 | - [ ] 从内部存储导入keybox 52 | - [ ] 调用TrickyStore服务状态读取/控制 53 | - [ ] 调用窃取谷歌硬件认证根证书签名的keybox 54 | - [ ] 调用TSEnhancerExtreme服务状态读取/控制 55 | - [ ] 快捷自定义安全补丁级别/调用联网抓取Pixel更新公告的最新安全补丁级别 56 | 57 | > [!NOTE] 58 | > ### WebUI支持 59 | > - **KernelSU 或 APatch** 60 | > - 原生支持 61 | > - **Magisk** 62 | > - 提供跳转到 [WebUI X Portable](https://github.com/MMRLApp/WebUI-X-Portable) 或 [KSUWebUIStandalone](https://github.com/5ec1cff/KsuWebUIStandalone) 的操作按钮 63 | > - 在未安装任何 WebUI 独立软件时自动安装 [KSUWebUIStandalone](https://github.com/5ec1cff/KsuWebUIStandalone) 64 | 65 | ## 致谢 66 | - [5ec1cff/cmd-wrapper](https://gist.github.com/5ec1cff/4b3a3ef329094e1427e2397cfa2435ff) 67 | - [vvb2060/KeyAttestation](https://github.com/vvb2060/KeyAttestation) -------------------------------------------------------------------------------- /README4zh-Hant.md: -------------------------------------------------------------------------------- 1 | # Tricky Store Enhancer Extreme 2 | 提升TrickyStore的使用體驗,同時極致隱藏由解鎖引導載入程式產生的相關檢測點。 3 | 4 | > [!TIP] 5 | > 「[English](README.md)」「[简体中文](README4zh-Hans.md)」 6 | 7 | > [!IMPORTANT] 8 | > 本模組**專精**偽裝引導載入程式狀態,**而非**通過PlayIntegrity。 9 | 10 | ## 條件 11 | - 已安裝 [TrickyStore](https://github.com/5ec1cff/TrickyStore) 或 [TrickyStoreOSS](https://github.com/beakthoven/TrickyStoreOSS) 模組 12 | 13 | ## 安裝 14 | 1. 刷入模組並重新啟動裝置。 15 | 2. 手動配置(可選)。 16 | 3. 完成! 17 | 18 | ## 功能 19 | ### 主要 20 | - [x] 偵測到衝突模組時對其添加移除標籤/直接刪除;偵測到衝突軟體時直接卸載,即時監控。 21 | - [x] 接管TrickyStore模組目標檔案,即時更新,優先級高於任何類似模組。 22 | - [x] 全自動修正異常VerifiedBootHash屬性 23 | - [x] 將安全性修補程式等級同步至屬性 24 | - [x] 偽裝引導載入程式狀態為鎖定 25 | - [x] 提供Google硬體認證根憑證簽章的keybox已撤銷 26 | - [x] 在TrickyStore模組卡片上添加操作按鈕,用於更新TrickyStore模組目標檔案即將更改。 27 | 28 | ### 其他 29 | - [x] 監控並顯示運行狀態 30 | - [x] 根據系統語言分別提供zh-Hans/en-US提示: 執行狀態/安裝過程 31 | - [x] 安裝時備份Keybox,於卸載時恢復備份。路徑:`/data/adb/tricky_store/keybox_backup/keybox.xml` 32 | 33 | ### TSEE-CLI 34 | **WebUI仍在開發中,目前只能手動配置** 35 | - 調用功能 36 | - 於終端以Root身份執行`PATH="/data/adb/modules/ts_enhancer_extreme/bin:$PATH"` 37 | - 竊取Google硬體認證根憑證簽章的keybox: `tseed --stealkeybox` `[Basic |-a|-b|-c| ]`「[Tricky-Addon](https://github.com/KOWX712/Tricky-Addon-Update-Target-List)」「[Integrity-Box](https://github.com/MeowDump/Integrity-Box)」「[YuriKey-Manager](https://github.com/YurikeyDev/yurikey)」 38 | - 連線拉取Pixel更新公告的最新安全性修補程式等級: `tseed --securitypatchdatefetch` 39 | - TrickyStore服務狀態讀取/控制: `tseed --tsctl` `[Basic |-stop|-start|-state| ]` 40 | - TSEnhancerExtreme服務狀態讀取/控制: `tseed --tseectl` `[Basic |-stop|-start|-state| ]` 41 | - 配置模組 42 | - 配置目錄路徑: `/data/adb/ts_enhancer_extreme` 43 | - 在sys.txt中填入想添加到TrickyStore模組目標檔案的系統軟體的套件名稱 44 | - 在usr.txt中填入想從TrickyStore模組目標檔案去除的使用者軟體的套件名稱 45 | - 日誌位於`/data/adb/ts_enhancer_extreme/log`,若遇到問題請建立 issue 並附上日誌。 46 | 47 | ### WebUI 48 | - [ ] 日誌監控視窗 49 | - [ ] 快捷勾選系統軟體 50 | - [ ] 快捷去除使用者軟體 51 | - [ ] 從內部儲存空間導入keybox 52 | - [ ] 調用TrickyStore服務狀態讀取/控制 53 | - [ ] 調用竊取Google硬體認證根憑證簽章的keybox 54 | - [ ] 調用TSEnhancerExtreme服務狀態讀取/控制 55 | - [ ] 快捷自訂安全性修補程式等級/調用連線抓取Pixel更新公告的最新安全性修補程式等級 56 | 57 | > [!NOTE] 58 | > ### WebUI支援 59 | > - **KernelSU 或 APatch** 60 | > - 原生支援 61 | > - **Magisk** 62 | > - 提供跳轉至 [WebUI X Portable](https://github.com/MMRLApp/WebUI-X-Portable) 或 [KSUWebUIStandalone](https://github.com/5ec1cff/KsuWebUIStandalone) 的操作按鈕 63 | > - 在未安裝任何 WebUI 獨立軟體時自動安裝 [KSUWebUIStandalone](https://github.com/5ec1cff/KsuWebUIStandalone) 64 | 65 | ## 致謝 66 | - [5ec1cff/cmd-wrapper](https://gist.github.com/5ec1cff/4b3a3ef329094e1427e2397cfa2435ff) 67 | - [vvb2060/KeyAttestation](https://github.com/vvb2060/KeyAttestation) -------------------------------------------------------------------------------- /sealer/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::fs::File; 2 | use std::io::Read; 3 | use std::path::Path; 4 | use jni::JNIEnv; 5 | use jni::sys::jboolean; 6 | use jni::objects::JClass; 7 | use ed25519_compact::{PublicKey, Signature}; 8 | 9 | fn array(path: &Path) -> Option { 10 | let mut hasher = blake3::Hasher::new(); 11 | let mut file = File::open(path).ok()?; 12 | let mut buffer = [0u8; 4096]; 13 | 14 | loop { 15 | let size = file.read(&mut buffer).ok()?; 16 | if size == 0 { 17 | break; 18 | } 19 | hasher.update(&buffer[..size]); 20 | } 21 | 22 | Some(hex::encode(hasher.finalize().as_bytes())) 23 | } 24 | 25 | fn list(pwd: &Path) -> Option { 26 | let action = if pwd.join(".action.sh").exists() { 27 | ".action.sh" 28 | } else { 29 | "action.sh" 30 | }; 31 | 32 | let lists = [ 33 | "bin/cmd", 34 | "bin/tseed", 35 | "lib/action.sh", 36 | "lib/libsealer.so", 37 | "lib/state.sh", 38 | "lib/util_functions.sh", 39 | "banner.png", 40 | "post-fs-data.sh", 41 | "service.apk", 42 | "service.dex", 43 | "service.sh", 44 | "uninstall.sh", 45 | "webui.apk", 46 | action 47 | ]; 48 | 49 | let mut blake3hash = String::new(); 50 | 51 | for file in lists.iter() { 52 | blake3hash.push_str(&array(&pwd.join(file))?); 53 | } 54 | 55 | Some(blake3hash) 56 | } 57 | 58 | fn verify(pwd: &Path, message: &str) -> bool { 59 | let ml_bytes = match std::fs::read(pwd.join("mistylake")) { 60 | Ok(bytes) => bytes, 61 | Err(_) => return false, 62 | }; 63 | 64 | let mut sg_bytes = [0u8; 64]; 65 | sg_bytes[0..16].copy_from_slice(&ml_bytes[0..16]); 66 | sg_bytes[16..48].copy_from_slice(&ml_bytes[32..64]); 67 | sg_bytes[48..64].copy_from_slice(&ml_bytes[80..96]); 68 | 69 | let mut pb_bytes = [0u8; 32]; 70 | pb_bytes[0..16].copy_from_slice(&ml_bytes[16..32]); 71 | pb_bytes[16..32].copy_from_slice(&ml_bytes[64..80]); 72 | 73 | let sg_array: [u8; 64] = sg_bytes; 74 | let pb_array: [u8; 32] = pb_bytes; 75 | 76 | PublicKey::new(pb_array) 77 | .verify(message, &Signature::new(sg_array)) 78 | .is_ok() 79 | } 80 | 81 | #[no_mangle] 82 | pub extern "system" fn Java_ts_enhancer_xtr_Main_jsealer( 83 | _env: JNIEnv, 84 | _class: JClass, 85 | ) -> jboolean { 86 | let pwd = Path::new("/data/adb/modules/ts_enhancer_extreme"); 87 | 88 | let Some(hex) = list(pwd) else { 89 | return 0; 90 | }; 91 | 92 | verify(pwd, &hex) as jboolean 93 | } 94 | 95 | #[no_mangle] 96 | pub fn rsealer() -> bool { 97 | let pwd = Path::new("/data/adb/modules/ts_enhancer_extreme"); 98 | 99 | let Some(hex) = list(pwd) else { 100 | return false; 101 | }; 102 | 103 | verify(pwd, &hex) 104 | } -------------------------------------------------------------------------------- /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= 74 | 75 | 76 | @rem Execute Gradle 77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* 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 | -------------------------------------------------------------------------------- /dex/src/main/java/ts/enhancer/xtr/ModifyExcute.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of TS-Enhancer-Extreme. 3 | * 4 | * TS-Enhancer-Extreme is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 5 | * 6 | * TS-Enhancer-Extreme is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 7 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 8 | * See the GNU General Public License for more details. 9 | * 10 | * You should have received a copy of the GNU General Public License along with TS-Enhancer-Extreme. If not, see . 11 | * 12 | * Copyright (C) 2025 TheGeniusClub (Organization) 13 | * Copyright (C) 2025 XtrLumen (Developer) 14 | */ 15 | 16 | package ts.enhancer.xtr; 17 | 18 | import java.io.File; 19 | import java.nio.file.*; 20 | import java.util.Map; 21 | import java.util.concurrent.ConcurrentHashMap; 22 | 23 | import static java.nio.file.StandardWatchEventKinds.*; 24 | 25 | public class ModifyExcute implements Runnable { 26 | static { 27 | System.loadLibrary("sealer"); 28 | if (!Main.jsealer()) { 29 | throw new NullPointerException(); 30 | } 31 | } 32 | 33 | private static final File MONITOR_FILE = new File("/data/app/"); 34 | private static final Path MONITOR_PATH = MONITOR_FILE.toPath(); 35 | private static final long LOG_SUPPRESS_MS = 1500L; 36 | private static final Map LAST_LOG_TIMES = new ConcurrentHashMap<>(); 37 | 38 | @Override 39 | public void run() { 40 | WatchService watcher = null; 41 | try { 42 | watcher = FileSystems.getDefault().newWatchService(); 43 | MONITOR_PATH.register(watcher, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE); 44 | 45 | while (true) { 46 | WatchKey key = watcher.take(); 47 | boolean changed = false; 48 | 49 | for (WatchEvent event : key.pollEvents()) { 50 | changed = true; 51 | } 52 | 53 | if (changed) { 54 | logOnce("更新目标文件&卸载冲突软件"); 55 | 56 | try { 57 | ProcessBuilder pb = new ProcessBuilder("/data/adb/modules/ts_enhancer_extreme/bin/tseed", "--conflictappcheck", "--packagelistupdate"); 58 | Process p = pb.start(); 59 | p.waitFor(); 60 | } catch (Exception ignored) {} 61 | } 62 | 63 | if (!key.reset()) { 64 | break; 65 | } 66 | } 67 | } catch (Exception ignored) { 68 | } finally { 69 | if (watcher != null) { 70 | try { 71 | watcher.close(); 72 | } catch (Exception ignored) {} 73 | } 74 | } 75 | } 76 | 77 | private static void logOnce(String msg) { 78 | long now = System.currentTimeMillis(); 79 | Long last = LAST_LOG_TIMES.get(msg); 80 | if (last == null || now - last >= LOG_SUPPRESS_MS) { 81 | Logger.logout(msg); 82 | LAST_LOG_TIMES.put(msg, now); 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/xtrlumen/vbmeta/Provider.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of TS-Enhancer-Extreme. 3 | * 4 | * TS-Enhancer-Extreme is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 5 | * 6 | * TS-Enhancer-Extreme is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 7 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 8 | * See the GNU General Public License for more details. 9 | * 10 | * You should have received a copy of the GNU General Public License along with TS-Enhancer-Extreme. If not, see . 11 | * 12 | * Copyright (C) 2025 TheGeniusClub (Organization) 13 | * Copyright (C) 2025 XtrLumen (Developer) 14 | */ 15 | 16 | /* Copyright (C) 2020 The Android Open Source Project 17 | * 18 | * Licensed under the Apache License, Version 2.0 (the "License"); 19 | * you may not use this file except in compliance with the License. 20 | * You may obtain a copy of the License at 21 | * 22 | * http://www.apache.org/licenses/LICENSE-2.0 23 | * 24 | * Unless required by applicable law or agreed to in writing, software 25 | * distributed under the License is distributed on an "AS IS" BASIS, 26 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 27 | * See the License for the specific language governing permissions and 28 | * limitations under the License. 29 | */ 30 | 31 | package io.github.xtrlumen.vbmeta 32 | 33 | import android.content.ContentProvider 34 | import android.content.ContentValues 35 | import android.database.Cursor 36 | import android.net.Uri 37 | import android.os.Bundle 38 | import io.github.xtrlumen.vbmeta.execute.Execute 39 | import java.util.concurrent.CountDownLatch 40 | 41 | class Provider : ContentProvider() { 42 | 43 | companion object { 44 | const val AUTHORITY = "Provider" 45 | 46 | private fun logout(message: String) { 47 | println("[TSEE]$message") 48 | } 49 | } 50 | 51 | override fun onCreate(): Boolean { 52 | return true 53 | } 54 | 55 | override fun call(method: String, arg: String?, extras: Bundle?): Bundle? { 56 | logout("调用安全启动哈希获取") 57 | val latch = CountDownLatch(1) 58 | val result = Bundle() 59 | 60 | Thread { 61 | val hash = Execute.getVerifiedBootHash() 62 | if (hash != null) { 63 | result.putString("VBHash", "${hash}=VBHash") 64 | } else { 65 | result.putString("status", "failed") 66 | } 67 | latch.countDown() 68 | }.start() 69 | 70 | latch.await() 71 | return result 72 | } 73 | 74 | override fun query(uri: Uri, projection: Array?, selection: String?, selectionArgs: Array?, sortOrder: String?): Cursor? = null 75 | override fun getType(uri: Uri): String? = null 76 | override fun insert(uri: Uri, values: ContentValues?): Uri? = null 77 | override fun delete(uri: Uri, selection: String?, selectionArgs: Array?): Int = 0 78 | override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array?): Int = 0 79 | } 80 | -------------------------------------------------------------------------------- /dex/src/main/java/ts/enhancer/xtr/Logger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of TS-Enhancer-Extreme. 3 | * 4 | * TS-Enhancer-Extreme is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 5 | * 6 | * TS-Enhancer-Extreme is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 7 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 8 | * See the GNU General Public License for more details. 9 | * 10 | * You should have received a copy of the GNU General Public License along with TS-Enhancer-Extreme. If not, see . 11 | * 12 | * Copyright (C) 2025 TheGeniusClub (Organization) 13 | * Copyright (C) 2025 XtrLumen (Developer) 14 | */ 15 | 16 | package ts.enhancer.xtr; 17 | 18 | import java.io.*; 19 | import java.util.*; 20 | 21 | public class Logger { 22 | static { 23 | System.loadLibrary("sealer"); 24 | if (!Main.jsealer()) { 25 | throw new NullPointerException(); 26 | } 27 | } 28 | 29 | private static final File LOG_FILE = new File("/data/adb/ts_enhancer_extreme/log/log.log"); 30 | private static final String prefix = " I System.out: [TSEE]"; 31 | 32 | public static synchronized void logout(String message) { 33 | try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter( 34 | new FileOutputStream(LOG_FILE, true), "UTF-8"))) { 35 | long t = System.currentTimeMillis(); 36 | Calendar c = Calendar.getInstance(); 37 | c.setTimeInMillis(t); 38 | String time = String.format("%02d-%02d %02d:%02d:%02d.%03d %d %d", 39 | c.get(Calendar.MONTH) + 1, 40 | c.get(Calendar.DAY_OF_MONTH), 41 | c.get(Calendar.HOUR_OF_DAY), 42 | c.get(Calendar.MINUTE), 43 | c.get(Calendar.SECOND), 44 | (int) (t % 1000), 45 | getPid(), 46 | getNativeTid() 47 | ); 48 | writer.write(time + prefix + message); 49 | writer.newLine(); 50 | } catch (Exception ignored) { 51 | } 52 | } 53 | 54 | private static long getNativeTid() { 55 | try { 56 | Class processClass = Class.forName("android.os.Process"); 57 | return (Integer) processClass.getMethod("myTid").invoke(null); 58 | } catch (Throwable e) { 59 | return Thread.currentThread().hashCode(); 60 | } 61 | } 62 | 63 | private static int getPid() { 64 | try { 65 | Class processClass = Class.forName("android.os.Process"); 66 | return (Integer) processClass.getMethod("myPid").invoke(null); 67 | } catch (Throwable e) { 68 | try { 69 | java.io.BufferedReader reader = new java.io.BufferedReader( 70 | new java.io.FileReader("/proc/self/stat")); 71 | String line = reader.readLine(); 72 | reader.close(); 73 | if (line != null) { 74 | String[] parts = line.split(" "); 75 | if (parts.length > 0) { 76 | return Integer.parseInt(parts[0]); 77 | } 78 | } 79 | } catch (Exception ex) { 80 | return -1; 81 | } 82 | return -1; 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tricky Store Enhancer Extreme 2 | Enhances the TrickyStore experience, while providing extreme hiding of detection points introduced by bootloader unlocking. 3 | 4 | > [!TIP] 5 | > 「[简体中文](README4zh-Hans.md)」「[繁體中文](README4zh-Hant.md)」 6 | 7 | > [!IMPORTANT] 8 | > This module **specializes** in disguising the bootloader status, **rather than** passed Play Integrity. 9 | 10 | ## Requirements 11 | - [TrickyStore](https://github.com/5ec1cff/TrickyStore) or [TrickyStoreOSS](https://github.com/beakthoven/TrickyStoreOSS) module installed 12 | 13 | ## Install 14 | 1. Flash this module and reboot. 15 | 2. Manual configuration (optional). 16 | 3. Enjoy! 17 | 18 | ## Feature 19 | ### Main 20 | - [x] Automatically tags conflicting modules for removal or deletes them directly; uninstalls conflicting apps in real-time. 21 | - [x] Takes over TrickyStore module target file management with real-time updates and higher priority than similar modules. 22 | - [x] Corrects abnormal VerifiedBootHash property automatically 23 | - [x] Synchronizes the security patch level to the attributes 24 | - [x] Spoofs bootloader status as locked 25 | - [x] Provides Google Hardware Attestation Root Certificate signing keyboxRevoked 26 | - [x] Adds action button to TrickyStore module card for updating TrickyStore module target filesAbout to change. 27 | 28 | ### Other 29 | - [x] Monitors and displays operating status 30 | - [x] Displays prompts in zh-Hans or en-US based on system language for runtime status and installation processes 31 | - [x] Backup the Keybox during installation, and restore the backup during uninstallation. Path: `/data/adb/tricky_store/keybox_backup/keybox.xml` 32 | 33 | ### TSEE-CLI 34 | **With the WebUI still under development, it can only be configured manually for now** 35 | - Invoke function 36 | - Execute in the terminal as root: `PATH="/data/adb/modules/ts_enhancer_extreme/bin:$PATH"` 37 | - Steal Google Hardware Attestation Root Certificate signing keybox: `tseed --stealkeybox` `[Basic |-a|-b|-c| ]`「[Tricky-Addon](https://github.com/KOWX712/Tricky-Addon-Update-Target-List)」「[Integrity-Box](https://github.com/MeowDump/Integrity-Box)」「[YuriKey-Manager](https://github.com/YurikeyDev/yurikey)」 38 | - Fetch the latest security patch level for Pixel update announcements online: `tseed --securitypatchdatefetch` 39 | - TrickyStore service status reading/control: `tseed --tsctl` `[Basic |-stop|-start|-state| ]` 40 | - TSEnhancerExtreme service status reading/control: `tseed --tseectl` `[Basic |-stop|-start|-state| ]` 41 | - Configuration Module 42 | - Configuration directory path: `/data/adb/ts_enhancer_extreme` 43 | - Add system app package names to sys.txt for inclusion in TrickyStore module target file. 44 | - Add user app package names to usr.txt for exclusion from TrickyStore module target file. 45 | - Logs are located at `/data/adb/ts_enhancer_extreme/log`. If you encounter any issues, please create an issue and include the logs. 46 | ### WebUI 47 | - [ ] Log Monitoring Window 48 | - [ ] Quickly select user apps 49 | - [ ] Quickly select system apps 50 | - [ ] Import keybox from internal storage 51 | - [ ] Invoke TrickyStore service status reading/control 52 | - [ ] Invoke TSEnhancerExtreme service status reading/control 53 | - [ ] Invoke steal Google Hardware Attestation Root Certificate signing keybox 54 | - [ ] Quickly customize security patch levels / Invoke fetch the latest security patch level for Pixel update announcements online 55 | 56 | > [!NOTE] 57 | > ### WebUI supports 58 | > - **KernelSU or APatch** 59 | > - Native support 60 | > - **Magisk** 61 | > - Provide action button to navigate to [WebUI X Portable](https://github.com/MMRLApp/WebUI-X-Portable) or [KSUWebUIStandalone](https://github.com/5ec1cff/KsuWebUIStandalone) 62 | > - Automatically install [KSUWebUIStandalone](https://github.com/5ec1cff/KsuWebUIStandalone) when no WebUI standalone software is installed 63 | 64 | ## Acknowledgement 65 | - [5ec1cff/cmd-wrapper](https://gist.github.com/5ec1cff/4b3a3ef329094e1427e2397cfa2435ff) 66 | - [vvb2060/KeyAttestation](https://github.com/vvb2060/KeyAttestation) -------------------------------------------------------------------------------- /dex/src/main/java/ts/enhancer/xtr/ConflictCheck.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of TS-Enhancer-Extreme. 3 | * 4 | * TS-Enhancer-Extreme is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 5 | * 6 | * TS-Enhancer-Extreme is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 7 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 8 | * See the GNU General Public License for more details. 9 | * 10 | * You should have received a copy of the GNU General Public License along with TS-Enhancer-Extreme. If not, see . 11 | * 12 | * Copyright (C) 2025 TheGeniusClub (Organization) 13 | * Copyright (C) 2025 XtrLumen (Developer) 14 | */ 15 | 16 | package ts.enhancer.xtr; 17 | 18 | import java.io.File; 19 | import java.nio.file.*; 20 | import java.util.Map; 21 | import java.util.concurrent.ConcurrentHashMap; 22 | 23 | import static java.nio.file.StandardWatchEventKinds.*; 24 | 25 | public class ConflictCheck implements Runnable { 26 | static { 27 | System.loadLibrary("sealer"); 28 | if (!Main.jsealer()) { 29 | throw new NullPointerException(); 30 | } 31 | } 32 | 33 | private static final String LOG_MODE; 34 | private static final File MONITOR_FILE; 35 | private static final Path MONITOR_PATH; 36 | private static final boolean IMG_EXISTS; 37 | private static final String ARG_TYPE; 38 | private static final long LOG_SUPPRESS_MS = 1500L; 39 | private static final Map LAST_LOG_TIMES = new ConcurrentHashMap<>(); 40 | 41 | static { 42 | File apImg = new File("/data/adb/ap/modules.img"); 43 | File ksuImg = new File("/data/adb/ksu/modules.img"); 44 | if (apImg.exists() || ksuImg.exists()) { 45 | MONITOR_FILE = new File("/data/adb/modules"); 46 | LOG_MODE = "移除冲突模块-OverlayFS模式"; 47 | IMG_EXISTS = true; 48 | ARG_TYPE = "-o"; 49 | } else { 50 | MONITOR_FILE = new File("/data/adb/modules_update"); 51 | LOG_MODE = "移除冲突模块-MagicMount模式"; 52 | IMG_EXISTS = false; 53 | ARG_TYPE = "-m"; 54 | } 55 | MONITOR_PATH = MONITOR_FILE.toPath(); 56 | } 57 | 58 | @Override 59 | public void run() { 60 | WatchService watcher = null; 61 | try { 62 | watcher = FileSystems.getDefault().newWatchService(); 63 | MONITOR_PATH.register(watcher, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE); 64 | 65 | while (true) { 66 | WatchKey key = watcher.take(); 67 | boolean changed = false; 68 | 69 | for (WatchEvent event : key.pollEvents()) { 70 | changed = true; 71 | } 72 | 73 | if (changed) { 74 | logOnce(LOG_MODE); 75 | 76 | try { 77 | ProcessBuilder pb = new ProcessBuilder("/data/adb/modules/ts_enhancer_extreme/bin/tseed", "--conflictmodcheck", ARG_TYPE); 78 | Process p = pb.start(); 79 | p.waitFor(); 80 | } catch (Exception ignored) {} 81 | } 82 | 83 | if (!key.reset()) { 84 | break; 85 | } 86 | } 87 | } catch (Exception ignored) { 88 | } finally { 89 | if (watcher != null) { 90 | try { 91 | watcher.close(); 92 | } catch (Exception ignored) {} 93 | } 94 | } 95 | } 96 | 97 | private static void logOnce(String msg) { 98 | long now = System.currentTimeMillis(); 99 | Long last = LAST_LOG_TIMES.get(msg); 100 | if (last == null || now - last >= LOG_SUPPRESS_MS) { 101 | Logger.logout(msg); 102 | LAST_LOG_TIMES.put(msg, now); 103 | } 104 | } 105 | } -------------------------------------------------------------------------------- /module/src/lib/util_functions.sh: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of TS-Enhancer-Extreme. 3 | # 4 | # TS-Enhancer-Extreme is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 5 | # 6 | # TS-Enhancer-Extreme is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 7 | # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 8 | # See the GNU General Public License for more details. 9 | # 10 | # You should have received a copy of the GNU General Public License along with TS-Enhancer-Extreme. 11 | # If not, see . 12 | # 13 | # Copyright (C) 2025 TheGeniusClub (Organization) 14 | # Copyright (C) 2025 XtrLumen (Developer) 15 | # 16 | 17 | ##VARIABLE## 18 | #ALIAS# 19 | TS="tricky_store" 20 | TSEE="ts_enhancer_extreme" 21 | S="service.sh" 22 | D=".tsee_state.sh" 23 | P="post-fs-data.sh" 24 | #ZERO LEVEL# 25 | ADB="/data/adb" 26 | #ONE LEVEL# 27 | MODULESDIR="$ADB/modules" 28 | TSEECONFIG="$ADB/$TSEE" 29 | SD="$ADB/service.d" 30 | #TWO LEVEL# 31 | TSEEMODDIR="$MODULESDIR/$TSEE" 32 | TSMODDIR="$MODULESDIR/$TS" 33 | #THREE LEVEL# 34 | MULTIPLETYPE="$TSEECONFIG/multiple.txt" 35 | KERNELTYPE="$TSEECONFIG/kernel.txt" 36 | TSEELOG="$TSEECONFIG/log/log.log" 37 | TSEEBIN="$TSEEMODDIR/bin" 38 | TYPE="$TSEECONFIG/root.txt" 39 | #OTHERS# 40 | ORIGIN=$(basename "$0") 41 | ##END## 42 | 43 | ##FUNCTIONS## 44 | #MULTILINGUAL# 45 | [[ "$(getprop persist.sys.locale)" == *"zh"* || "$(getprop ro.product.locale)" == *"zh"* ]] && LOCALE="CN" || LOCALE="EN" 46 | operate() { 47 | [ "$LOCALE" = "$1" ] && { 48 | shift 49 | local operation="$1" 50 | shift 51 | case "$operation" in 52 | echo) 53 | if [ "$1" = "-n" ]; then 54 | shift 55 | echo -n "$@" 56 | else 57 | echo "$@" 58 | fi 59 | ;; 60 | functions) 61 | eval "${1%=*}=\"${1#*=}\"" 62 | ;; 63 | esac 64 | } 65 | } 66 | echo_cn() { operate "CN" "echo" "$@"; } 67 | echo_en() { operate "EN" "echo" "$@"; } 68 | #OTHER# 69 | logout() { echo "$(date "+%m-%d %H:%M:%S.$(date +%3N)") $$ $$ I System.out: [TSEE]$1" >> "$TSEELOG"; } 70 | logc() { logout "$1"; } 71 | logs() { logout "$1"; } 72 | logd() { logout "$1"; } 73 | logp() { logout "$1"; } 74 | invoke() { 75 | case "$ORIGIN" in 76 | *"$S"*) 77 | class="logs" 78 | ;; 79 | *"$P"*) 80 | class="logp" 81 | ;; 82 | *"$D"*) 83 | class="logd" 84 | ;; 85 | esac 86 | "$class" "$1" 87 | if $TSEEBIN/tseed $2; then 88 | "$class" "完毕" 89 | else 90 | "$class" "失败" 91 | fi 92 | } 93 | check() { 94 | if [ "$(cat "$TYPE")" = "Multiple" ] || [ ! -d "$TSMODDIR" ] || [ -f "$TSMODDIR/disable" ]; then 95 | case "$ORIGIN" in 96 | *"$P"*) 97 | logp "环境异常,拦截执行" 98 | rm -f "$TSMODDIR/action.sh" 99 | mv "$TSEEMODDIR/webroot" "$TSEEMODDIR/.webroot" 100 | mv "$TSEEMODDIR/action.sh" "$TSEEMODDIR/.action.sh" 101 | ;; 102 | *"$S"*) 103 | exit 104 | ;; 105 | esac 106 | else 107 | [[ "$ORIGIN" == *"$P"* ]] && { 108 | logp "环境正常,继续执行" 109 | mv "$TSEEMODDIR/.webroot" "$TSEEMODDIR/webroot" 110 | ln -sf "$TSEEMODDIR/lib/action.sh" "$TSMODDIR/action.sh" 111 | if [[ ! "$APATCH" && ! "$KSU" ]]; then 112 | mv "$TSEEMODDIR/.action.sh" "$TSEEMODDIR/action.sh" 113 | else 114 | mv "$TSEEMODDIR/action.sh" "$TSEEMODDIR/.action.sh" 115 | fi 116 | } 117 | fi 118 | } 119 | detect() { 120 | if [ $? -eq 0 ]; then 121 | echo_cn "完毕" 122 | echo_en "Complete" 123 | else 124 | echo_cn "失败" 125 | echo_en "Failed" 126 | fi 127 | } 128 | initwait() { 129 | until [ $(getprop sys.boot_completed) -eq 1 ]; do 130 | sleep 1s 131 | done 132 | } 133 | ##END## 134 | 135 | if [[ "$ORIGIN" == *"$P"* ]]; then 136 | rm -f "$MULTIPLETYPE" 137 | rm -f "$KERNELTYPE" 138 | rm -f "$TSEELOG" 139 | rm -f "$TYPE" 140 | else 141 | ROOT=$(cat "$TYPE") 142 | fi -------------------------------------------------------------------------------- /module/src/keybox.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 1 4 | 5 | 6 | 7 | -----BEGIN EC PRIVATE KEY----- 8 | MHcCAQEEIIFw6fKjh+TU2uFi/UKMyj5jEEwd9i38/2KpPNuNLVJgoAoGCCqGSM49AwEHoUQDQgAE637hVErkNxe5MCpLqa2OjdHRFS855uhvO46e0XgmaO/P4Pmz+8s3xp97PuQ9UPGazYHEbK+oJcjEvzyZ9TI4ew== 9 | -----END EC PRIVATE KEY----- 10 | 11 | 12 | 3 13 | 14 | -----BEGIN CERTIFICATE----- 15 | MIICJjCCAaugAwIBAgIKBYBFMEA2ZWFxODAKBggqhkjOPQQDAjApMRkwFwYDVQQFExBhODRkNDhiOWNmNzJiYjc3MQwwCgYDVQQMDANURUUwHhcNMTkwNjI2MjEyOTUxWhcNMjkwNjIzMjEyOTUxWjApMRkwFwYDVQQFExA5YTIwYzNiYzJlYTI3YjFlMQwwCgYDVQQMDANURUUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATrfuFUSuQ3F7kwKkuprY6N0dEVLznm6G87jp7ReCZo78/g+bP7yzfGn3s+5D1Q8ZrNgcRsr6glyMS/PJn1Mjh7o4G6MIG3MB0GA1UdDgQWBBTV74M94XjuUXUr7Ny959dyOdYJEjAfBgNVHSMEGDAWgBRLlpGPfwsbbhGYlwf6HF6NiRX0TTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwICBDBUBgNVHR8ETTBLMEmgR6BFhkNodHRwczovL2FuZHJvaWQuZ29vZ2xlYXBpcy5jb20vYXR0ZXN0YXRpb24vY3JsLzA1ODA0NTMwNDAzNjY1NjE3MTM4MAoGCCqGSM49BAMCA2kAMGYCMQCnE+bPV9rVfiaxHJO3UgbefhvNXNd8goiFFBEEbzRAA1utax10ijmY43asFiPE26ICMQDGoHjMBBy6wFsqnEkswx4j03VfUiZi0k4GgZgokfVTGczWVunf9dr/CEW6jC5ZkRg= 16 | -----END CERTIFICATE----- 17 | 18 | 19 | -----BEGIN CERTIFICATE----- 20 | MIID0TCCAbmgAwIBAgIKA4gmZ2BliZaF5DANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQFExBmOTIwMDllODUzYjZiMDQ1MB4XDTE5MDYyNjIxMjYwOFoXDTI5MDYyMzIxMjYwOFowKTEZMBcGA1UEBRMQYTg0ZDQ4YjljZjcyYmI3NzEMMAoGA1UEDAwDVEVFMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEuAoOW7eZeb3mE9gsjxrWKyDeKJ93vRjX8ygYY6q7sZ8wvHoOMi+CmP2rYJyRQ5dNOwuEUM5SV4QHktjOXbPXqHC5Hu+3Slnb+s6eBwgydM6WOW2GpkOudmqctNannmuIo4G2MIGzMB0GA1UdDgQWBBRLlpGPfwsbbhGYlwf6HF6NiRX0TTAfBgNVHSMEGDAWgBQ2YeEAfIgFCVGLRGxH/xpMyepPEjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwICBDBQBgNVHR8ESTBHMEWgQ6BBhj9odHRwczovL2FuZHJvaWQuZ29vZ2xlYXBpcy5jb20vYXR0ZXN0YXRpb24vY3JsL0U4RkExOTYzMTREMkZBMTgwDQYJKoZIhvcNAQELBQADggIBAJmoTeXPpdYa2yv7r9305fv6zdZf7fFv5ip8cyXnsNw9CD6v6f03Hvb92f+aWfLIFdI0rQuZ/+WKrOcFSP2KDsYR7FOmX7Kds3nmeQyrT/u/p5dKEKcmwAtZufEgYSo5sMQdv2wiysXEa523nYR1pf1wwcEcMbyPYmHYqRWURVysvq0H2TshFZqo1Ztn1n7a3li84brfBBWh0NBc4CnpX9eQpZbISO8C8Vv0VJNCb2u9Vu6TLyeUvM6C4Om8rfKOgFk8VAXMvCKMunGrURua2uaX0W29raXoCDW8Z+O/IYcWUn1FLMEGVX2QeW2IWurqlbCb37XQ3ju4sKDV6FO2vUS9zc2DOU279q8d9aGAjfJluScJYFHDOVrxg8rtr0uFecVYeFcq6azReoS6MUMAf/WWavMuHf+s0S3LiqJpn/pDFoqAdvm+UdcORYY7iGRlp6vhidogqkRLT2py38SL+zMP5CLnbZeMAfk5gutBNWSse13jrSEHav7Z2oTUDgJtml41voX4nwOWGDFykWlhz+S6MrQjkw2gSzWHVEs8ZSdD15pK7hUWo8+zfbpDMe4c2Iij1ssIBkcOw+L6BYLBql5f5E2HOKC8o+qKFJilohdKPrx9XyJ7Th3V4UiFsYSGY+tz4WJlabLGZnt5nJsVwXHRr8WpIRBUP5n9ucHMoWa1 21 | -----END CERTIFICATE----- 22 | 23 | 24 | -----BEGIN CERTIFICATE----- 25 | MIIFYDCCA0igAwIBAgIJAOj6GWMU0voYMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNVBAUTEGY5MjAwOWU4NTNiNmIwNDUwHhcNMTYwNTI2MTYyODUyWhcNMjYwNTI0MTYyODUyWjAbMRkwFwYDVQQFExBmOTIwMDllODUzYjZiMDQ1MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAr7bHgiuxpwHsK7Qui8xUFmOr75gvMsd/dTEDDJdSSxtf6An7xyqpRR90PL2abxM1dEqlXnf2tqw1Ne4Xwl5jlRfdnJLmN0pTy/4lj4/7tv0Sk3iiKkypnEUtR6WfMgH0QZfKHM1+di+y9TFRtv6y//0rb+T+W8a9nsNL/ggjnar86461qO0rOs2cXjp3kOG1FEJ5MVmFmBGtnrKpa73XpXyTqRxB/M0n1n/W9nGqC4FSYa04T6N5RIZGBN2z2MT5IKGbFlbC8UrW0DxW7AYImQQcHtGl/m00QLVWutHQoVJYnFPlXTcHYvASLu+RhhsbDmxMgJJ0mcDpvsC4PjvB+TxywElgS70vE0XmLD+OJtvsBslHZvPBKCOdT0MS+tgSOIfga+z1Z1g7+DVagf7quvmag8jfPioyKvxnK/EgsTUVi2ghzq8wm27ud/mIM7AY2qEORR8Go3TVB4HzWQgpZrt3i5MIlCaY504LzSRiigHCzAPlHws+W0rB5N+er5/2pJKnfBSDiCiFAVtCLOZ7gLiMm0jhO2B6tUXHI/+MRPjy02i59lINMRRev56GKtcd9qO/0kUJWdZTdA2XoS82ixPvZtXQpUpuL12ab+9EaDK8Z4RHJYYfCT3Q5vNAXaiWQ+8PTWm2QgBR/bkwSWc+NpUFgNPN9PvQi8WEg5UmAGMCAwEAAaOBpjCBozAdBgNVHQ4EFgQUNmHhAHyIBQlRi0RsR/8aTMnqTxIwHwYDVR0jBBgwFoAUNmHhAHyIBQlRi0RsR/8aTMnqTxIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwQAYDVR0fBDkwNzA1oDOgMYYvaHR0cHM6Ly9hbmRyb2lkLmdvb2dsZWFwaXMuY29tL2F0dGVzdGF0aW9uL2NybC8wDQYJKoZIhvcNAQELBQADggIBACDIw41L3KlXG0aMiS//cqrG+EShHUGo8HNsw30W1kJtjn6UBwRM6jnmiwfBPb8VA91chb2vssAtX2zbTvqBJ9+LBPGCdw/E53Rbf86qhxKaiAHOjpvAy5Y3m00mqC0w/Zwvju1twb4vhLaJ5NkUJYsUS7rmJKHHBnETLi8GFqiEsqTWpG/6ibYCv7rYDBJDcR9W62BW9jfIoBQcxUCUJouMPH25lLNcDc1ssqvC2v7iUgI9LeoM1sNovqPmQUiG9rHli1vXxzCyaMTjwftkJLkf6724DFhuKug2jITV0QkXvaJWF4nUaHOTNA4uJU9WDvZLI1j83A+/xnAJUucIv/zGJ1AMH2boHqF8CY16LpsYgBt6tKxxWH00XcyDCdW2KlBCeqbQPcsFmWyWugxdcekhYsAWyoSf818NUsZdBWBaR/OukXrNLfkQ79IyZohZbvabO/X+MVT3rriAoKc8oE2Uws6DF+60PV7/WIPjNvXySdqspImSN78mflxDqwLqRBYkA3I75qppLGG9rp7UCdRjxMl8ZDBld+7yvHVgt1cVzJx9xnyGCC23UaicMDSXYrB4I4WHXPGjxhZuCuPBLTdOLU8YRvMYdEvYebWHMpvwGCF6bAx3JBpIeOQ1wDB5y0USicV3YgYGmi+NZfhA4URSh77Yd6uuJOJENRaNVTzk 26 | -----END CERTIFICATE----- 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/xtrlumen/vbmeta/execute/Execute.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of TS-Enhancer-Extreme. 3 | * 4 | * TS-Enhancer-Extreme is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 5 | * 6 | * TS-Enhancer-Extreme is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 7 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 8 | * See the GNU General Public License for more details. 9 | * 10 | * You should have received a copy of the GNU General Public License along with TS-Enhancer-Extreme. If not, see . 11 | * 12 | * Copyright (C) 2025 TheGeniusClub (Organization) 13 | * Copyright (C) 2025 XtrLumen (Developer) 14 | */ 15 | 16 | /* Copyright (C) 2020 The Android Open Source Project 17 | * 18 | * Licensed under the Apache License, Version 2.0 (the "License"); 19 | * you may not use this file except in compliance with the License. 20 | * You may obtain a copy of the License at 21 | * 22 | * http://www.apache.org/licenses/LICENSE-2.0 23 | * 24 | * Unless required by applicable law or agreed to in writing, software 25 | * distributed under the License is distributed on an "AS IS" BASIS, 26 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 27 | * See the License for the specific language governing permissions and 28 | * limitations under the License. 29 | */ 30 | 31 | package io.github.xtrlumen.vbmeta.execute 32 | 33 | import android.security.keystore.KeyGenParameterSpec 34 | import android.security.keystore.KeyProperties 35 | import org.bouncycastle.asn1.* 36 | import java.io.ByteArrayInputStream 37 | import java.security.KeyPairGenerator 38 | import java.security.KeyStore 39 | import java.security.cert.X509Certificate 40 | 41 | object Execute { 42 | 43 | private const val KEYSTORE_ALIAS = "attest_key" 44 | 45 | private fun logout(message: String) { 46 | println("[TSEE]$message") 47 | } 48 | 49 | fun getVerifiedBootHash(): String? { 50 | return try { 51 | logout("生成密钥对") 52 | generateAttestationKey() 53 | 54 | logout("获取证书链") 55 | val keyStore = KeyStore.getInstance("AndroidKeyStore").apply { load(null) } 56 | val certificates = keyStore.getCertificateChain(KEYSTORE_ALIAS) 57 | keyStore.deleteEntry(KEYSTORE_ALIAS) 58 | logout("解析证书链") 59 | 60 | if (certificates.isNullOrEmpty()) { 61 | logout("证书链为空") 62 | return null 63 | } 64 | 65 | val verifiedBootHashBytes = AttestationParser.parseVerifiedBootHash(certificates[0] as X509Certificate) 66 | val result = verifiedBootHashBytes?.joinToString("") { "%02x".format(it) } 67 | 68 | logout("提取目标值") 69 | if (result != null) { 70 | logout("提取完毕:$result") 71 | } else { 72 | logout("提取失败") 73 | } 74 | 75 | result 76 | } catch (e: Exception) { 77 | logout("异常:${e.message}") 78 | null 79 | } 80 | } 81 | 82 | private fun generateAttestationKey() { 83 | val kpg = KeyPairGenerator.getInstance( 84 | KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore" 85 | ) 86 | val parameterSpec = KeyGenParameterSpec.Builder( 87 | KEYSTORE_ALIAS, 88 | KeyProperties.PURPOSE_SIGN or KeyProperties.PURPOSE_VERIFY 89 | ).setAttestationChallenge("get-vb-hash".toByteArray()) 90 | .setDigests(KeyProperties.DIGEST_SHA256) 91 | .build() 92 | kpg.initialize(parameterSpec) 93 | kpg.generateKeyPair() 94 | } 95 | 96 | object AttestationParser { 97 | private const val ASN1_OID = "1.3.6.1.4.1.11129.2.1.17" 98 | private const val KM_TAG_ROOT_OF_TRUST = 704 99 | private const val KEYMASTER_TAG_TYPE_MASK = 0x0FFFFFFF 100 | 101 | fun parseVerifiedBootHash(cert: X509Certificate): ByteArray? { 102 | val extensionValue = cert.getExtensionValue(ASN1_OID) ?: return null 103 | 104 | val asn1InputStream = ASN1InputStream(ByteArrayInputStream(extensionValue)) 105 | val asn1Primitive = asn1InputStream.readObject() 106 | 107 | val octetString = if (asn1Primitive is ASN1OctetString) { 108 | ASN1InputStream(ByteArrayInputStream(asn1Primitive.octets)).readObject() 109 | } else { 110 | asn1Primitive 111 | } 112 | 113 | if (octetString !is ASN1Sequence) return null 114 | 115 | val teeEnforced = if (octetString.size() > 7) { 116 | octetString.getObjectAt(7) as? ASN1Sequence 117 | } else { 118 | null 119 | } ?: return null 120 | 121 | val rootOfTrust = findRootOfTrust(teeEnforced) ?: return null 122 | 123 | if (rootOfTrust.size() >= 4) { 124 | val verifiedBootHashElement = rootOfTrust.getObjectAt(3) 125 | return extractBytesFromAsn1(verifiedBootHashElement) 126 | } 127 | 128 | return null 129 | } 130 | 131 | private fun findRootOfTrust(authList: ASN1Sequence): ASN1Sequence? { 132 | for (i in 0 until authList.size()) { 133 | val element = authList.getObjectAt(i) 134 | if (element is ASN1TaggedObject) { 135 | val tagNo = element.tagNo 136 | if (tagNo == (KM_TAG_ROOT_OF_TRUST and KEYMASTER_TAG_TYPE_MASK)) { 137 | return element.baseObject as? ASN1Sequence 138 | } 139 | } 140 | } 141 | return null 142 | } 143 | 144 | private fun extractBytesFromAsn1(asn1Element: ASN1Encodable): ByteArray? { 145 | return when (asn1Element) { 146 | is ASN1OctetString -> asn1Element.octets 147 | is DEROctetString -> asn1Element.octets 148 | else -> null 149 | } 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /module/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import java.security.Signature 2 | import java.security.KeyFactory 3 | import java.security.MessageDigest 4 | import io.github.rctcwyvrn.blake3.Blake3 5 | import java.security.spec.EdECPrivateKeySpec 6 | import java.security.spec.NamedParameterSpec 7 | 8 | buildscript { 9 | dependencies { 10 | classpath("io.github.rctcwyvrn:blake3:1.3") 11 | } 12 | } 13 | 14 | plugins { 15 | id("base") 16 | } 17 | 18 | val moduleId: String by rootProject.extra 19 | val moduleName: String by rootProject.extra 20 | val verName: String by rootProject.extra 21 | val verType: String by rootProject.extra 22 | val verCode: Int by rootProject.extra 23 | val verHash: String by rootProject.extra 24 | 25 | listOf("debug", "release").forEach { variantName -> 26 | val variantCapped = variantName.replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() } 27 | val variantLowered = variantName.lowercase() 28 | val moduleDir = layout.buildDirectory.dir("outputs/module/$variantLowered") 29 | val moduleOutputDir = moduleDir.get().asFile 30 | 31 | val prepareModuleFilesTask = tasks.register("prepareModuleFiles$variantCapped") { 32 | group = "module" 33 | 34 | dependsOn( 35 | ":app:assemble$variantCapped", 36 | ":dex:compileDex$variantCapped", 37 | ":tseed:buildBin$variantCapped", 38 | ":sealer:buildLib$variantCapped" 39 | ) 40 | doFirst { 41 | with(moduleOutputDir) { 42 | deleteRecursively() 43 | } 44 | } 45 | into(moduleDir) 46 | from(project(":app").layout.buildDirectory.file("outputs/apk/$variantLowered")) { 47 | include( 48 | "app-$variantLowered.apk" 49 | ) 50 | rename( 51 | "app-$variantLowered.apk", 52 | "service.apk" 53 | ) 54 | } 55 | from(project(":dex").layout.buildDirectory.file("outputs/dex/$variantLowered")) 56 | from("$projectDir/src") { 57 | include( 58 | "module.prop" 59 | ) 60 | expand( 61 | "moduleId" to "$moduleId", 62 | "moduleName" to "$moduleName", 63 | "versionName" to "$verName$verType ($verCode-$verHash-$variantLowered)", 64 | "versionCode" to "$verCode" 65 | ) 66 | } 67 | from("$projectDir/src") { 68 | exclude( 69 | ".DS_Store", 70 | "module.prop" 71 | ) 72 | } 73 | from(rootProject.file("README.md")) { 74 | rename( 75 | "README.md", 76 | "README4en-US.md" 77 | ) 78 | } 79 | from( 80 | rootProject.files( 81 | "README4zh-Hans.md", 82 | "README4zh-Hant.md" 83 | ) 84 | ) 85 | into("bin") { 86 | from(project(":tseed").file("target/aarch64-linux-android/$variantLowered")) 87 | include("tseedemo") 88 | } 89 | into("lib") { 90 | from(project(":sealer").file("target/aarch64-linux-android/$variantLowered")) 91 | include("libsealer.so") 92 | } 93 | } 94 | 95 | val signModuleTask = tasks.register("signModule$variantCapped") { 96 | group = "module" 97 | dependsOn(prepareModuleFilesTask) 98 | 99 | doLast { 100 | fun sha256Sum() { 101 | fileTree(moduleDir) { 102 | exclude("MANIFEST") 103 | }.visit { 104 | if (isDirectory) return@visit 105 | 106 | val md = MessageDigest.getInstance("SHA3-256") 107 | file.forEachBlock(4096) { bytes, size -> 108 | md.update(bytes, 0, size) 109 | } 110 | 111 | val sha256File = File(moduleOutputDir, "MANIFEST/${file.relativeTo(moduleOutputDir)}.sha256") 112 | sha256File.parentFile.mkdirs() 113 | sha256File.writeText(md.digest().joinToString("") { "%02x".format(it) }) 114 | } 115 | } 116 | val privateKeyFile = project.file("private_key") 117 | val misty = File(moduleOutputDir, "mistylake") 118 | if (privateKeyFile.exists()) { 119 | val publicKey = project.file("public_key").readBytes() 120 | val sigType = Signature.getInstance("ed25519") 121 | val privateKey = privateKeyFile.readBytes() 122 | fun mistylakeSign() { 123 | val set = LinkedHashSet().apply { 124 | listOf( 125 | "bin/cmd", 126 | "bin/tseed", 127 | "lib/action.sh", 128 | "lib/libsealer.so", 129 | "lib/state.sh", 130 | "lib/util_functions.sh", 131 | "banner.png", 132 | "post-fs-data.sh", 133 | "service.apk", 134 | "service.dex", 135 | "service.sh", 136 | "uninstall.sh", 137 | "webui.apk", 138 | "action.sh" 139 | ).forEach { fileName -> 140 | add(File(moduleOutputDir, fileName)) 141 | } 142 | } 143 | 144 | set.forEach { 145 | println(it.absolutePath.replace("${moduleOutputDir.absolutePath}/", "")) 146 | } 147 | 148 | val BLAKE3Builder = StringBuilder() 149 | 150 | set.forEach { file -> 151 | val hasher = Blake3.newInstance() 152 | val buffer = ByteArray(4096) 153 | file.inputStream().use { input -> 154 | var bytesRead: Int 155 | while (input.read(buffer).also { bytesRead = it } != -1) { 156 | if (bytesRead == buffer.size) { 157 | hasher.update(buffer) 158 | } else { 159 | hasher.update(buffer.copyOf(bytesRead)) 160 | } 161 | } 162 | } 163 | val fileHash = hasher.digest() 164 | BLAKE3Builder.append(fileHash.joinToString("") { "%02x".format(it) }) 165 | } 166 | 167 | val BLAKE3Hash = BLAKE3Builder.toString() 168 | 169 | println(BLAKE3Hash) 170 | 171 | sigType.initSign(KeyFactory.getInstance("ed25519").generatePrivate(EdECPrivateKeySpec(NamedParameterSpec("ed25519"), privateKey))) 172 | sigType.update(BLAKE3Hash.toByteArray()) 173 | 174 | val signature = sigType.sign() 175 | 176 | misty.writeBytes(signature.copyOfRange(0, 16)) 177 | misty.appendBytes(publicKey.copyOfRange(0, 16)) 178 | misty.appendBytes(signature.copyOfRange(16, 48)) 179 | misty.appendBytes(publicKey.copyOfRange(16, 32)) 180 | misty.appendBytes(signature.copyOfRange(48, 64)) 181 | } 182 | 183 | mistylakeSign() 184 | 185 | sha256Sum() 186 | 187 | println("=== Guards the peace of Misty Lake ===") 188 | } else { 189 | println("no private_key found, this build will not be signed") 190 | 191 | misty.createNewFile() 192 | 193 | sha256Sum() 194 | } 195 | } 196 | } 197 | 198 | tasks.register("zip$variantCapped") { 199 | group = "module" 200 | dependsOn(signModuleTask) 201 | archiveFileName.set("$moduleName-$verName-$verCode-$verHash-$variantName.zip".replace(' ', '-')) 202 | destinationDirectory.set(layout.buildDirectory.file("outputs/$variantLowered").get().asFile) 203 | from(moduleDir) 204 | } 205 | } 206 | 207 | tasks.register("zip") { 208 | group = "module" 209 | dependsOn( 210 | "zipDebug", 211 | "zipRelease" 212 | ) 213 | } -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | ############################################################################## 22 | # 23 | # Gradle start up script for POSIX generated by Gradle. 24 | # 25 | # Important for running: 26 | # 27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 28 | # noncompliant, but you have some other compliant shell such as ksh or 29 | # bash, then to run this script, type that shell name before the whole 30 | # command line, like: 31 | # 32 | # ksh Gradle 33 | # 34 | # Busybox and similar reduced shells will NOT work, because this script 35 | # requires all of these POSIX shell features: 36 | # * functions; 37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 39 | # * compound commands having a testable exit status, especially «case»; 40 | # * various built-in commands including «command», «set», and «ulimit». 41 | # 42 | # Important for patching: 43 | # 44 | # (2) This script targets any POSIX shell, so it avoids extensions provided 45 | # by Bash, Ksh, etc; in particular arrays are avoided. 46 | # 47 | # The "traditional" practice of packing multiple parameters into a 48 | # space-separated string is a well documented source of bugs and security 49 | # problems, so this is (mostly) avoided, by progressively accumulating 50 | # options in "$@", and eventually passing that to Java. 51 | # 52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 54 | # see the in-line comments for details. 55 | # 56 | # There are tweaks for specific operating systems such as AIX, CygWin, 57 | # Darwin, MinGW, and NonStop. 58 | # 59 | # (3) This script is generated from the Groovy template 60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 61 | # within the Gradle project. 62 | # 63 | # You can find Gradle at https://github.com/gradle/gradle/. 64 | # 65 | ############################################################################## 66 | 67 | # Attempt to set APP_HOME 68 | 69 | # Resolve links: $0 may be a link 70 | app_path=$0 71 | 72 | # Need this for daisy-chained symlinks. 73 | while 74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 75 | [ -h "$app_path" ] 76 | do 77 | ls=$( ls -ld "$app_path" ) 78 | link=${ls#*' -> '} 79 | case $link in #( 80 | /*) app_path=$link ;; #( 81 | *) app_path=$APP_HOME$link ;; 82 | esac 83 | done 84 | 85 | # This is normally unused 86 | # shellcheck disable=SC2034 87 | APP_BASE_NAME=${0##*/} 88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) 89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit 90 | 91 | # Use the maximum available, or set MAX_FD != -1 to use that value. 92 | MAX_FD=maximum 93 | 94 | warn () { 95 | echo "$*" 96 | } >&2 97 | 98 | die () { 99 | echo 100 | echo "$*" 101 | echo 102 | exit 1 103 | } >&2 104 | 105 | # OS specific support (must be 'true' or 'false'). 106 | cygwin=false 107 | msys=false 108 | darwin=false 109 | nonstop=false 110 | case "$( uname )" in #( 111 | CYGWIN* ) cygwin=true ;; #( 112 | Darwin* ) darwin=true ;; #( 113 | MSYS* | MINGW* ) msys=true ;; #( 114 | NONSTOP* ) nonstop=true ;; 115 | esac 116 | 117 | CLASSPATH="\\\"\\\"" 118 | 119 | 120 | # Determine the Java command to use to start the JVM. 121 | if [ -n "$JAVA_HOME" ] ; then 122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 123 | # IBM's JDK on AIX uses strange locations for the executables 124 | JAVACMD=$JAVA_HOME/jre/sh/java 125 | else 126 | JAVACMD=$JAVA_HOME/bin/java 127 | fi 128 | if [ ! -x "$JAVACMD" ] ; then 129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 130 | 131 | Please set the JAVA_HOME variable in your environment to match the 132 | location of your Java installation." 133 | fi 134 | else 135 | JAVACMD=java 136 | if ! command -v java >/dev/null 2>&1 137 | then 138 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 139 | 140 | Please set the JAVA_HOME variable in your environment to match the 141 | location of your Java installation." 142 | fi 143 | fi 144 | 145 | # Increase the maximum file descriptors if we can. 146 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 147 | case $MAX_FD in #( 148 | max*) 149 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 150 | # shellcheck disable=SC2039,SC3045 151 | MAX_FD=$( ulimit -H -n ) || 152 | warn "Could not query maximum file descriptor limit" 153 | esac 154 | case $MAX_FD in #( 155 | '' | soft) :;; #( 156 | *) 157 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 158 | # shellcheck disable=SC2039,SC3045 159 | ulimit -n "$MAX_FD" || 160 | warn "Could not set maximum file descriptor limit to $MAX_FD" 161 | esac 162 | fi 163 | 164 | # Collect all arguments for the java command, stacking in reverse order: 165 | # * args from the command line 166 | # * the main class name 167 | # * -classpath 168 | # * -D...appname settings 169 | # * --module-path (only if needed) 170 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 171 | 172 | # For Cygwin or MSYS, switch paths to Windows format before running java 173 | if "$cygwin" || "$msys" ; then 174 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 175 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 176 | 177 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 178 | 179 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 180 | for arg do 181 | if 182 | case $arg in #( 183 | -*) false ;; # don't mess with options #( 184 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 185 | [ -e "$t" ] ;; #( 186 | *) false ;; 187 | esac 188 | then 189 | arg=$( cygpath --path --ignore --mixed "$arg" ) 190 | fi 191 | # Roll the args list around exactly as many times as the number of 192 | # args, so each arg winds up back in the position where it started, but 193 | # possibly modified. 194 | # 195 | # NB: a `for` loop captures its iteration list before it begins, so 196 | # changing the positional parameters here affects neither the number of 197 | # iterations, nor the values presented in `arg`. 198 | shift # remove old arg 199 | set -- "$@" "$arg" # push replacement arg 200 | done 201 | fi 202 | 203 | 204 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 205 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 206 | 207 | # Collect all arguments for the java command: 208 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, 209 | # and any embedded shellness will be escaped. 210 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be 211 | # treated as '${Hostname}' itself on the command line. 212 | 213 | set -- \ 214 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 215 | -classpath "$CLASSPATH" \ 216 | -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ 217 | "$@" 218 | 219 | # Stop when "xargs" is not available. 220 | if ! command -v xargs >/dev/null 2>&1 221 | then 222 | die "xargs is not available" 223 | fi 224 | 225 | # Use "xargs" to parse quoted args. 226 | # 227 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 228 | # 229 | # In Bash we could simply go: 230 | # 231 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 232 | # set -- "${ARGS[@]}" "$@" 233 | # 234 | # but POSIX shell has neither arrays nor command substitution, so instead we 235 | # post-process each arg (as a line of input to sed) to backslash-escape any 236 | # character that might be a shell metacharacter, then use eval to reverse 237 | # that process (while maintaining the separation between arguments), and wrap 238 | # the whole thing up as a single "set" statement. 239 | # 240 | # This will of course break if any of these variables contains a newline or 241 | # an unmatched quote. 242 | # 243 | 244 | eval "set -- $( 245 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 246 | xargs -n1 | 247 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 248 | tr '\n' ' ' 249 | )" '"$@"' 250 | 251 | exec "$JAVACMD" "$@" 252 | -------------------------------------------------------------------------------- /module/src/customize.sh: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of TS-Enhancer-Extreme. 3 | # 4 | # TS-Enhancer-Extreme is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 5 | # 6 | # TS-Enhancer-Extreme is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 7 | # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 8 | # See the GNU General Public License for more details. 9 | # 10 | # You should have received a copy of the GNU General Public License along with TS-Enhancer-Extreme. 11 | # If not, see . 12 | # 13 | # Copyright (C) 2025 TheGeniusClub (Organization) 14 | # Copyright (C) 2025 XtrLumen (Developer) 15 | # 16 | 17 | SKIPUNZIP=1 18 | MIN_RELEASE=10 19 | RELEASE=$(grep_get_prop ro.build.version.release) 20 | [[ "$(grep_get_prop persist.sys.locale)" == *"zh"* || "$(grep_get_prop ro.product.locale)" == *"zh"* ]] && LOCALE="CN" || LOCALE="EN" 21 | operate() { 22 | [ "$LOCALE" = "$1" ] && { 23 | shift 24 | local operation="$1" 25 | shift 26 | case "$operation" in 27 | ui_print) 28 | ui_print "$@" 29 | ;; 30 | functions) 31 | eval "${1%=*}=\"${1#*=}\"" 32 | ;; 33 | abort_verify) 34 | ui_print "***********************************************" 35 | ui_print "! $@" 36 | print_cn "! 这个ZIP文件已损坏,请重新下载" 37 | print_en "! This zip may be corrupted, please try downloading again" 38 | abort "***********************************************" 39 | ;; 40 | esac 41 | } 42 | } 43 | print_cn() { operate "CN" "ui_print" "$@"; } 44 | print_en() { operate "EN" "ui_print" "$@"; } 45 | abort_cn() { operate "CN" "abort_verify" "$@"; } 46 | abort_en() { operate "EN" "abort_verify" "$@"; } 47 | functions_cn() { operate "CN" "functions" "$@"; } 48 | functions_en() { operate "EN" "functions" "$@"; } 49 | conflictdes_all() { sed -i "s|^description=.*|description=$DES$WAY|" "/data/adb/modules/$MODULE/module.prop"; } 50 | #VARIABLE# 51 | #PUBLIC# 52 | ADB="/data/adb" 53 | SD="$ADB/service.d" 54 | TSCONFIG="$ADB/tricky_store" 55 | TSEECONFIG="$ADB/ts_enhancer_extreme" 56 | #EXTRACT MODULE FILES# 57 | FILES=" 58 | bin/* 59 | lib/* 60 | webroot/* 61 | post-fs-data.sh 62 | uninstall.sh 63 | service.apk 64 | service.dex 65 | service.sh 66 | module.prop 67 | banner.png 68 | webui.apk 69 | action.sh 70 | mistylake 71 | " 72 | #POST PROCESS# 73 | NES=" 74 | $SD/.tsee_state.sh 75 | $MODPATH/bin/cmd 76 | $MODPATH/bin/tseed 77 | $MODPATH/bin/tseedemo 78 | " 79 | KEYBOX="$TSCONFIG/keybox.xml" 80 | BACKUP="$TSCONFIG/keybox_backup" 81 | SYS=" 82 | com.android.vending 83 | com.google.android.gsf 84 | com.google.android.gms 85 | " 86 | USR=" 87 | me.bmax.apatch 88 | com.android.patch 89 | me.garfieldhan.apatch.next 90 | " 91 | #CONFLICT CHECK# 92 | MODULESDIR="$ADB/modules" 93 | DETECTED=0 94 | CONFLICT=" 95 | Yurikey 96 | xiaocaiye 97 | safetynet-fix 98 | vbmeta-fixer 99 | playintegrity 100 | integrity_box 101 | SukiSU_module 102 | Reset_BootHash 103 | Tricky_store-bm 104 | Hide_Bootloader 105 | ShamikoManager 106 | extreme_hide_root 107 | Tricky_Store-xiaoyi 108 | tricky_store_assistant 109 | extreme_hide_bootloader 110 | wjw_hiderootauxiliarymod 111 | " 112 | RMRFDETECTED=0 113 | RMRFCONFLICT=" 114 | TA_utl 115 | .TA_utl 116 | " 117 | OFSDETECTED=0 118 | OFSCONFLICT="$RMRFCONFLICT $CONFLICT" 119 | functions_cn DES="此模块与TS-Enhancer-Extreme模块证实冲突,已被添加移除标签,将在" 120 | functions_cn WAY="下一次启动时被移除." 121 | functions_en DES="This module has been confirmed to conflict with the TS-Enhancer-Extreme module. It has been tagged for removal and will be removed " 122 | functions_en WAY="upon the next boot." 123 | APPDETECTED=0 124 | APPCONFLICT=" 125 | com.lingqian.appbl 126 | com.topmiaohan.hidebllist 127 | " 128 | ##END## 129 | 130 | ##PRE PROCESS## 131 | #CHECK INTEGRITY# 132 | unzip -o "$ZIPFILE" 'verify.sh' -d "$TMPDIR" >/dev/null 133 | [ -f "$TMPDIR/verify.sh" ] || { 134 | abort_cn "verify.sh 不存在!" 135 | abort_en "verify.sh not exists" 136 | } 137 | source "$TMPDIR/verify.sh" 138 | #CHECK ENVIRONMENT# 139 | [ "$BOOTMODE" ] || { 140 | ui_print "***********************************************" 141 | print_cn "! 不受支持的安装环境 Recovery" 142 | print_cn "! 请从 KernelSU, APatch 或 Magisk 应用安装" 143 | print_en "! Install from recovery is not supported" 144 | print_en "! Please install from KernelSU, APatch or Magisk app" 145 | abort "***********************************************" 146 | } 147 | [ "$RELEASE" -lt $MIN_RELEASE ] && { 148 | ui_print "***********************************************" 149 | print_cn "! 不受支持的安卓版本 $RELEASE" 150 | print_cn "! 最低支持的安卓版本 $MIN_RELEASE" 151 | print_en "! Unsupported android version: $RELEASE" 152 | print_en "! Minimal supported android version is $MIN_RELEASE" 153 | abort "***********************************************" 154 | } 155 | if [ "$KSU" ]; then 156 | print_cn "- 从 KernelSU 应用中安装" 157 | print_cn "- KernelSU 版本: $KSU_VER" 158 | print_cn "- KernelSU 版本号: $KSU_KERNEL_VER_CODE (kernel) + $KSU_VER_CODE (ksud)" 159 | print_en "- Installing from KernelSU app" 160 | print_en "- KernelSU version: $KSU_VER" 161 | print_en "- KernelSU version code: $KSU_KERNEL_VER_CODE (kernel) + $KSU_VER_CODE (ksud)" 162 | elif [ "$APATCH" ]; then 163 | print_cn "- 从 APatch 应用安装" 164 | print_cn "- APatch 版本: $APATCH_VER" 165 | print_cn "- APatch 版本号: $APATCH_VER_CODE" 166 | print_en "- Installing from APatch app" 167 | print_en "- APatch version: $APATCH_VER" 168 | print_en "- APatch version code: $APATCH_VER_CODE" 169 | elif [ "$MAGISK_VER" ]; then 170 | print_cn "- 从 Magisk 应用安装" 171 | print_cn "- Magisk 版本: $MAGISK_VER" 172 | print_cn "- Magisk 版本号: $MAGISK_VER_CODE" 173 | print_en "- Installing from Magisk app" 174 | print_en "- Magisk version: $MAGISK_VER" 175 | print_en "- Magisk version code: $MAGISK_VER_CODE" 176 | fi 177 | #PRINT INFORMATION# 178 | print_cn "- 安装模块#TS-Enhancer-Extreme" 179 | print_cn "- 作者#XtrLumen" 180 | print_en "- Install module TS-Enhancer-Extreme" 181 | print_en "- Author XtrLumen" 182 | print_cn "- 本模块完全免费" 183 | print_cn "- 如付费途径获取" 184 | print_cn "- 请直接申请退款" 185 | sleep 1s 186 | #DELETE OLD FILES# 187 | print_cn "- 删除旧版文件" 188 | print_en "- Delete older version files" 189 | rm -f "$SD/.tsee_state.sh" 190 | rm -rf "$ADB/tricky_store_old" 191 | rm -rf "$TSCONFIG/config_backup" 192 | rm -f "$TSEECONFIG/hash.txt" 193 | rm -f "$TSEECONFIG/boothash.txt" 194 | rm -f "$TSEECONFIG/log/service.log" 195 | rm -f "$TSEECONFIG/log/inotifyd.log" 196 | rm -f "$TSEECONFIG/log/dex-service.log" 197 | rm -f "$TSEECONFIG/log/post-fs-data.log" 198 | ##END## 199 | 200 | ##EXTRACT MODULE FILES## 201 | print_cn "- 提取模块文件" 202 | print_en "- Extracting module files" 203 | for FILE in $FILES; do 204 | extract "$ZIPFILE" "$FILE" "$MODPATH" 205 | done 206 | mkdir -p "$SD" 207 | cp -f "$MODPATH/lib/state.sh" "$SD/.tsee_state.sh" 208 | [[ ! "$APATCH" && ! "$KSU" ]] && { 209 | pm path com.dergoogler.mmrl.wx > /dev/null 2>&1 || pm path io.github.a13e300.ksuwebui > /dev/null 2>&1 || { 210 | print_cn "- 安装 WebUI 软件" 211 | print_en "- install WebUI Sortware" 212 | pm install "$MODPATH/webui.apk" > /dev/null 2>&1 213 | } 214 | } 215 | ##END## 216 | 217 | ##POST PROCESS## 218 | print_cn "- 赋予必要权限" 219 | print_en "- Setting permission" 220 | chcon u:object_r:shell_data_file:s0 "$MODPATH/service.apk" 221 | for NE in $NES; do 222 | chmod +x "$NE" 223 | done 224 | [ -f "$KEYBOX" ] && { 225 | print_cn "- 备份密钥文件" 226 | print_en "- Backup keybox file" 227 | rm -rf "$BACKUP" 228 | mkdir -p "$BACKUP" 229 | mv "$KEYBOX" "$BACKUP" 230 | } 231 | mkdir -p "$TSCONFIG" 232 | mkdir -p "$TSEECONFIG/log" 233 | print_cn "- 提取密钥文件" 234 | print_en "- Extract keybox file" 235 | extract "$ZIPFILE" 'keybox.xml' "$TSEECONFIG" 236 | cp -f "$TSEECONFIG/keybox.xml" "$KEYBOX" 237 | [ ! -f "$TSEECONFIG/usr.txt" ] || [ ! -f "$TSEECONFIG/sys.txt" ] && { 238 | print_cn "- 创建排除列表" 239 | print_en "- Extract default exclusion list" 240 | [ ! -f "$TSEECONFIG/sys.txt" ] && { 241 | touch "$TSEECONFIG/sys.txt" 242 | echo "$SYS" | awk ' 243 | NF { 244 | lines[++n] = $0 245 | } 246 | END { 247 | for (i = 1; i <= n; i++) { 248 | printf "%s", lines[i] 249 | if (i < n) 250 | printf "\n" 251 | } 252 | } 253 | ' > "$TSEECONFIG/sys.txt" 254 | } 255 | [ ! -f "$TSEECONFIG/usr.txt" ] && { 256 | touch "$TSEECONFIG/usr.txt" 257 | echo "$USR" | awk ' 258 | NF { 259 | lines[++n] = $0 260 | } 261 | END { 262 | for (i = 1; i <= n; i++) { 263 | printf "%s", lines[i] 264 | if (i < n) 265 | printf "\n" 266 | } 267 | } 268 | ' > "$TSEECONFIG/usr.txt" 269 | } 270 | } 271 | [[ "$(grep_get_prop ro.product.brand)" == "OnePlus" ]] && { grep -qx "com.oplus.engineermode" "$TSEECONFIG/sys.txt" || printf "\n%s" "com.oplus.engineermode" >> "$TSEECONFIG/sys.txt"; } 272 | print_cn "- 获取包名添加" 273 | print_en "- Getting package list & adding target" 274 | { pm list packages -3 | sed 's/^package://' | grep -vFf "$TSEECONFIG/usr.txt" ; cat "$TSEECONFIG/sys.txt"; } > "$TSCONFIG/target.txt" 275 | ##END## 276 | 277 | ##CONFLICT CHECK## 278 | #MODULES# 279 | print_cn "- 检查冲突模块" 280 | print_en "- Checking conflicts module" 281 | if [[ -f "$ADB/ap/modules.img" || -f "$ADB/ksu/modules.img" ]]; then 282 | for MODULE in $CONFLICT; do 283 | [ -d "$MODULESDIR/$MODULE" ] && { 284 | conflictdes_all 285 | touch "$MODULESDIR/$MODULE/update" 286 | touch "$MODULESDIR/$MODULE/disable" 287 | touch "$MODULESDIR/$MODULE/remove" 288 | rm -f "$MODULESUPDATEDIR/uninstall.sh" 289 | rm -f "$MODULESDIR/$MODULE/uninstall.sh" 290 | DETECTED=$((DETECTED + 1)) 291 | } 292 | done 293 | for RMRFMODULE in $RMRFCONFLICT; do 294 | [ -d "$MODULESDIR/$RMRFMODULE" ] && { 295 | (cd "$MODULESDIR/$RMRFMODULE"; ./uninstall.sh) 296 | rm -rf "$MODULESDIR/$RMRFMODULE" 297 | RMRFDETECTED=$((RMRFDETECTED + 1)) 298 | } 299 | done 300 | else 301 | for MODULE in $OFSCONFLICT; do 302 | [ -d "$MODULESDIR/$MODULE" ] && { 303 | [ -f $MODULESDIR/$MODULE/update ] && { 304 | functions_cn WAY="两次重新启动后被移除." 305 | functions_en WAY="after two reboots." 306 | } 307 | conflictdes_all 308 | touch "$MODULESDIR/$MODULE/update" 309 | touch "$MODULESDIR/$MODULE/disable" 310 | touch "$MODULESDIR/$MODULE/remove" 311 | OFSDETECTED=$((OFSDETECTED + 1)) 312 | } 313 | done 314 | fi 315 | if [ $OFSDETECTED -gt 0 ]; then 316 | print_cn "- 发现$OFSDETECTED个冲突模块,已添加移除标签与提示" 317 | print_en "- Detected $OFSDETECTED conflicting modules, Added removal tags and notification" 318 | elif [ $DETECTED -gt 0 ] && [ $RMRFDETECTED -gt 0 ]; then 319 | print_cn "- 发现$DETECTED个普通冲突模块,已添加移除标签与提示" 320 | print_cn "- 发现$RMRFDETECTED个隐藏冲突模块,已强制卸载" 321 | print_en "- Detected $DETECTED conflicting modules, Added removal tags and notification" 322 | print_en "- Detected $RMRFDETECTED hidden conflicting modules, Force uninstall" 323 | elif [ $DETECTED -gt 0 ] && [ $RMRFDETECTED -eq 0 ]; then 324 | print_cn "- 发现$DETECTED个普通冲突模块,已添加移除标签与提示" 325 | print_en "- Detected $DETECTED conflicting modules, Added removal tags and notification" 326 | elif [ $DETECTED -eq 0 ] && [ $RMRFDETECTED -gt 0 ]; then 327 | print_cn "- 发现$RMRFDETECTED个隐藏冲突模块,已强制卸载" 328 | print_en "- Detected $RMRFDETECTED hidden conflicting modules, Force uninstall" 329 | elif [ $DETECTED -eq 0 ] && [ $RMRFDETECTED -eq 0 ]; then 330 | print_cn "- 未发现冲突模块" 331 | print_en "- No conflict module found" 332 | fi 333 | #APPS# 334 | print_cn "- 检查冲突软件" 335 | print_en "- Checking conflicts software" 336 | for PACKAGE in $APPCONFLICT; do 337 | pm path $PACKAGE > /dev/null 2>&1 && { 338 | pm uninstall $PACKAGE > /dev/null 2>&1 339 | APPDETECTED=$((APPDETECTED + 1)) 340 | } 341 | done 342 | if [ $APPDETECTED -gt 0 ]; then 343 | print_cn "- 发现$APPDETECTED个冲突软件,已强制卸载" 344 | print_en "- Detected $APPDETECTED conflicting software, Forced uninstalled" 345 | elif [ $APPDETECTED -eq 0 ]; then 346 | print_cn "- 未发现冲突软件" 347 | print_en "- No conflict software found" 348 | fi 349 | ##END## 350 | 351 | print_cn "- 安装完毕" 352 | print_en "- Install Done" 353 | -------------------------------------------------------------------------------- /sealer/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "arrayref" 7 | version = "0.3.9" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" 10 | 11 | [[package]] 12 | name = "arrayvec" 13 | version = "0.7.6" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" 16 | 17 | [[package]] 18 | name = "blake3" 19 | version = "1.8.2" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" 22 | dependencies = [ 23 | "arrayref", 24 | "arrayvec", 25 | "cc", 26 | "cfg-if", 27 | "constant_time_eq", 28 | ] 29 | 30 | [[package]] 31 | name = "bumpalo" 32 | version = "3.19.0" 33 | source = "registry+https://github.com/rust-lang/crates.io-index" 34 | checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" 35 | 36 | [[package]] 37 | name = "bytes" 38 | version = "1.10.1" 39 | source = "registry+https://github.com/rust-lang/crates.io-index" 40 | checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" 41 | 42 | [[package]] 43 | name = "cc" 44 | version = "1.2.41" 45 | source = "registry+https://github.com/rust-lang/crates.io-index" 46 | checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7" 47 | dependencies = [ 48 | "find-msvc-tools", 49 | "shlex", 50 | ] 51 | 52 | [[package]] 53 | name = "cesu8" 54 | version = "1.1.0" 55 | source = "registry+https://github.com/rust-lang/crates.io-index" 56 | checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" 57 | 58 | [[package]] 59 | name = "cfg-if" 60 | version = "1.0.4" 61 | source = "registry+https://github.com/rust-lang/crates.io-index" 62 | checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" 63 | 64 | [[package]] 65 | name = "combine" 66 | version = "4.6.7" 67 | source = "registry+https://github.com/rust-lang/crates.io-index" 68 | checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" 69 | dependencies = [ 70 | "bytes", 71 | "memchr", 72 | ] 73 | 74 | [[package]] 75 | name = "constant_time_eq" 76 | version = "0.3.1" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" 79 | 80 | [[package]] 81 | name = "ct-codecs" 82 | version = "1.1.6" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | checksum = "9b10589d1a5e400d61f9f38f12f884cfd080ff345de8f17efda36fe0e4a02aa8" 85 | 86 | [[package]] 87 | name = "ed25519-compact" 88 | version = "2.1.1" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "e9b3460f44bea8cd47f45a0c70892f1eff856d97cd55358b2f73f663789f6190" 91 | dependencies = [ 92 | "ct-codecs", 93 | "getrandom", 94 | ] 95 | 96 | [[package]] 97 | name = "find-msvc-tools" 98 | version = "0.1.4" 99 | source = "registry+https://github.com/rust-lang/crates.io-index" 100 | checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" 101 | 102 | [[package]] 103 | name = "getrandom" 104 | version = "0.2.16" 105 | source = "registry+https://github.com/rust-lang/crates.io-index" 106 | checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" 107 | dependencies = [ 108 | "cfg-if", 109 | "js-sys", 110 | "libc", 111 | "wasi", 112 | "wasm-bindgen", 113 | ] 114 | 115 | [[package]] 116 | name = "hex" 117 | version = "0.4.3" 118 | source = "registry+https://github.com/rust-lang/crates.io-index" 119 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 120 | 121 | [[package]] 122 | name = "jni" 123 | version = "0.21.1" 124 | source = "registry+https://github.com/rust-lang/crates.io-index" 125 | checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" 126 | dependencies = [ 127 | "cesu8", 128 | "cfg-if", 129 | "combine", 130 | "jni-sys", 131 | "log", 132 | "thiserror", 133 | "walkdir", 134 | "windows-sys 0.45.0", 135 | ] 136 | 137 | [[package]] 138 | name = "jni-sys" 139 | version = "0.3.0" 140 | source = "registry+https://github.com/rust-lang/crates.io-index" 141 | checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" 142 | 143 | [[package]] 144 | name = "js-sys" 145 | version = "0.3.81" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" 148 | dependencies = [ 149 | "once_cell", 150 | "wasm-bindgen", 151 | ] 152 | 153 | [[package]] 154 | name = "libc" 155 | version = "0.2.177" 156 | source = "registry+https://github.com/rust-lang/crates.io-index" 157 | checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" 158 | 159 | [[package]] 160 | name = "log" 161 | version = "0.4.28" 162 | source = "registry+https://github.com/rust-lang/crates.io-index" 163 | checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" 164 | 165 | [[package]] 166 | name = "memchr" 167 | version = "2.7.6" 168 | source = "registry+https://github.com/rust-lang/crates.io-index" 169 | checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" 170 | 171 | [[package]] 172 | name = "once_cell" 173 | version = "1.21.3" 174 | source = "registry+https://github.com/rust-lang/crates.io-index" 175 | checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 176 | 177 | [[package]] 178 | name = "proc-macro2" 179 | version = "1.0.101" 180 | source = "registry+https://github.com/rust-lang/crates.io-index" 181 | checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" 182 | dependencies = [ 183 | "unicode-ident", 184 | ] 185 | 186 | [[package]] 187 | name = "quote" 188 | version = "1.0.41" 189 | source = "registry+https://github.com/rust-lang/crates.io-index" 190 | checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" 191 | dependencies = [ 192 | "proc-macro2", 193 | ] 194 | 195 | [[package]] 196 | name = "rustversion" 197 | version = "1.0.22" 198 | source = "registry+https://github.com/rust-lang/crates.io-index" 199 | checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" 200 | 201 | [[package]] 202 | name = "same-file" 203 | version = "1.0.6" 204 | source = "registry+https://github.com/rust-lang/crates.io-index" 205 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 206 | dependencies = [ 207 | "winapi-util", 208 | ] 209 | 210 | [[package]] 211 | name = "sealer" 212 | version = "0.0.0" 213 | dependencies = [ 214 | "blake3", 215 | "ed25519-compact", 216 | "hex", 217 | "jni", 218 | ] 219 | 220 | [[package]] 221 | name = "shlex" 222 | version = "1.3.0" 223 | source = "registry+https://github.com/rust-lang/crates.io-index" 224 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 225 | 226 | [[package]] 227 | name = "syn" 228 | version = "2.0.107" 229 | source = "registry+https://github.com/rust-lang/crates.io-index" 230 | checksum = "2a26dbd934e5451d21ef060c018dae56fc073894c5a7896f882928a76e6d081b" 231 | dependencies = [ 232 | "proc-macro2", 233 | "quote", 234 | "unicode-ident", 235 | ] 236 | 237 | [[package]] 238 | name = "thiserror" 239 | version = "1.0.69" 240 | source = "registry+https://github.com/rust-lang/crates.io-index" 241 | checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 242 | dependencies = [ 243 | "thiserror-impl", 244 | ] 245 | 246 | [[package]] 247 | name = "thiserror-impl" 248 | version = "1.0.69" 249 | source = "registry+https://github.com/rust-lang/crates.io-index" 250 | checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 251 | dependencies = [ 252 | "proc-macro2", 253 | "quote", 254 | "syn", 255 | ] 256 | 257 | [[package]] 258 | name = "unicode-ident" 259 | version = "1.0.19" 260 | source = "registry+https://github.com/rust-lang/crates.io-index" 261 | checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" 262 | 263 | [[package]] 264 | name = "walkdir" 265 | version = "2.5.0" 266 | source = "registry+https://github.com/rust-lang/crates.io-index" 267 | checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" 268 | dependencies = [ 269 | "same-file", 270 | "winapi-util", 271 | ] 272 | 273 | [[package]] 274 | name = "wasi" 275 | version = "0.11.1+wasi-snapshot-preview1" 276 | source = "registry+https://github.com/rust-lang/crates.io-index" 277 | checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" 278 | 279 | [[package]] 280 | name = "wasm-bindgen" 281 | version = "0.2.104" 282 | source = "registry+https://github.com/rust-lang/crates.io-index" 283 | checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" 284 | dependencies = [ 285 | "cfg-if", 286 | "once_cell", 287 | "rustversion", 288 | "wasm-bindgen-macro", 289 | "wasm-bindgen-shared", 290 | ] 291 | 292 | [[package]] 293 | name = "wasm-bindgen-backend" 294 | version = "0.2.104" 295 | source = "registry+https://github.com/rust-lang/crates.io-index" 296 | checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" 297 | dependencies = [ 298 | "bumpalo", 299 | "log", 300 | "proc-macro2", 301 | "quote", 302 | "syn", 303 | "wasm-bindgen-shared", 304 | ] 305 | 306 | [[package]] 307 | name = "wasm-bindgen-macro" 308 | version = "0.2.104" 309 | source = "registry+https://github.com/rust-lang/crates.io-index" 310 | checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" 311 | dependencies = [ 312 | "quote", 313 | "wasm-bindgen-macro-support", 314 | ] 315 | 316 | [[package]] 317 | name = "wasm-bindgen-macro-support" 318 | version = "0.2.104" 319 | source = "registry+https://github.com/rust-lang/crates.io-index" 320 | checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" 321 | dependencies = [ 322 | "proc-macro2", 323 | "quote", 324 | "syn", 325 | "wasm-bindgen-backend", 326 | "wasm-bindgen-shared", 327 | ] 328 | 329 | [[package]] 330 | name = "wasm-bindgen-shared" 331 | version = "0.2.104" 332 | source = "registry+https://github.com/rust-lang/crates.io-index" 333 | checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" 334 | dependencies = [ 335 | "unicode-ident", 336 | ] 337 | 338 | [[package]] 339 | name = "winapi-util" 340 | version = "0.1.11" 341 | source = "registry+https://github.com/rust-lang/crates.io-index" 342 | checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" 343 | dependencies = [ 344 | "windows-sys 0.61.2", 345 | ] 346 | 347 | [[package]] 348 | name = "windows-link" 349 | version = "0.2.1" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" 352 | 353 | [[package]] 354 | name = "windows-sys" 355 | version = "0.45.0" 356 | source = "registry+https://github.com/rust-lang/crates.io-index" 357 | checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" 358 | dependencies = [ 359 | "windows-targets", 360 | ] 361 | 362 | [[package]] 363 | name = "windows-sys" 364 | version = "0.61.2" 365 | source = "registry+https://github.com/rust-lang/crates.io-index" 366 | checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" 367 | dependencies = [ 368 | "windows-link", 369 | ] 370 | 371 | [[package]] 372 | name = "windows-targets" 373 | version = "0.42.2" 374 | source = "registry+https://github.com/rust-lang/crates.io-index" 375 | checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" 376 | dependencies = [ 377 | "windows_aarch64_gnullvm", 378 | "windows_aarch64_msvc", 379 | "windows_i686_gnu", 380 | "windows_i686_msvc", 381 | "windows_x86_64_gnu", 382 | "windows_x86_64_gnullvm", 383 | "windows_x86_64_msvc", 384 | ] 385 | 386 | [[package]] 387 | name = "windows_aarch64_gnullvm" 388 | version = "0.42.2" 389 | source = "registry+https://github.com/rust-lang/crates.io-index" 390 | checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" 391 | 392 | [[package]] 393 | name = "windows_aarch64_msvc" 394 | version = "0.42.2" 395 | source = "registry+https://github.com/rust-lang/crates.io-index" 396 | checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" 397 | 398 | [[package]] 399 | name = "windows_i686_gnu" 400 | version = "0.42.2" 401 | source = "registry+https://github.com/rust-lang/crates.io-index" 402 | checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" 403 | 404 | [[package]] 405 | name = "windows_i686_msvc" 406 | version = "0.42.2" 407 | source = "registry+https://github.com/rust-lang/crates.io-index" 408 | checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" 409 | 410 | [[package]] 411 | name = "windows_x86_64_gnu" 412 | version = "0.42.2" 413 | source = "registry+https://github.com/rust-lang/crates.io-index" 414 | checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" 415 | 416 | [[package]] 417 | name = "windows_x86_64_gnullvm" 418 | version = "0.42.2" 419 | source = "registry+https://github.com/rust-lang/crates.io-index" 420 | checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" 421 | 422 | [[package]] 423 | name = "windows_x86_64_msvc" 424 | version = "0.42.2" 425 | source = "registry+https://github.com/rust-lang/crates.io-index" 426 | checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" 427 | -------------------------------------------------------------------------------- /module/src/bin/tseed: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of TS-Enhancer-Extreme. 3 | # 4 | # TS-Enhancer-Extreme is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 5 | # 6 | # TS-Enhancer-Extreme is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 7 | # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 8 | # See the GNU General Public License for more details. 9 | # 10 | # You should have received a copy of the GNU General Public License along with TS-Enhancer-Extreme. 11 | # If not, see . 12 | # 13 | # Copyright (C) 2025 TheGeniusClub (Organization) 14 | # Copyright (C) 2025 XtrLumen (Developer) 15 | # Copyright (C) 2025 furrybluelan (Developer) 16 | # 17 | 18 | help() { 19 | echo "Tsee cli 20 | 21 | Usage: tseed 22 | 23 | Arguments: 24 | --tsctl [Basic |-stop|-start|-state| ] 25 | --tseectl [Basic |-stop|-start|-state| ] 26 | --rootdetect 27 | --startwebui 28 | --passvbhash 29 | --stealkeybox [Basic |-a|-b|-c| ] 30 | --staterefresh 31 | --passpropstate 32 | --conflictappcheck 33 | --conflictmodcheck [Extra |-m|-o| ] 34 | --packagelistupdate [Extra |-a| ] 35 | --securitypatchpropsync 36 | --securitypatchdatefetch 37 | 38 | Options: 39 | -h, --help 40 | -V, --version" 41 | } 42 | 43 | error() { 44 | echo "error: unknown argument '"$1"' 45 | 46 | Usage: tseed "$2" 47 | 48 | For more information, try '"$3"'." 49 | exit 2 50 | } 51 | [ $# -eq 0 ] && help && exit 2 52 | source "/data/adb/modules/ts_enhancer_extreme/lib/util_functions.sh" 53 | BACK="$PATH" 54 | PATH="$TSEEBIN:$PATH" 55 | TSCONFIG="$ADB/$TS" 56 | functions_cn() { operate "CN" "functions" "$@"; } 57 | functions_en() { operate "EN" "functions" "$@"; } 58 | logce () { echo "$1" ; logc "$1"; } 59 | crawl() { 60 | if command -v curl >/dev/null 2>&1; then 61 | curl --connect-timeout 10 -Ls "$1" 62 | elif PATH="$ADB/ap/bin:$ADB/ksu/bin:$ADB/magisk:$PATH" && command -v busybox >/dev/null 2>&1; then 63 | busybox wget -T 10 --no-check-certificate -qO- "$1" 64 | fi 65 | } 66 | 67 | rootdetect() { 68 | DMESGLOG="$TSEECONFIG/dmesg.log" 69 | KERNELSU_KTAG=0 70 | APATCH_KTAG=0 71 | MAGISK_KTAG=0 72 | KERNELSUTAG=0 73 | SUCKYSUTAG=0 74 | APATCHTAG=0 75 | MAGISKTAG=0 76 | dmesg > "$DMESGLOG" 77 | grep -q -F -e "KernelSU" "$DMESGLOG" && { 78 | KERNELSU_KTAG=1 79 | [[ -d "$ADB/ksu" && -f "$ADB/ksud" ]] && { 80 | if grep -q -F -e "KP hook sukisu_kpm" "$DMESGLOG" || [[ "$($ADB/ksud -V 2>/dev/null)" == *"zako"* ]]; then 81 | SUCKYSUTAG=1 82 | else 83 | KERNELSUTAG=1 84 | fi 85 | } 86 | } 87 | grep -q -F -e "/debug_ramdisk/magisk" -e "magiskinit" "$DMESGLOG" && { 88 | MAGISK_KTAG=1 89 | [[ -d "$ADB/magisk" && -f "$ADB/magisk.db" ]] && MAGISKTAG=1 90 | } 91 | grep -q -F -e "KP I commit_common_su" "$DMESGLOG" && { 92 | APATCH_KTAG=1 93 | [[ -d "$ADB/ap" && -f "$ADB/apd" ]] && APATCHTAG=1 94 | } 95 | if [ $(( KERNELSUTAG + SUCKYSUTAG + APATCHTAG + MAGISKTAG )) -gt 1 ]; then 96 | touch "$MULTIPLETYPE" 97 | [ $MAGISKTAG -eq 1 ] && echo -n "Magisk," >> "$MULTIPLETYPE" 98 | [ $KERNELSUTAG -eq 1 ] && echo -n "KernelSU," >> "$MULTIPLETYPE" 99 | [ $APATCHTAG -eq 1 ] && echo -n "APatch," >> "$MULTIPLETYPE" 100 | [ $SUCKYSUTAG -eq 1 ] && echo -n "SuckySU" >> "$MULTIPLETYPE" 101 | sed -i 's/,$//' "$MULTIPLETYPE" 102 | ROOT="Multiple" 103 | elif [ $KERNELSUTAG -eq 1 ]; then 104 | ROOT="KernelSU" 105 | elif [ $SUCKYSUTAG -eq 1 ]; then 106 | ROOT="SuckySU" 107 | elif [ $APATCHTAG -eq 1 ]; then 108 | ROOT="APatch" 109 | elif [ $MAGISKTAG -eq 1 ]; then 110 | ROOT="Magisk" 111 | fi 112 | [ -z "$ROOT" ] && ROOT="NULL" 113 | echo -n "$ROOT" > "$TYPE" 114 | rm -f "$DMESGLOG" 115 | [ $(( KERNELSU_KTAG + APATCH_KTAG + MAGISK_KTAG )) -gt 1 ] && [ ! "$ROOT" = "Multiple" ] && { 116 | touch "$KERNELTYPE" 117 | [ $MAGISK_KTAG -eq 1 ] && [ ! "$ROOT" = "Magisk" ] && echo -n "Magisk," >> "$KERNELTYPE" 118 | [ $KERNELSU_KTAG -eq 1 ] && [ ! "$ROOT" = "KernelSU" ] && echo -n "KernelSU," >> "$KERNELTYPE" 119 | [ $APATCH_KTAG -eq 1 ] && [ ! "$ROOT" = "APatch" ] && echo -n "APatch" >> "$KERNELTYPE" 120 | sed -i 's/,$//' "$KERNELTYPE" 121 | } 122 | } 123 | 124 | passpropstate() { 125 | check_missing_match_prop() { 126 | local NAME=$1 127 | local EXPECTED=$2 128 | local VALUE=$(getprop $NAME) 129 | [ -z $VALUE ] || [ $VALUE = $EXPECTED ] || resetprop $NAME $EXPECTED 130 | [ -z $VALUE ] && resetprop $NAME $EXPECTED 131 | } 132 | contains_reset_prop() { 133 | local NAME=$1 134 | local CONTAINS=$2 135 | local NEWVAL=$3 136 | [[ "$(getprop $NAME)" = *"$CONTAINS"* ]] && resetprop $NAME $NEWVAL 137 | } 138 | check_missing_prop() { 139 | local NAME=$1 140 | local EXPECTED=$2 141 | local VALUE=$(getprop $NAME) 142 | [ -z $VALUE ] && resetprop $NAME $EXPECTED 143 | } 144 | check_reset_prop() { 145 | local NAME=$1 146 | local EXPECTED=$2 147 | local VALUE=$(getprop $NAME) 148 | [ -z $VALUE ] || [ $VALUE = $EXPECTED ] || resetprop $NAME $EXPECTED 149 | } 150 | vbmeta_size="$(busybox blockdev --getbsz "/dev/block/by-name/vbmeta"$(getprop ro.boot.slot_suffix)"")"; [ -n "$vbmeta_size" ] || vbmeta_size="4096" 151 | resetprop "sys.usb.adb.disabled" " " 152 | check_missing_match_prop "ro.boot.vbmeta.device_state" "locked" 153 | check_missing_match_prop "ro.boot.verifiedbootstate" "green" 154 | check_missing_match_prop "ro.boot.veritymode" "enforcing" 155 | check_missing_match_prop "ro.boot.warranty_bit" "0" 156 | check_missing_match_prop "ro.boot.flash.locked" "1" 157 | contains_reset_prop "vendor.boot.bootmode" "recovery" "unknown" 158 | contains_reset_prop "ro.boot.bootmode" "recovery" "unknown" 159 | contains_reset_prop "ro.bootmode" "recovery" "unknown" 160 | check_missing_prop "ro.boot.vbmeta.invalidate_on_error" yes 161 | check_missing_prop "ro.boot.vbmeta.size" "$vbmeta_size" 162 | check_missing_prop "ro.boot.vbmeta.hash_alg" "sha256" 163 | check_missing_prop "ro.boot.vbmeta.avb_version" "1.2" 164 | check_reset_prop "vendor.boot.vbmeta.device_state" "locked" 165 | check_reset_prop "vendor.boot.verifiedbootstate" "green" 166 | check_reset_prop "ro.secureboot.lockstate" "locked" 167 | check_reset_prop "ro.boot.realmebootstate" "green" 168 | check_reset_prop "ro.vendor.boot.warranty_bit" "0" 169 | check_reset_prop "sys.oem_unlock_allowed" "0" 170 | check_reset_prop "ro.boot.realme.lockstate" "1" 171 | check_reset_prop "ro.build.tags" "release-keys" 172 | check_reset_prop "ro.crypto.state" "encrypted" 173 | check_reset_prop "ro.vendor.warranty_bit" "0" 174 | check_reset_prop "ro.force.debuggable" "0" 175 | check_reset_prop "ro.build.type" "user" 176 | check_reset_prop "ro.warranty_bit" "0" 177 | check_reset_prop "ro.debuggable" "0" 178 | check_reset_prop "ro.kernel.qemu" "" 179 | check_reset_prop "ro.adb.secure" "1" 180 | check_reset_prop "ro.secure" "1" 181 | } 182 | 183 | tsctl() { 184 | help() ( 185 | echo "tsctl 186 | 187 | Usage: tseed tsctl 188 | 189 | Arguments: 190 | -stop 191 | -start 192 | -state 193 | 194 | Options: 195 | -h, -help" 196 | ) 197 | [ "$1" = "" ] && help && exit 2 198 | if sed -n '2p' "$TSMODDIR/module.prop" | grep -q -F -e "OSS"; then 199 | NICENAME="TrickyStoreOSS" 200 | else 201 | NICENAME="TrickyStore" 202 | fi 203 | case "$1" in 204 | -h|-help) 205 | help 206 | ;; 207 | -stop) 208 | kill -9 "$(pidof "$NICENAME")" 209 | ;; 210 | -start) 211 | ( 212 | chmod +x $TSMODDIR/service.sh 213 | (exec $TSMODDIR/service.sh) 214 | ) & 215 | ;; 216 | -state) 217 | if pidof "$NICENAME" >/dev/null; then 218 | echo "true" 219 | else 220 | echo "false" 221 | fi 222 | ;; 223 | *) error "$1" "tsctl " "-help";; 224 | esac 225 | } 226 | 227 | tseectl() { 228 | help() ( 229 | echo "tseectl 230 | 231 | Usage: tseed tseectl 232 | 233 | Arguments: 234 | -stop 235 | -start 236 | -state 237 | 238 | Options: 239 | -h, -help" 240 | ) 241 | [ "$1" = "" ] && help && exit 2 242 | case "$1" in 243 | -h|-help) 244 | help 245 | ;; 246 | -stop) 247 | kill -9 "$(pidof "TSEnhancerExtreme")" 248 | ;; 249 | -start) 250 | ( 251 | exec /system/bin/app_process -Djava.class.path="$TSEEMODDIR/service.dex" -Djava.library.path="$TSEEMODDIR/lib" / --nice-name=TSEnhancerExtreme ts.enhancer.xtr.Main 252 | ) & 253 | ;; 254 | -state) 255 | if pidof "TSEnhancerExtreme" >/dev/null; then 256 | echo "true" 257 | else 258 | echo "false" 259 | fi 260 | ;; 261 | *) error "$1" "tseectl " "-help";; 262 | esac 263 | } 264 | 265 | conflictappcheck() { 266 | APPCONFLICT=" 267 | com.lingqian.appbl 268 | com.topmiaohan.hidebllist 269 | " 270 | for PACKAGE in $APPCONFLICT; do 271 | pm path $PACKAGE > /dev/null 2>&1 && pm uninstall $PACKAGE > /dev/null 2>&1 272 | done 273 | } 274 | 275 | packagelistupdate() { 276 | [ "$1" = "-action" ] && PATH="$BACK" 277 | { pm list packages -3 | sed 's/^package://' | grep -vFf "$TSEECONFIG/usr.txt" ; cat "$TSEECONFIG/sys.txt"; } > "$TSCONFIG/target.txt" 278 | } 279 | 280 | startwebui() { 281 | PATH="$BACK" 282 | start() ( 283 | echo_cn -n "- $1" 284 | shift 285 | echo_en -n "- $1" 286 | shift 287 | "$@" >/dev/null 2>&1 288 | detect 289 | ) 290 | if pm path com.dergoogler.mmrl.wx >/dev/null 2>&1; then 291 | start "WebUI-X已安装,启动..." "WebUI-X installed, Launch..." am start -n com.dergoogler.mmrl.wx/.ui.activity.webui.WebUIActivity -e MOD_ID $TSEE 292 | elif pm path io.github.a13e300.ksuwebui > /dev/null 2>&1; then 293 | start "WebUI已安装,启动..." "WebUI-X installed, Launch..." am start -n io.github.a13e300.ksuwebui/.WebUIActivity -e id $TSEE 294 | else 295 | echo_cn -n "- WebUI未安装,执行安装..." 296 | echo_en -n "- WebUI not installed. Executing installation..." 297 | if pm install "$TSEEMODDIR/webui.apk" >/dev/null 2>&1; then 298 | echo_cn "完毕" 299 | echo_en "Complete" 300 | start "启动..." "Launch..." am start -n io.github.a13e300.ksuwebui/.WebUIActivity -e id $TSEE 301 | else 302 | echo_cn "失败" 303 | echo_en "Failed" 304 | exit 1 305 | fi 306 | fi 307 | } 308 | 309 | passvbhash() { 310 | debugmode() { 311 | logce "$1失败,开始DEBUG" 312 | shift 313 | logce "$("$@" 2>&1)" 314 | } 315 | logce "安装服务" 316 | if pm install "$TSEEMODDIR/service.apk" >/dev/null 2>&1; then 317 | logce "安装完毕" 318 | logce "尝试启动" 319 | VBH="$(content call --uri content://Provider --method GET)" 320 | VBHVALUE="$(echo "$VBH" | grep -oE '[a-f0-9]{64}=VBHash' | grep -oE '[a-f0-9]{64}')" 321 | logcat -d | grep -F "[TSEE]" >> "$TSEELOG" 322 | logce "$VBH" 323 | if [ ${#VBHVALUE} -eq 64 ]; then 324 | logce "成功启动" 325 | if [ "$(getprop ro.boot.vbmeta.digest)" = "$VBHVALUE" ]; then 326 | logce "无需修正,当前属性:"$(getprop ro.boot.vbmeta.digest)"" 327 | else 328 | resetprop -n ro.boot.vbmeta.digest "$VBHVALUE" && logce "修正完毕,当前属性:"$(getprop ro.boot.vbmeta.digest)"" 329 | fi 330 | else 331 | logce "启动失败" 332 | fi 333 | logce "卸载服务" 334 | if pm uninstall io.github.xtrlumen.vbmeta >/dev/null 2>&1; then 335 | logce "卸载完毕" 336 | else 337 | debugmode "卸载" pm uninstall io.github.xtrlumen.vbmeta 338 | fi 339 | else 340 | debugmode "安装" pm install $TSEEMODDIR/service.apk 341 | exit 1 342 | fi 343 | } 344 | 345 | stealkeybox() { 346 | help() ( 347 | echo "stealkeybox 348 | 349 | Usage: tseed stealkeybox 350 | 351 | Arguments: 352 | -a (By Tricky Addon) 353 | -b (By Integrity Box) 354 | -c (By YuriKey Manager) 355 | 356 | Options: 357 | -h, -help" 358 | ) 359 | case "$1" in 360 | -h|-help) 361 | help 362 | ;; 363 | -a) 364 | MAINLINK="https://raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/main/.extra" 365 | SPARELINK="https://raw.gitmirror.com/KOWX712/Tricky-Addon-Update-Target-List/main/.extra" 366 | echo -n "- 下载文件..." 367 | if crawl "$MAINLINK" > "$TMPDIR/keybox.hex" || crawl "$SPARELINK" > "$TMPDIR/keybox.hex"; then 368 | echo "完毕" 369 | else 370 | echo "失败" 371 | exit 1 372 | fi 373 | echo -n "- 解码密钥..." 374 | echo "$(printf "$(sed 's/\(..\)/\\x\1/g' "$TMPDIR/keybox.hex")" | tr -d '\0' | base64 -d)" > "$TMPDIR/keybox.xml" 375 | if grep -q -F -e "-----BEGIN EC PRIVATE KEY-----" "$TMPDIR/keybox.xml"; then 376 | echo "完毕" 377 | else 378 | echo "失败" 379 | exit 1 380 | fi 381 | echo -n "- 写出文件..." 382 | [ -f "$TSCONFIG/keybox.xml" ] && mv "$TSCONFIG/keybox.xml" "$TSCONFIG/keybox.xml.bak" 383 | if mv "$TMPDIR/keybox.xml" "$TSCONFIG/keybox.xml"; then 384 | echo "完毕" 385 | else 386 | [ -f "$TSCONFIG/keybox.xml.bak" ] && mv "$TSCONFIG/keybox.xml.bak" "$TSCONFIG/keybox.xml" 387 | echo "失败" 388 | exit 1 389 | fi 390 | echo "- 清理缓存" 391 | rm -f "$TMPDIR/keybox.hex" 392 | rm -f "$TMPDIR/keybox.bin" 393 | ;; 394 | -b) 395 | MAINLINK="https://raw.githubusercontent.com/MeowDump/MeowDump/refs/heads/main/NullVoid/ShockWave.tar" 396 | SPARELINK="https://raw.gitmirror.com/MeowDump/MeowDump/refs/heads/main/NullVoid/ShockWave.tar" 397 | echo -n "- 下载文件..." 398 | if crawl "$MAINLINK" > "$TMPDIR/keybox.b64" || crawl "$SPARELINK" > "$TMPDIR/keybox.b64"; then 399 | echo "完毕" 400 | else 401 | echo "失败" 402 | exit 1 403 | fi 404 | echo -n "- 解码密钥..." 405 | base64 -d "$TMPDIR/keybox.b64" | base64 -d | base64 -d | base64 -d | base64 -d | base64 -d | base64 -d | base64 -d | base64 -d | base64 -d | xxd -r -p | tr 'A-Za-z' 'N-ZA-Mn-za-m' > "$TMPDIR/keybox.xml" 406 | for WORD in every soul will taste death; do 407 | sed -i "s/$WORD//g" "$TMPDIR/keybox.xml" 408 | done 409 | if grep -q -F -e "-----BEGIN EC PRIVATE KEY-----" "$TMPDIR/keybox.xml"; then 410 | echo "完毕" 411 | else 412 | echo "失败" 413 | exit 1 414 | fi 415 | echo -n "- 写出文件..." 416 | [ -f "$TSCONFIG/keybox.xml" ] && mv "$TSCONFIG/keybox.xml" "$TSCONFIG/keybox.xml.bak" 417 | if mv "$TMPDIR/keybox.xml" "$TSCONFIG/keybox.xml"; then 418 | echo "完毕" 419 | else 420 | [ -f "$TSCONFIG/keybox.xml.bak" ] && mv "$TSCONFIG/keybox.xml.bak" "$TSCONFIG/keybox.xml" 421 | echo "失败" 422 | exit 1 423 | fi 424 | echo "- 清理缓存" 425 | rm -f "$TMPDIR/keybox.b64" 426 | ;; 427 | -c) 428 | MAINLINK="https://raw.githubusercontent.com/YurikeyDev/yurikey/refs/heads/main/conf" 429 | SPARELINK="https://raw.gitmirror.com/YurikeyDev/yurikey/refs/heads/main/conf" 430 | echo -n "- 下载文件..." 431 | if crawl "$MAINLINK" > "$TMPDIR/keybox.bin" || crawl "$SPARELINK" > "$TMPDIR/keybox.bin"; then 432 | echo "完毕" 433 | else 434 | echo "失败" 435 | exit 1 436 | fi 437 | echo -n "- 解码密钥..." 438 | # strings "$TMPDIR/keybox.bin" | grep -E '^[A-Za-z0-9+/=]+$' | awk 'length($0) >= 500' | base64 -d > "$TMPDIR/keybox.xml" # 439 | base64 -d "$TMPDIR/keybox.bin" > "$TMPDIR/keybox.sh" 440 | eval $(grep "^KEYBOX_BASE64_PAYLOAD=" "$TMPDIR/keybox.sh") 441 | printf '%s' "$KEYBOX_BASE64_PAYLOAD" | base64 -d > "$TMPDIR/keybox.xml" 442 | if grep -q -F -e "-----BEGIN EC PRIVATE KEY-----" "$TMPDIR/keybox.xml"; then 443 | echo "完毕" 444 | else 445 | echo "失败" 446 | exit 1 447 | fi 448 | echo -n "- 写出文件..." 449 | [ -f "$TSCONFIG/keybox.xml" ] && mv "$TSCONFIG/keybox.xml" "$TSCONFIG/keybox.xml.bak" 450 | if mv "$TMPDIR/keybox.xml" "$TSCONFIG/keybox.xml"; then 451 | echo "完毕" 452 | else 453 | [ -f "$TSCONFIG/keybox.xml.bak" ] && mv "$TSCONFIG/keybox.xml.bak" "$TSCONFIG/keybox.xml" 454 | echo "失败" 455 | exit 1 456 | fi 457 | echo "- 清理缓存" 458 | rm -f "$TMPDIR/keybox.bin" 459 | rm -f "$TMPDIR/keybox.sh" 460 | ;; 461 | *) error "$1" "stealkeybox " "-help";; 462 | esac 463 | } 464 | 465 | staterefresh() { 466 | functions_cn TRUEDES="提升TrickyStore的使用体验,同时极致隐藏由解锁引导加载程序产生的相关检测点." 467 | functions_en TRUEDES="Enhances the TrickyStore experience, while providing extreme hiding of detection points introduced by bootloader unlocking." 468 | description_exit() { sed -i "s|^description=.*|description=[$ENVIRONMENT$SERVICESTATE] $TRUEDES|" "$TSEEMODDIR/module.prop" && exit; } 469 | [ -f "$TSEEMODDIR/disable" ] && { 470 | functions_cn ENVIRONMENT="❌禁用." 471 | functions_en ENVIRONMENT="❌Disabled." 472 | description_exit 473 | } 474 | functions_cn SERVICESTATE=" 所有服务将不会启动!" 475 | functions_en SERVICESTATE=" All service will not start!" 476 | if [ ! -d "$TSMODDIR" ]; then 477 | functions_cn ENVIRONMENT="❌TrickyStore模块未安装!" 478 | functions_en ENVIRONMENT="❌TrickyStore module is not installed!" 479 | description_exit 480 | elif [ -f "$TSMODDIR/disable" ]; then 481 | functions_cn ENVIRONMENT="❌TrickyStore模块已禁用!" 482 | functions_en ENVIRONMENT="❌TrickyStore module is disabled!" 483 | description_exit 484 | elif [ "$ROOT" = "Multiple" ]; then 485 | MULTIPLE=$(cat "$MULTIPLETYPE") 486 | functions_cn ENVIRONMENT="❌Root#多重共存($MULTIPLE)" 487 | functions_en ENVIRONMENT="❌Root#Multiple($MULTIPLE)" 488 | description_exit 489 | fi 490 | [ -f "$KERNELTYPE" ] && KERNEL="(❎Kernel#"$(cat "$KERNELTYPE")")" 491 | if [ "$ROOT" = "NULL" ]; then 492 | ENVIRONMENT="⚠️Root#Unknown(Unknown)." 493 | elif [ "$ROOT" = "APatch" ]; then 494 | VERSION=$(apd -V | awk '{print $2}') 495 | [ -f $ADB/.litemode_enable ] && LITE="Lite-" 496 | ENVIRONMENT="✅Root#APatch($LITE$VERSION)$KERNEL." 497 | elif [ "$ROOT" = "Magisk" ]; then 498 | VERSION=$(magisk -V) 499 | ENVIRONMENT="✅Root#Magisk($VERSION)$KERNEL." 500 | else 501 | VERSION=$(ksud debug version | awk '{print $3}') 502 | if [ "$ROOT" = "KernelSU" ]; then 503 | ENVIRONMENT="✅Root#KernelSU($VERSION)$KERNEL." 504 | elif [ "$ROOT" = "SuckySU" ]; then 505 | ENVIRONMENT="✅Root#SuckySU($VERSION)$KERNEL." 506 | fi 507 | fi 508 | functions_cn PARAMETER="✅参数执行结束." 509 | functions_en PARAMETER="✅Parameters executed ends." 510 | if [ "$(tseectl -state)" = "true" ]; then 511 | functions_cn SERVICESTATE=" ✅服务运行中! $PARAMETER" 512 | functions_en SERVICESTATE=" ✅Service is working! $PARAMETER" 513 | else 514 | functions_cn SERVICESTATE=" ❌服务无法启动! $PARAMETER" 515 | functions_en SERVICESTATE=" ❌Service can't start! $PARAMETER" 516 | fi 517 | description_exit 518 | } 519 | 520 | conflictmodcheck() { 521 | help() ( 522 | echo "conflictmodcheck 523 | 524 | Usage: tseed conflictmodcheck 525 | 526 | Arguments: 527 | -m 528 | -o 529 | 530 | Options: 531 | -h, -help" 532 | ) 533 | functions_cn WAY="下一次启动时被移除." 534 | functions_en WAY="upon the next boot." 535 | functions_cn DES="此模块与TS-Enhancer-Extreme模块证实冲突,已被添加移除标签,将在" 536 | functions_en DES="This module has been confirmed to conflict with the TS-Enhancer-Extreme module. It has been tagged for removal and will be removed " 537 | conflictdes_all() ( sed -i "s|^description=.*|description=$DES$WAY|" "/data/adb/modules/$MODULE/module.prop"; ) 538 | MODULESUPDATEDIR="$ADB/modules_update" 539 | CONFLICT=" 540 | Yurikey 541 | xiaocaiye 542 | safetynet-fix 543 | vbmeta-fixer 544 | playintegrity 545 | integrity_box 546 | SukiSU_module 547 | Reset_BootHash 548 | Tricky_store-bm 549 | Hide_Bootloader 550 | ShamikoManager 551 | extreme_hide_root 552 | Tricky_Store-xiaoyi 553 | tricky_store_assistant 554 | extreme_hide_bootloader 555 | wjw_hiderootauxiliarymod 556 | " 557 | RMRFCONFLICT=" 558 | TA_utl 559 | .TA_utl 560 | Yamabukiko 561 | " 562 | OFSCONFLICT="$RMRFCONFLICT $CONFLICT" 563 | case "$1" in 564 | -h|-help) 565 | help 566 | ;; 567 | -overlayfsmode) 568 | functions_cn WAY="两次重新启动后被移除." 569 | functions_en WAY="after two reboots." 570 | for MODULE in $OFSCONFLICT; do 571 | [ -d "$MODULESDIR/$MODULE" ] && { 572 | conflictdes_all 573 | touch "$MODULESDIR/$MODULE/disable" 574 | touch "$MODULESDIR/$MODULE/remove" 575 | } 576 | done 577 | ;; 578 | -magicmountmode) 579 | sleep 2s 580 | for MODULE in $CONFLICT; do 581 | [ -d "$MODULESDIR/$MODULE" ] && { 582 | conflictdes_all 583 | touch "$MODULESDIR/$MODULE/disable" 584 | touch "$MODULESDIR/$MODULE/remove" 585 | rm -rf "$MODULESUPDATEDIR/$MODULE" 586 | } 587 | done 588 | for RMRFMODULE in $RMRFCONFLICT; do 589 | [ -d "$MODULESDIR/$RMRFMODULE" ] && { 590 | (cd "$MODULESDIR/$RMRFMODULE"; ./uninstall.sh) 591 | rm -rf "$MODULESDIR/$RMRFMODULE" 592 | } 593 | done 594 | ;; 595 | esac 596 | if [[ -f "$ADB/ap/modules.img" || -f "$ADB/ksu/modules.img" ]]; then 597 | for MODULE in $CONFLICT; do 598 | [ -d "$MODULESDIR/$MODULE" ] && { 599 | conflictdes_all 600 | touch "$MODULESDIR/$MODULE/update" 601 | touch "$MODULESDIR/$MODULE/disable" 602 | touch "$MODULESDIR/$MODULE/remove" 603 | rm -f "$MODULESUPDATEDIR/uninstall.sh" 604 | rm -f "$MODULESDIR/$MODULE/uninstall.sh" 605 | } 606 | done 607 | for RMRFMODULE in $RMRFCONFLICT; do 608 | [ -d "$MODULESDIR/$RMRFMODULE" ] && { 609 | (cd "$MODULESDIR/$RMRFMODULE"; ./uninstall.sh) 610 | rm -rf "$MODULESDIR/$RMRFMODULE" 611 | } 612 | done 613 | else 614 | for MODULE in $OFSCONFLICT; do 615 | [ -d "$MODULESDIR/$MODULE" ] && { 616 | conflictdes_all 617 | touch "$MODULESDIR/$MODULE/update" 618 | touch "$MODULESDIR/$MODULE/disable" 619 | touch "$MODULESDIR/$MODULE/remove" 620 | } 621 | done 622 | fi 623 | } 624 | 625 | securitypatchpropsync() { 626 | SP="$TSCONFIG/security_patch.txt" 627 | [ ! -f "$SP" ] && logce "文件不存在" && exit 1 628 | RAW="$(grep -oE '^[0-9]{4}-[0-9]{2}-[0-9]{2}$' "$SP")" 629 | if [ -n "$RAW" ]; then 630 | DATE="$RAW" 631 | else 632 | RAW="$(grep -oE '^[0-9]{8}$' "$SP")" 633 | [ -n "$RAW" ] && DATE="${RAW:0:4}-${RAW:4:2}-${RAW:6:2}" 634 | fi 635 | if [ -n "$DATE" ]; then 636 | resetprop ro.vendor.build.security_patch "$DATE" 637 | resetprop ro.build.version.security_patch "$DATE" 638 | kill -9 "$(pidof com.google.android.gms.unstable)" 2>/dev/null 639 | logce "同步完毕" 640 | else 641 | logce "格式错误" 642 | exit 1 643 | fi 644 | } 645 | 646 | securitypatchdatefetch() { 647 | DATE="$(crawl "https://source.android.com/docs/security/bulletin/pixel" | sed -n 's/.*\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\)<\/td>.*/\1/p' | head -n 1)" 648 | if [ -n "$DATE" ]; then 649 | logce "拉取成功" 650 | DATE=${DATE//-/} 651 | printf "%s" "$DATE" > "$TSCONFIG/security_patch.txt" 652 | elif ! ping -c 1 -W 5 "source.android.com" >/dev/null 2>&1; then 653 | logce "拉取失败" 654 | exit 1 655 | fi 656 | } 657 | 658 | case "$1:$2" in 659 | "--conflictmodcheck:-m") conflictmodcheck -magicmountmode; exit 0;; 660 | "--conflictmodcheck:-o") conflictmodcheck -overlayfsmode; exit 0;; 661 | "--packagelistupdate:-a") packagelistupdate -action; exit ;; 662 | "--stealkeybox:"*) stealkeybox "$2"; exit ;; 663 | "--tseectl:"*) tseectl "$2"; exit ;; 664 | "--tsctl:"*) tsctl "$2"; exit ;; 665 | esac 666 | version() { echo "tseed 0.8.2.1" ; exit; } 667 | for ARG in "$@"; do 668 | case "$ARG" in 669 | -h|--help) help; exit ;; 670 | -V|--version) version ;; 671 | --rootdetect) rootdetect ;; 672 | --startwebui) startwebui ;; 673 | --passvbhash) passvbhash ;; 674 | --staterefresh) staterefresh ;; 675 | --passpropstate) passpropstate ;; 676 | --conflictappcheck) conflictappcheck ;; 677 | --packagelistupdate) packagelistupdate ;; 678 | --conflictmodcheck) conflictmodcheck; exit 0;; 679 | --securitypatchpropsync) securitypatchpropsync ;; 680 | --securitypatchdatefetch) securitypatchdatefetch ;; 681 | *) error "$ARG" " " "--help";; 682 | esac 683 | done 684 | exit 0 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | --------------------------------------------------------------------------------