package biz.bokhorst.xprivacy;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import android.os.Build;
import android.os.Process;
import android.text.TextUtils;
public class XRuntime extends XHook {
private Methods mMethod;
private String mCommand;
private XRuntime(Methods method, String restrictionName, String command) {
super(restrictionName, method.name(), command);
mMethod = method;
mCommand = command;
}
public String getClassName() {
return "java.lang.Runtime";
}
@Override
public boolean isVisible() {
return !(mMethod == Methods.load || mMethod == Methods.loadLibrary);
}
// public Process exec(String[] progArray)
// public Process exec(String[] progArray, String[] envp)
// public Process exec(String[] progArray, String[] envp, File directory)
// public Process exec(String prog)
// public Process exec(String prog, String[] envp)
// public Process exec(String prog, String[] envp, File directory)
// public void load(String pathName)
// public void loadLibrary(String libName)
// libcore/luni/src/main/java/java/lang/Runtime.java
// http://developer.android.com/reference/java/lang/Runtime.html
private enum Methods {
exec, load, loadLibrary
};
public static List<XHook> getInstances() {
List<XHook> listHook = new ArrayList<XHook>();
listHook.add(new XRuntime(Methods.exec, PrivacyManager.cShell, "sh"));
listHook.add(new XRuntime(Methods.exec, PrivacyManager.cShell, "su"));
listHook.add(new XRuntime(Methods.exec, PrivacyManager.cShell, null));
listHook.add(new XRuntime(Methods.load, PrivacyManager.cShell, null));
listHook.add(new XRuntime(Methods.loadLibrary, PrivacyManager.cShell, null));
return listHook;
}
@Override
protected void before(XParam param) throws Throwable {
switch (mMethod) {
case exec:
// Get programs
String[] progs = null;
if (param.args.length > 0 && param.args[0] != null)
if (String.class.isAssignableFrom(param.args[0].getClass()))
progs = new String[] { (String) param.args[0] };
else
progs = (String[]) param.args[0];
// Check programs
if (progs != null) {
String command = TextUtils.join(" ", progs);
if (matches(command, mCommand) && isRestrictedExtra(param, command))
param.setThrowable(new IOException("XPrivacy"));
}
break;
case load:
case loadLibrary:
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP || Process.myUid() != Process.SYSTEM_UID)
if (param.args.length > 0) {
String libName = (String) param.args[0];
if (isRestrictedExtra(param, libName))
param.setThrowable(new UnsatisfiedLinkError("XPrivacy"));
}
break;
}
}
@Override
protected void after(final XParam param) throws Throwable {
// Do nothing
}
public static boolean matches(String command, String mCommand) {
if (mCommand == null)
return !isShell(command) && !isSU(command);
else if (mCommand.equals("sh"))
return isShell(command);
else if (mCommand.equals("su"))
return isSU(command);
else
return false;
}
private static boolean isShell(String command) {
return command.startsWith("sh") || command.matches("/.*/.*/sh.*") || command.contains("sh ");
}
private static boolean isSU(String command) {
return command.startsWith("su") || command.matches("/.*/.*/su.*") || command.contains("su ");
}
}