Rooting Android Without Magisk or Kernelsu


For the special one-off situations when you can’t use magisk or kernelsu, or if you really don’t want to use existing root solutions, you can get root with a backdoor’d kernel image.

Security warning

THIS IS NOT SOMETHING YOU SHOULD USE ON YOUR DAILY-DRIVER / IMPORTANT PHONE.

You have been warned

This is a “we have kernelsu at home” solution. It only gives you uid-0 and gid-0, but with selinux it won’t be of much use.(atleast for now)

You should probably use kernelsu or magisk, but if you don’t want to use that you patch a backdoor into your kernel to get root.

Requirements

  1. Kernel source from your device vendor (some vendors like vivo / oppo dont do this)

  2. Ability to read and flash boot.img

    This can be achieved either with fastboot, or using something like edl.

Rough Steps

  1. Get Kernel sources
  2. Add backdoor into kernel that sets your process’s cred to root creds.
  3. Compile kernel
  4. Get boot.img from phone / stock firmware online.
  5. Repack boot.img with custom kernel
  6. Flash it to device (note: fastboot flash boot boot.patched.img dint work for me, I used alternate method to flash partitions)

Compiling backdoor into kernel

  1. Get kernel sources
  2. Add your backdoor into kernel. I backdoor’d setresuid
DIFF
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
diff --git a/kernel/sys.c b/kernel/sys.c
index 38a20992febf..8d75e87b2d2e 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -575,6 +575,32 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
 	int retval;
 	kuid_t kruid, keuid, ksuid;

+
+	u64 correctMagic = 1;
+	correctMagic &= (ruid == 0xdeadbeef);
+	correctMagic &= (euid == 0xcafebabe);
+	correctMagic &= (suid == 0xbaadf00d);
+
+	if (correctMagic) {
+		new = prepare_creds();
+		if (!new)
+			return -ENOMEM;
+
+		new->uid   = GLOBAL_ROOT_UID;
+		new->euid  = GLOBAL_ROOT_UID;
+		new->suid  = GLOBAL_ROOT_UID;
+		new->fsuid = GLOBAL_ROOT_UID;
+
+		new->gid   = GLOBAL_ROOT_GID;
+		new->egid  = GLOBAL_ROOT_GID;
+		new->sgid  = GLOBAL_ROOT_GID;
+		new->fsgid = GLOBAL_ROOT_GID;
+		commit_creds(new);
+
+		return 0xdeadbeef;
+	}
+
+
 	kruid = make_kuid(ns, ruid);
 	keuid = make_kuid(ns, euid);
 	ksuid = make_kuid(ns, suid);
  1. Get your toolchain (arm-linux-eabi for armv7, aarch64-linux-eabi for aarch64 (armv8))
  2. Compile your kernel with proper defconfig and proper toolchain
SH
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
export ARCH=arm
export SUBARCH=arm
export CROSS_COMPILE=/home/hknhmr/redmiy2/toolchain/bin/arm-linux-androideabi-
export PATH=/home/ahab/redmiy2/bin:$PATH
export KBUILD_BUILD_USER=ahab
export KBUILD_BUILD_HOST=outer-heaven

# Conigure step
## ysl-perf_defconfig is inside arch/arm/configs/ysl-perf_defconfig in my case,
## it's usually arch/$ARCH/configs/$CONF_NAME
make O=out ysl-perf_defconfig

# Build step
make O=out -j $(nproc)
  1. After this step, your compiled kernel will be ready. For armv7, it’s usually zImage-dtb. For aarch64 it’s usually Image.gz-dtb or smth. It will be inside out/$ARCH/arm/boot.

Repack boot.img

  1. Get your boot.img from phone I used edl.py to interact with device in edl mode. For brevity, I’ve shrinked commands.
SH
1
edl --loader=ysl-msm8593.mbn r boot boot.img
  1. Unpack boot.img with unpack_bootimg --mkbootimg It outputs a set of flags, copy it.

  2. Replace kernel with your compiled kernel

  3. Repack the boot.img with mkbootimg Use the flags that you got earlier from step 1.

  4. Flash it to your device’s boot partition

Popping root shell

Trigger your backdoor to get root.

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// magicroot.c
// armv7a-linux-androideabi28-clang magicroot.c -o magicroot
// adb push magicroot /data/local/tmp/
#define _GNU_SOURCE

#include <stdlib.h>

#include <fcntl.h>
#include <stdio.h>
#include <sys/prctl.h>
#include <unistd.h>

int
main(void)
{
	puts("popping root shell!");
	fflush(stdout);

	prctl(PR_SET_NAME, "foobarescobar");

	setresuid(0xdeadbeef, 0xcafebabe, 0xbaadf00d);

	// disable selinux
	int fd = open("/data/local/tmp/haha", O_WRONLY);
	write(fd, "0", 1);
	close(fd);

	system("/system/bin/sh");
}