From baddff862268a0adc4edcb5ff4a695121cbe277d Mon Sep 17 00:00:00 2001 From: Rifat Azad Date: Mon, 23 Dec 2024 04:52:19 +0600 Subject: [PATCH] manager: sus_su mode in StatusInfo and toggle to enable/disable sus_su susfs: variant and sus_su syscalls added --- .../java/com/rifsxd/ksunext/ui/screen/Home.kt | 2 +- .../com/rifsxd/ksunext/ui/screen/Settings.kt | 33 ++++--- .../java/com/rifsxd/ksunext/ui/util/KsuCli.kt | 20 +++- .../src/main/jniLibs/arm64-v8a/libsusfs.so | Bin 5320 -> 6248 bytes manager/app/src/main/res/values/strings.xml | 2 + userspace/susfs/jni/susfs.c | 91 +++++++++++++++++- 6 files changed, 132 insertions(+), 16 deletions(-) diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Home.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Home.kt index d61a6bf8..237afefe 100644 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Home.kt +++ b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Home.kt @@ -406,7 +406,7 @@ private fun InfoCard() { if (suSFS != "Unsupported") { InfoCardItem( label = stringResource(R.string.home_susfs_version), - content = "${getSuSFSVersion()} (${getSuSFSVariant()})", + content = "${getSuSFSVersion()} (${getSuSFSVariant()}) [+] sus_su mode: ${susfsSUSSU_Mode()}", icon = Icons.Filled.SettingsSuggest, ) } diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Settings.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Settings.kt index 6b0ebd7c..ee2b21da 100644 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Settings.kt +++ b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Settings.kt @@ -19,17 +19,7 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.Undo -import androidx.compose.material.icons.filled.BugReport -import androidx.compose.material.icons.filled.Compress -import androidx.compose.material.icons.filled.ContactPage -import androidx.compose.material.icons.filled.Delete -import androidx.compose.material.icons.filled.DeleteForever -import androidx.compose.material.icons.filled.DeveloperMode -import androidx.compose.material.icons.filled.Fence -import androidx.compose.material.icons.filled.RemoveModerator -import androidx.compose.material.icons.filled.Save -import androidx.compose.material.icons.filled.Share -import androidx.compose.material.icons.filled.Update +import androidx.compose.material.icons.filled.* import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -87,6 +77,7 @@ import com.rifsxd.ksunext.ui.component.rememberCustomDialog import com.rifsxd.ksunext.ui.component.rememberLoadingDialog import com.rifsxd.ksunext.ui.util.LocalSnackbarHost import com.rifsxd.ksunext.ui.util.getBugreportFile +import com.rifsxd.ksunext.ui.util.* import java.time.LocalDateTime import java.time.format.DateTimeFormatter @@ -196,6 +187,26 @@ fun SettingScreen(navigator: DestinationsNavigator) { enableWebDebugging = it } + val suSFSVar = getSuSFSVariant() + if (suSFSVar != "NON-GKI") { + var isEnabled by rememberSaveable { + mutableStateOf(susfsSUSSU_Mode() == "2") + } + SwitchItem( + icon = Icons.Filled.VisibilityOff, + title = stringResource(id = R.string.settings_susfs_toggle), + summary = stringResource(id = R.string.settings_susfs_toggle_summary), + checked = isEnabled + ) { + if (it) { + susfsSUSSU_1() + } else { + susfsSUSSU_0() + } + isEnabled = it + } + } + var showBottomsheet by remember { mutableStateOf(false) } ListItem( diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/KsuCli.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/KsuCli.kt index 8e2b706e..7bc4d90c 100644 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/KsuCli.kt +++ b/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/KsuCli.kt @@ -142,6 +142,24 @@ fun getSuSFSVariant(): String { return result } +fun susfsSUSSU_0(): String { + val shell = getRootShell() + val result = ShellUtils.fastCmd(shell, "${getSuSFSPath()} sus_su 0") + return result +} + +fun susfsSUSSU_1(): String { + val shell = getRootShell() + val result = ShellUtils.fastCmd(shell, "${getSuSFSPath()} sus_su 2") + return result +} + +fun susfsSUSSU_Mode(): String { + val shell = getRootShell() + val result = ShellUtils.fastCmd(shell, "${getSuSFSPath()} sus_su show_working_mode") + return result +} + fun getSuperuserCount(): Int { return Natives.allowList.size } @@ -426,7 +444,7 @@ fun getAppProfileTemplate(id: String): String { fun setAppProfileTemplate(id: String, template: String): Boolean { val shell = getRootShell() val escapedTemplate = template.replace("\"", "\\\"") - val cmd = """${getKsuDaemonPath()} profile set-template "$id" "$escapedTemplate'"""" + val cmd = """${getKsuDaemonPath()} profile set-template "$id" "$escapedTemplate'""" return shell.newJob().add(cmd) .to(ArrayList(), null).exec().isSuccess } diff --git a/manager/app/src/main/jniLibs/arm64-v8a/libsusfs.so b/manager/app/src/main/jniLibs/arm64-v8a/libsusfs.so index 77077b87a27d52c5f424f5b3e55d04d67078d21f..77167075d39189515a7d5297b63b224325ef5c3f 100755 GIT binary patch literal 6248 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 literal 5320 zcmb_gZ){uD6~DGSns%WC$OdU?{X*&1ZjIwOf0`83nKXogypm<<#5M`%*?x|_*naNw zOO>qMNY{Oc7)Z62X?y{~gtVsWq`#9%NGP*Otb1x4D-Mi+^5$IKRPK*UwA+Kk^8 zb-TI&`UVGc`{S-auUn$QYh?rDAxPqtx!*6p#N$Ltge1SfeQSyMW)~Hynp~ZD6szFz ztvrt9G{+&*&s%JC$1m=^R=S!}GB4qgIr3NLc*^WY(8Pi z7cMTey>srl-@JGJM^_&`dDAD^rup2m#(*2w!Rc|YHJ-NJT6pI=c;7ns0pK^I`pbO) z*0TT2b#SGEANvd7={b5cID3&pn$HuXMWKC;aRctF=EUU7WwhO8}VOM};49im4vXw8{S@0{io*qx8bK}XZ zo-Zge9jTZq@j(AUQi`NNW(w4Z-{FQ4;*Bc#;gAm>;-H6o_$cEK`*4j9_9){4*yq&h zIGkoY2%OeL%8Uo+Bj$9S_TaQ9r9A1uc?wR~oCo*j%`+a{d;S+Zxa1@<^r8pfBu*iZ zRP-@pzqYHQ-E+*aDtWVXqB2n~o0ffGvwEO(OfTRdAJeV8Ua}SUsBgO?4D`4hb)>|7 zz?h}!*4RYRDA{D)$%cV#p}V8-N%L4iJ%rkYMaxke@&sfC@-(Ck`5dI|#lR1TRp7*q zz_!M)qNz}BnL`~wRRe7UTcU>=w>LcLRbQoFkT7=8-@M~s`!bb zZKJ-7I*Az6z?OKTal7{O;OvH{Z+NOq7JqW=2YKi(MlB1SmnnY%(u+tu`6 zcAzeYR29_bZ|n>$)&HpeeC2p>{>mv;#q(Ie+Am-+7O*E4-rT9G7enE*4XuN)$(An^I~v3A>|8J--rCXH_u#`eG>gI$;-~hqcg>s@I!HUf30A zItriENBTk5>!E<-|NVzTP7EWj-o3O*P2V!}<#;W;K^;AFD*WNUHmaANXiy`a8{#!u z{?_MPs>`8U&l>PQ8gw4f>DK?b7-E?n4KX(BV&4ZA->ABGpMPw4`Hf!=pHXwxCCn`l z2*=*KRaNJferw@5G*e$I#!#Q&&tmMGScAi`ad~6>r5yZWK~JkYwpQ`(@QIvznKOfJ zfD~VC_zYb;5f7;q7`8*(BUqqr}$gC9DyRQGs~vE3m7n>EU9_k#WhnIZgu2j7v_JTzZHH z$^jRDY*sza4*50D$z5dXKUdxPmAPMI`*I((vX1BMlopn9FKuI8`sI$5`^lTTXy^*h zznA@8Wj(<yIk4d-mbfE zr;#z!94iBR((;cZI zCDS${5?emwU>Ff87tm=L1>J3>DisyUOqKBdq#{NxnYHwyk<4YFjg=-MJn1AdX%(sD;M&$xFl=UYTmPK4(-W{m zxkS$EdjC&~I~waP_duaDEPVg}Gf#R4qs_--6@3{kFJI&HFY>O{k#57!KL?m{h4`2J zA##QJl+P%3$!n5Vo&iQ@RrqqAMM|C$zcNnbkHM$2FS?w6ksA7`h<~x;qIkhT;{y+0 z@|Q@-JHnIrg`Y!%mQ4IheiV5^2D0=&zh3|++rnSX|D13qndkQ}>-Sye_wzW({~{MX ze7bWae&PQc7{!G2The current KernelSU-Next version %d is too low for the manager to work properly. Please upgrade to version %d or higher! Umount modules by default The global default value for \"Umount modules\" in App Profile. If enabled, it will remove all module modifications to the system for apps that don\'t have a profile set. + Hide suspecious su with SuSFS + It disables kprobe hooks made by ksu, and instead the non-kprobe inline hooks will be enabled, just the same implementation for non-gki kernel without kprobe supported. Enabling this option will allow KernelSU-Next to restore any modified files by the modules for this app. Domain Rules diff --git a/userspace/susfs/jni/susfs.c b/userspace/susfs/jni/susfs.c index 6c8d596d..13276611 100644 --- a/userspace/susfs/jni/susfs.c +++ b/userspace/susfs/jni/susfs.c @@ -1,14 +1,57 @@ #include -#include #include +#include #include +#include #define KERNEL_SU_OPTION 0xDEADBEEF + #define CMD_SUSFS_SHOW_VERSION 0x555e1 +#define CMD_SUSFS_SHOW_ENABLED_FEATURES 0x555e2 #define CMD_SUSFS_SHOW_VARIANT 0x555e3 +#define CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE 0x555e4 +#define CMD_SUSFS_IS_SUS_SU_READY 0x555f0 +#define CMD_SUSFS_SUS_SU 0x60000 + +#define SUS_SU_DISABLED 0 +#define SUS_SU_WITH_HOOKS 2 + +struct st_sus_su { + int mode; +}; + +int enable_sus_su(int last_working_mode, int target_working_mode) { + struct st_sus_su info; + int error = -1; + + if (target_working_mode == SUS_SU_WITH_HOOKS) { + info.mode = SUS_SU_WITH_HOOKS; + prctl(KERNEL_SU_OPTION, CMD_SUSFS_SUS_SU, &info, NULL, &error); + if (error) { + if (error == 1) { + } else if (error == 2) { + } + return error; + } + printf("[+] sus_su mode 2 is enabled\n"); + } else if (target_working_mode == SUS_SU_DISABLED) { + info.mode = SUS_SU_DISABLED; + prctl(KERNEL_SU_OPTION, CMD_SUSFS_SUS_SU, &info, NULL, &error); + if (error) { + if (error == 1) { + } + return error; + } + printf("[+] sus_su mode 0 is enabled\n"); + } else { + return 1; + } + return 0; +} int main(int argc, char *argv[]) { int error = -1; + char support[16]; char version[16]; char variant[16]; @@ -20,9 +63,9 @@ int main(int argc, char *argv[]) { // If 'version' is given, show version if (strcmp(argv[1], "support") == 0) { - prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_VERSION, version, NULL, &error); + prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_VERSION, support, NULL, &error); if (!error) { - if (version[0] == 'v') { + if (support[0] == 'v') { printf("Supported\n"); } } else { @@ -43,6 +86,48 @@ int main(int argc, char *argv[]) { } else { printf("Invalid\n"); } + } else if (argc == 3 && !strcmp(argv[1], "sus_su")) { + int last_working_mode = 0; + int target_working_mode; + char* endptr; + + prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE, &last_working_mode, NULL, &error); + if (error) + return error; + if (!strcmp(argv[2], "show_working_mode")) { + printf("%d\n", last_working_mode); + return 0; + } + target_working_mode = strtol(argv[2], &endptr, 10); + if (*endptr != '\0') { + return 1; + } + if (target_working_mode == SUS_SU_WITH_HOOKS) { + bool is_sus_su_ready; + prctl(KERNEL_SU_OPTION, CMD_SUSFS_IS_SUS_SU_READY, &is_sus_su_ready, NULL, &error); + if (error) + return error; + if (!is_sus_su_ready) { + printf("[-] sus_su mode %d has to be run during or after service stage\n", SUS_SU_WITH_HOOKS); + return 1; + } + if (last_working_mode == SUS_SU_DISABLED) { + error = enable_sus_su(last_working_mode, SUS_SU_WITH_HOOKS); + } else if (last_working_mode == SUS_SU_WITH_HOOKS) { + printf("[-] sus_su is already in mode %d\n", last_working_mode); + return 1; + } else { + error = enable_sus_su(last_working_mode, SUS_SU_DISABLED); + if (!error) + error = enable_sus_su(last_working_mode, SUS_SU_WITH_HOOKS); + } + } else if (target_working_mode == SUS_SU_DISABLED) { + if (last_working_mode == SUS_SU_DISABLED) { + printf("[-] sus_su is already in mode %d\n", last_working_mode); + return 1; + } + error = enable_sus_su(last_working_mode, SUS_SU_DISABLED); + } } else { fprintf(stderr, "Invalid argument: %s\n", argv[1]); return 1;