How to check root access in android? - android

I created a method for checking whether the android phone is rooted or not. This is done as follows
public int checkrootcommand(String string) {
// TODO Auto-generated method stub
Process exec;
try {
exec = Runtime.getRuntime().exec(new String[]{"su","-c"});
final OutputStreamWriter out = new OutputStreamWriter(exec.getOutputStream());
out.write("exit");
out.flush();
Log.i(SUPER_USER_COMMAND, "su command executed successfully");
return 0; // returns zero when the command is executed successfully
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return 1; //returns one when the command execution fails
}
But the problem is that the method checkrootcommand() is executed first it works perfectly, but when the same method called again the superuser session is still running. Is there any way to end the superuser session once the method is executed??

There is no reliable means of detecting a rooted condition on a device where hardware protections have been overcome by exploiting software vulnerabilities.
At best you can detect the presence of particular toolsets or scan for things that aren't supposed to be there or changes in files that are - but that requires knowledge of what a given installation should look like, and assumes that the OS functionality you are using to make the checks hasn't been modified to hide the changes.
To reliably scan, you need to be sure trusted code runs at a lower level than untrusted code; a rooted device is one where this assurance has been fundamentally broken, or where the end user is trusted more than you the developer are.

In your case, you should kill the process after executing it for the job which is done before returning. The following changes to your code should do the thing.
public int checkrootcommand(String string) {
// TODO Auto-generated method stub
Process exec = null;
try {
exec = Runtime.getRuntime().exec(new String[]{"su","-c"});
final OutputStreamWriter out = new OutputStreamWriter(exec.getOutputStream());
out.write("exit");
out.flush();
Log.i(SUPER_USER_COMMAND, "su command executed successfully");
return 0; // returns zero when the command is executed successfully
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (exec != null) {
try {
exec.destroy();
} catch (Exception ignored) {
}
}
}
return 1; //returns one when the command execution fails
}
You may not be able to universally detect whether phone is rooted or not but you should be able to request and then confirm is your app can access root by running id as root e.g., su -c id validate if the command executed successfully and the output contains uid=0 i.e., the uid of the root user.

Method 1 : Application asks for ROOT access :
Add this in your app-level gradle build file :
dependencies {
compile 'eu.chainfire:libsuperuser:201501111220'
}
Now,
System.out.println(Shell.Su.available());
//Outputs true if user-granted else false
Method 2 : Application doesn't asks for ROOT :
boolean deviceisRooted() {
String[] filespaths = {"/system/app/Superuser.apk","/sbin/su", "/system/bin/su","/system/xbin/su"};
for (String xyz : filespaths) {
if (new File(xyz).exists()) return true;
}
return false;
}
System.out.prinln(deviceisRooted());
//Outputs true if device is ROOTED else false
//Doesn't asks user
//Also returns true IF NOT PROPERLY ROOTED (But ROOTED somehow)

Use this code:
Process executor = Runtime.getRuntime().exec("su -c ls /data/data");
executor.waitFor();
int iabd = executor.exitValue();
if(iabd != 0){ /*process exit value is not 0, so user is not root*/ }else{ /* user is root*/ }

You can achieve this from a terminal command and you can run terminal commands within an app.
if [ ! -z "$(/system/bin/ps -A | grep -v grep | grep -c daemonsu)" ]; then echo "device is rooted"; else echo "device is not rooted"; fi
Your application also doesn't require root access this way.

Related

Get screenshot of current foreground app on Android having root priviliges

I'm developing an application that is installed on the system partition and I would like to know if it's possible to get a screenshot of the current foreground application from a service. Of course, the application being any third party app.
I'm not interested in security issues or anything related to that matter. I only want to get a snapshot of the current foreground third party app.
Note: I'm aware of the /system/bin/screencap solution but I'm looking for a more elegant alternative that does everything programmatically.
The method that I'm going to describe below will let you to programmatically take screen shots of whatever app it's in the foreground from a background process.
I am assuming that you have a rooted device.
I this case you can use the uiautomator framework to get the job done.
This framework has a been created to automate black box testing of apps on android, but it will suite this purpose as well.
We are going to use the method
takeScreenshot(File storePath, float scale, int quality)
This goes in the service class:
File f = new File(context.getApplicationInfo().dataDir, "test.jar");
//this command will start uiautomator
String cmd = String.format("uiautomator runtest %s -c com.mypacket.Test", f.getAbsoluteFile());
Process p = doCmds(cmd);
if(null != p)
{
p.waitFor();
}
else
{
Log.e(TAG, "starting the test FAILED");
}
private Process doCmds(String cmds)
{
try
{
Process su = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(su.getOutputStream());
os.writeBytes(cmds + "\n");
os.writeBytes("exit\n");
os.flush();
os.close();
return su;
}
catch(Exception e)
{
e.printStackTrace();
Log.e(TAG, "doCmds FAILED");
return null;
}
}
This is the class for uiautomator:
public class Test extends UiAutomatorTestCase
{
public void testDemo()
{
UiDevice dev = UiDevice.getInstance();
File f = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
dev.takeScreenshot(f, 1.0, 100);
}
}
It's best if you create a background thread in which uiautomator will run, that way it will not run onto the ui thread. (the Service runs on the ui thread).
uiatuomator doesn't know about or have a android context.
Once uiautomator gets the control you will be able to call inside it android methods that do not take a context parameter or belong to the context class.
If you need to communicate between uiautomator and the service (or other android components) you can use LocalSocket.
This will allow communication in both ways.
Months have passed since I asked this question but just now had the time to add this feature. The way to do this is simply by calling screencap -p <file_name_absolute_path> and then grabbing the file. Next is the code I used:
private class WorkerTask extends AsyncTask<String, String, File> {
#Override
protected File doInBackground(String... params) {
File screenshotFile = new File(Environment.getExternalStorageDirectory().getPath(), SCREENSHOT_FILE_NAME);
try {
Process screencap = Runtime.getRuntime().exec("screencap -p " + screenshotFile.getAbsolutePath());
screencap.waitFor();
return screenshotFile;
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(File screenshot_file) {
// Do something with the file.
}
}
Remember to add the <uses-permission android:name="android.permission.READ_FRAME_BUFFER" /> permission to the manifest. Otherwise screenshot.png will be blank.
This is much simpler than what Goran stated and is what I finally used.
Note: It only worked for me when the app is installed on the system partition.

Need help for an app to push a file with a button

Okay, Im very new to android programming, and im making a root app to push a specific file to /system/framework with a button
how can i accomplish this? i tried the command style and none are working
There are a number of steps you need to take to be able to do this.
First (of course) the device needs to be rooted. You can check this in a number of ways.
The following code will check if the "su" command returns a command not found error (su binary exists) AND that a super user app is installed to grant the permissions after you request them.
private boolean isDeviceRooted() {
// check for SU command in shell
if ((new ExecShell().executeCommand(ExecShell.SHELL_COMMAND.su_check) != null) && (appInstalled("eu.chainfire.supersu.nonag") || appInstalled("eu.chainfire.supersu") || appInstalled("com.noshufou.android.su") || appInstalled("com.koushikdutta.superuser"))) {
Log.i(TAG, "Device Rooted");
return true;
}
// check for SU application installed
if (appInstalled("eu.chainfire.supersu.nonag") || appInstalled("eu.chainfire.supersu") || appInstalled("com.noshufou.android.su") || appInstalled("com.koushikdutta.superuser")) {
Log.i(TAG, "Device Rooted");
return true;
}
Log.i(TAG, "Device Not Rooted");
return false;
}
private boolean appInstalled(String uri) {
PackageManager pm = getPackageManager();
boolean app_installed = false;
try {
pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES);
app_installed = true;
} catch (PackageManager.NameNotFoundException e) {
app_installed = false;
}
return app_installed;
}
If this code returns false you could set a flag or display and error, else continue.
Then, once you know the device is rooted, you want to execute the necessary root commands to do what you need.
The following code takes as input String[] of commands, and executes them sequentially as root.
public boolean RunAsRoot(String[] cmds) {
Process p;
try {
p = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(p.getOutputStream());
try {
for (String tmpCmd : cmds) {
os.writeBytes(tmpCmd + "\n");
}
os.writeBytes("exit\n");
os.flush();
return true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
}
In your case you will first want to mount /system as rw. There is lots of information on the web to help you find the command you want but it will look something like
mount -o remount rw /system mount -o remount rw /system
You then want to move the file you want using either mv or cp.
An example of the use of the root commands would be
String[] cmds = {"mount -o remount rw /system mount -o remount rw /system", "cp /sdcard/myfile /system/framework/myfile"};
if(!RunAsRoot(cmds)){
//Commands failed to run, show an error/retry
}
This covers the "hard" bit which is the root functionality.
An easy tutorial for the button can be found here.
Program flow could be
onCreate(){
checkIsRooted();
Button x = (Button) findViewById(R.id.x);
x.setOnClickListener(onClickListener());
}
onClickListener(){
onClick(){
String[] cmds = {...};
if(!runAsRoot(cmds))
AlertDialog.Builder.makeText(...).show();
}
}
NOTE, THIS IS PSEUDO CODE, YOU CAN'T COPY AND PASTE THIS CODE TO MAKE IT WORK, YOU NEED TO DO IT PROPERLY YOURSELF!

Sending shell command returns "No such file or directory" while it actually exists

I am making a Core management app for rooted android dual-core phones and up ... So what this app shall do is modify a file in the /sys directory , so it surely needs to use root or "su" . So what i am doing is that when i execute the command chmod 7777 /sys/devices/system/cpu/cpu1/online OR echo \"0\" > /sys/devices/system/cpu/cpu1/online from my app it gives me back "No such file or directory" , however , if I copy paste the command from my code to the terminal it self , the command goes flawless and completes my point ...
For sending the command , I am using a library that i made for my own , specifically I am using the su(String) method , which executes the commands you want as ROOT , and it works fine (I can see that from the SuperSU logs) , and I have used it before !
Here are some of the code that I am using :
Method to start ready everything up :
static public void ready_cores(){
Shells.Start();//Starts the root shell so it could be used with su(String) method
Shells.su("chmod 7777 /sys/devices/system/cpu/cpu3/online");//I have a dual-core so this one is normal to give me "No such file or directory"
Shells.su("chmod 7777 /sys/devices/system/cpu/cpu2/online");//This one too
Shells.su("chmod 7777 /sys/devices/system/cpu/cpu1/online");//This one should return no output and get executed successfully, more like in the terminal , but still returns NO such file or directory
}
MY on click listener for the button that runs the stuff :
Executable.ready_cores();//This is the above method
D2.setOnClickListener(new View.OnClickListener() {//D2 is my button (obviously :p)
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Executable.disable_core(1);//It sends the following command as root : echo "0" > /sys/devices/system/cpu/cpu1/online
refresh(); //refreshes everything , don't bother with it , it causes no harm ...
}
});
My Shells.su(String) method :
static public void su(String ssu){//BTW , the variable psu is defined at Start() as : psu = Runtime.getRuntime().exec("su")
cmd = ssu + "\r";
try {
su = new DataOutputStream(psu.getOutputStream());
su.flush();
if (bool = true){
su.writeBytes(cmd+ "\n");
su.flush();
bool = false;
}else if (bool = false){
su.writeBytes(cmd+ "\n");
su.flush();
bool = true;
}else {
su.writeBytes("\n" + cmd+ "\n");
su.flush();
bool = true;
}
if (ssu.contains("echo") &! ssu.contains(">")){
su.close();
su = new DataOutputStream(psu.getOutputStream());
}
} catch (Exception ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
}
I also added the permissions to read and write external storage !

How can check android Device is Rooted Device? [duplicate]

This question already has answers here:
Determine if running on a rooted device
(28 answers)
Closed 9 years ago.
How can i check if android device is rooted or not? I am using the following code:
Process proc = Runtime.getRuntime ().exec ("su");
and when I run it on a device I got following exception.
Causes by:Permission denied
But running on an emulator does not give any exception.
I am using another way to check. Entering adb shell in the commend line for emulator returns #, but for device writing adb shell gives the following error:
shell#android:/ $ su
su
/system/bin/sh: su: not found
127|shell#android:/ $
So how can I check if device is rooted or not.
Thanks in Advance.
I use this class:
private void CheckRoot()
{
Process p;
try {
// Preform su to get root privledges
p = Runtime.getRuntime().exec("su");
// Attempt to write a file to a root-only
DataOutputStream os = new DataOutputStream(p.getOutputStream());
os.writeBytes("echo \"Do I have root?\" >/data/LandeRootCheck.txt\n");
// Close the terminal
os.writeBytes("exit\n");
os.flush();
try {
p.waitFor();
if (p.exitValue() == 0) {
// TODO Code to run on success
this.IsRoot=true;
}
else {
// TODO Code to run on unsuccessful
this.IsRoot=false;
}
} catch (InterruptedException e) {
// TODO Code to run in interrupted exception
toastMessage("not root");
}
} catch (IOException e) {
// TODO Code to run in input/output exception
toastMessage("not root");
}
}

How to execute shell commands in android?

I am trying to execute shell command through my code for adding entry in Iptables. The following is my piece of code
private void createShellCommand(String uidValue_param, String interface_param) {
// TODO Auto-generated method stub
StringBuilder cmdScript=new StringBuilder();
script.append("iptables -A OUTPUT " + interface_param + "-m owner --uid-owner " + uidValue_param + "-j REJECT");
writeIptables(cmdScript);
}
private void writeIptables(StringBuilder scriptfile) {
// TODO Auto-generated method stub
String cmd=scriptfile.toString();
if(RootTools.isRootAvailable())
{
Process exec;
try {
exec = Runtime.getRuntime().exec(new String[]{"su","-c"});
final OutputStreamWriter out = new OutputStreamWriter(exec.getOutputStream());
out.write(cmd);
// Terminating the "su" session
out.write("exit\n");
out.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("IPtables updation failed", "Iptable write failed"+e);
}
}
else
{
Log.e("Root Access denied", "Access Denied");
}
}
Here there are two methods i.e, createshellCommand() for building the shell command and writeIptables() for updating the iptables. But whenever I run the program logcat is displaying the following warning
"W 19913 su request rejected (0->0 /system/bin/sh)"
But I can manually add the entry through command prompt and its adding to the iptables but by using the above code its not updating. My phone is rooted and I am using android 2.3.4 with linux kernel 2.6.29. And I am using external library "Roottools" for checking the root access.
Please help me to rectify the error.
This Works:
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
execute_reboot();
}
void execute_reboot()
{
Process reboot;
try {
reboot=Runtime.getRuntime().exec("su");
DataOutputStream os =
new DataOutputStream(reboot.getOutputStream());
os.writeBytes("reboot\n");
os.flush();
os.writeBytes("exit\n");
os.flush();
reboot.waitFor();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
This Code Works fine. There are couple of small mistakes in your program. Try the one i pasted. Its working charm. All the best. I kept it as simple as possible so that it is easy to understand. You can still use arrays and other stuff to fancy your coding.
And yaa the same one also works for chmod command where you need to pass more than one argument.
For this Just replace
"os.writeBytes("reboot\n");"
with
"chmod 777 /dev/video0\n"(or any other system file).
Thanks. LEt me know if there is something tat i can do.
public static void rebootNow() {
Log.d(TAG, "Rebooting");
try {
#SuppressWarnings("unused")
Process proc = Runtime.getRuntime().exec(
new String[] { "su", "-c", "reboot" });
} catch (Exception ex) {
Log.d(TAG, "Rebooting failed (Terminal Error)");
}
}
This one is a little more compact
You can add "proc.waitFor();" after the Process proc... line to get rid of the unused warning, but rebooting your device takes a few seconds time and if you want to disable some features during the few seconds in your UI-thread, I think its better to not wait for the process to end.
Trying using the iptables command (with sudo and without), rather than just clobbering the iptables config file.

Categories

Resources