// Ripped from https://github.com/Ch0pin/medusa/ and modified to fit Androguard packets

colorLog('[+] LOADING HELPER/ANTIDEBUG/PROCESS.JS',{c: Color.Red});

var fakeCmd = "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled";


var loaded_classes = Java.enumerateLoadedClassesSync();

console.log("Loaded " + loaded_classes.length + " classes!");

var useProcessManager = false;

console.log("loaded: " + loaded_classes.indexOf('java.lang.ProcessManager'));

if (loaded_classes.indexOf('java.lang.ProcessManager') != -1) {
    try {
        useProcessManager = true;
        var ProcessManager = Java.use('java.lang.ProcessManager');
    } catch (err) {
        console.log("ProcessManager Hook failed: " + err);
    }
} else {
    console.log("ProcessManager hook not loaded");
}

if (useProcessManager) {
    var ProcManExec = ProcessManager.exec.overload('[Ljava.lang.String;', '[Ljava.lang.String;', 'java.io.File', 'boolean');
    var ProcManExecVariant = ProcessManager.exec.overload('[Ljava.lang.String;', '[Ljava.lang.String;', 'java.lang.String', 'java.io.FileDescriptor', 'java.io.FileDescriptor', 'java.io.FileDescriptor', 'boolean');

    ProcManExec.implementation = function(cmd, env, workdir, redirectstderr) {
        agPacket({cmd: cmd}).send();

        var fake_cmd = cmd;
        for (var i = 0; i < cmd.length; i = i + 1) {
            var tmp_cmd = cmd[i];
            if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd == "mount" || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd == "id") {
                var fake_cmd = ["grep"];
                agSysPacket({information: "proc exec bypass", cmd: cmd}).send();

            }

            if (tmp_cmd == "su") {
                var fake_cmd = [fakeCmd];
                agSysPacket({information: "proc exec bypass" , cmd: cmd}).send();
            }
        }
        return ProcManExec.call(this, fake_cmd, env, workdir, redirectstderr);
    };

    ProcManExecVariant.implementation = function(cmd, env, directory, stdin, stdout, stderr, redirect) {
        agPacket({cmd: cmd}).send();

        var fake_cmd = cmd;
        for (var i = 0; i < cmd.length; i = i + 1) {
            var tmp_cmd = cmd[i];
            if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd == "mount" || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd == "id") {
                var fake_cmd = ["grep"];
                agSysPacket({information: "proc exec variant bypass", cmd: cmd}).send();
            }

            if (tmp_cmd == "su") {
                var fake_cmd = [fakeCmd];
                agSysPacket({information: "proc exec variant bypass", cmd: cmd}).send();
            }
        }
        return ProcManExecVariant.call(this, fake_cmd, env, directory, stdin, stdout, stderr, redirect);
    };
}


Interceptor.attach(Module.findExportByName("libc.so", "system"), {
    onEnter: function(args) {
        var cmd = Memory.readCString(args[0]);
        agPacket({cmd: cmd}).send();
        if (cmd.indexOf("getprop") != -1 || cmd == "mount" || cmd.indexOf("build.prop") != -1 || cmd == "id") {
            agSysPacket({information: "system bypass", cmd: cmd}).send();
            Memory.writeUtf8String(args[0], "grep");
        }
        if (cmd == "su") {
            agSysPacket({information: "system bypass", cmd: cmd}).send();
            Memory.writeUtf8String(args[0], fakeCmd);
        }
    },
    onLeave: function(retval) {

    }
});


var ProcessBuilder = Java.use('java.lang.ProcessBuilder');
var executeCommand = ProcessBuilder.command.overload('java.util.List');

ProcessBuilder.start.implementation = function() {
    var cmd = this.command.call(this);
    var shouldModifyCommand = false;
    agPacket({cmd: cmd}).send();

    for (var i = 0; i < cmd.size(); i = i + 1) {
        var tmp_cmd = cmd.get(i).toString();
        if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd.indexOf("mount") != -1 || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd.indexOf("id") != -1) {
            shouldModifyCommand = true;
        }
    }
    if (shouldModifyCommand) {
        agSysPacket({information: "process builder bypass", cmd: cmd}).send();
        this.command.call(this, ["grep"]);
        return this.start.call(this);
    }
    if (cmd.indexOf("su") != -1) {
        agSysPacket({information: "process builder bypass", cmd: cmd}).send();
        this.command.call(this, [fakeCmd]);
        return this.start.call(this);
    }

    return this.start.call(this);
};


var Runtime = Java.use('java.lang.Runtime');

var exec = Runtime.exec.overload('[Ljava.lang.String;');
var exec1 = Runtime.exec.overload('java.lang.String');
var exec2 = Runtime.exec.overload('java.lang.String', '[Ljava.lang.String;');
var exec3 = Runtime.exec.overload('[Ljava.lang.String;', '[Ljava.lang.String;');
var exec4 = Runtime.exec.overload('[Ljava.lang.String;', '[Ljava.lang.String;', 'java.io.File');
var exec5 = Runtime.exec.overload('java.lang.String', '[Ljava.lang.String;', 'java.io.File');


exec5.implementation = function(cmd, env, dir) {
    agPacket({cmd: cmd, env: env, dir: dir}).send();

    if (cmd.indexOf("getprop") != -1 || cmd == "mount" || cmd.indexOf("build.prop") != -1 || cmd == "id" || cmd == "sh") {
        agSysPacket({information: "exec5 bypass", cmd: cmd}).send();
        return exec1.call(this, "grep");
    }
    if (cmd == "su") {
        agSysPacket({information: "exec5 bypass", cmd: cmd}).send();
        return exec1.call(this, fakeCmd);
    }
    return exec5.call(this, cmd, env, dir);
};

exec4.implementation = function(cmdarr, env, file) {
    agPacket({cmdarr: cmdarr, env: env, file: file}).send();

    for (var i = 0; i < cmdarr.length; i = i + 1) {
        var tmp_cmd = cmdarr[i];
        if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd == "mount" || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd == "id" || tmp_cmd == "sh") {
            agSysPacket({information: "exec4 bypass", cmd: cmd}).send();
            return exec1.call(this, "grep");
        }

        if (tmp_cmd == "su") {
            agSysPacket({information: "exec4 bypass", cmd: cmd}).send();
            return exec1.call(this, fakeCmd);
        }
    }

    return exec4.call(this, cmdarr, env, file);
};

exec3.implementation = function(cmdarr, envp) {
    agPacket({cmdarr: cmdarr, envp: envp}).send();

    for (var i = 0; i < cmdarr.length; i = i + 1) {
        var tmp_cmd = cmdarr[i];
        if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd == "mount" || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd == "id" || tmp_cmd == "sh") {
            agSysPacket({information: "exec3 bypass", cmd: cmd}).send();
            return exec1.call(this, "grep");
        }

        if (tmp_cmd == "su") {
            agSysPacket({information: "exec3 bypass", cmd: cmd}).send();
            return exec1.call(this, fakeCmd);
        }
    }
    return exec3.call(this, cmdarr, envp);
};

exec2.implementation = function(cmd, env) {
    agPacket({cmd: cmd, env: env}).send();

    if (cmd.indexOf("getprop") != -1 || cmd == "mount" || cmd.indexOf("build.prop") != -1 || cmd == "id" || cmd == "sh") {
        agSysPacket({information: "exec2 bypass", cmd: cmd}).send();
        return exec1.call(this, "grep");
    }

    if (cmd == "su") {
        agSysPacket({information: "exec2 bypass", cmd: cmd}).send();
        return exec1.call(this, fakeCmd);
    }
    return exec2.call(this, cmd, env);
};

exec1.implementation = function(cmd) {
    agPacket({cmd: cmd}).send();
   
    if (cmd.indexOf("getprop") != -1 || cmd == "mount" || cmd.indexOf("build.prop") != -1 || cmd == "id" || cmd == "sh") {
        agSysPacket({information: "exec1 bypass", cmd: cmd}).send();
        return exec1.call(this, "grep");
    }
    
    if (cmd == "su") {
        agSysPacket({information: "exec1 bypass", cmd: cmd}).send();
        return exec1.call(this, fakeCmd);
    }

    return exec1.call(this, cmd);
};

exec.implementation = function(cmd) {
    agPacket({cmd: cmd}).send();

    for (var i = 0; i < cmd.length; i = i + 1) {
        var tmp_cmd = cmd[i];
        if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd == "mount" || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd == "id" || tmp_cmd == "sh") {
            agSysPacket({information: "exec bypass", cmd: cmd}).send();
            return exec1.call(this, "grep");
        }

        if (tmp_cmd == "su") {
            agSysPacket({information: "exec bypass", cmd: cmd}).send();
            return exec.call(this, ["which", fakeCmd]);
        }
    }

    return exec.call(this, cmd);
};


/*

TO IMPLEMENT:

Exec Family

int execl(const char *path, const char *arg0, ..., const char *argn, (char *)0);
int execle(const char *path, const char *arg0, ..., const char *argn, (char *)0, char *const envp[]);
int execlp(const char *file, const char *arg0, ..., const char *argn, (char *)0);
int execlpe(const char *file, const char *arg0, ..., const char *argn, (char *)0, char *const envp[]);
int execv(const char *path, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char *const envp[]);

*/
