Executing a Root access based commands on Android application - android

I basically want to start a process which resides in /system/bin/... from the Application java command.
I tried all types of Runtime.process.exec() options
Tried the su and ouputStream combination as well, but nothing is able to start the application.
I am using the code in device and emulators, no luck in both.
I am able to run the same commands from ADB Shell successfully (as it has root permissions).
The device is rooted, I am able to see the # when I use adb to debug my device and it also can go into su via adb.
based on my searching I found that (after doing ps from adb shell)
I am able to run any command with lrwz--x--x permission such as (ls->toolbox, ps->toolbox) from the application layer but I am not able to execute any other commands which are not linked to the toolbox.
This doesn't execute ls:
Process p = Runtime.getRuntime().exec("su");
DataOutputStream os=new DataOutputStream(p.getOutputStream());
os.writeBytes("ls \n");
os.flush();
But this does execute ls:
Process p = Runtime.getRuntime().exec("ls");
I would really appreciate if I can get any help on this here! I am posting this after doing lots of research.

Rather than sending ls \n to the su command's standard input, try running:
su -c ls
The -c option to su(1) asks it to run a command with elevated privileges rather than starting an interactive shell.

Try creating a shell script file(eg: init.sh) and write following commands in it:
su
reboot
Now try executing this shell script by
Runtime.getRuntime().exec("sh init.sh");
If this restarted your droid then you can write your required code in init.sh file & run it.

Related

How do I run "adb shell" commands in a terminal emulator locally on an Android device?

From a shell on my PC, I can run adb shell cmd package list packages, and get a list of all installed packages. I would like to run this and similar commands locally on my Android phone (Nexus 6P) in a terminal emulator (currently using Termux).
If I open the same shell with /system/bin/sh, and then try to run /system/bin/cmd package list packages, nothing happens (no errors, just outputs nothing and reloads the prompt).
If I run /system/bin/cmd -l the list of options appears as expected. $PATH and $LD_LIBRARY_PATH are the same in both environments. One major difference is that echo $USER returns "shell" from adb shell, but returns my local username from /system/bin/sh launched from Termux.
Is there any way to replicate the behavior of commands run from adb shell in a terminal emulator locally on Android?
Edit:
My device is rooted, and I am OK with root only solutions.
The problem is Termux. By design, Termux runs only (or is mostly?) the Linux command line programs that you install from within Termux using apt or the newer "native" package management interface, e.g. apt install bsdtar. What you need to run the adb shell commands is a terminal emulator that can truly access the underlying Android file system, not just the Termux that is practically a chroot save for the fact that it's aware it's not running commands from the filesystem root /.
As a simple test, run the following command:
which ls
It should return something like /system/bin/ls. But if it returns something like /data/data/com.termux/files/usr/bin/applets/ls then you have to change your terminal emulator to something else. I suspect that Termux was designed to take into account the more restrictive shell execution policies that Google put into place after KitKat or the Android 4.X.
The Android distribution I'm using, LineageOS 14.1, comes with a built-in shell emulator that allows me to run commands found in /system/bin/ls.
I don't have a rooted Nougat device handy, but something like the following may be a close enough approximation to adb shell (assuming you are using SuperSU):
env -i USER=shell "$(PATH=/system/xbin:/system/bin:/su/bin:/sbin:/magisk/.core/bin which su)" shell --context u:r:shell:s0 --shell /system/bin/sh --command COMMAND
I (very briefly) tested it from Termux on a rooted Marshmallow device.
To elaborate:
the -i flag is used to start with an empty environment
USER=shell isn't specifically required, but for some reason su refuses to run with a completely empty environment
$(PATH=/system/xbin:/system/bin:/su/bin:/sbin:/magisk/.core/bin which su) points to the full path of the su binary on your device and can be hardcoded if you prefer
shell instructs the su binary to login as the shell user (the same as adb shell)
--context u:r:shell:s0 sets the appropriate SELinux context
--shell /system/bin/sh instructs SuperSU to use the system shell rather than it's own sush shell
Another option would be to actually run adb from the device, connecting to itself over TCP. If you need some functionality that is only available via adb (e.g. in my case it was adb forward) then this may be your only option. Unfortunately this isn't particularly convenient.
I wasn't able to find success with any publicly available adb binaries, so I build it myself with a few minor changes. You can see the sources I used and the changes I made at https://github.com/shakalaca/fastboot-adb-android and https://github.com/brbsix/fastboot-adb-android, respectively.
Once you have adb installed, here's an abbreviated list of commands I used to connect to the device:
# Add iptables rules to block external connections to port 9999'
su root iptables -N adbd
su root iptables -A adbd -i lo -p tcp -m tcp --dport 9999 -j ACCEPT
su root iptables -A adbd -p tcp -m tcp --dport 9999 -j DROP
su root iptables -A INPUT -j adbd
# Necessary in order to display authorization prompt
su shell setprop ro.debuggable 1
su shell setprop service.adb.tcp.port 9999
su root start adbd
adb connect 127.0.0.1:9999
adb wait-for-local-device
To shut down:
adb kill-server
su root stop adbd
su shell setprop ro.debuggable 0
su shell setprop service.adb.tcp.port 0
su root iptables -D INPUT -j adbd
su root iptables -F adbd
su root iptables -X adbd
So I tried this recently...if you're rooted you can use a terminal emulator.
su
then the command you want without "adb shell" part of it.
i tried the command "adb shell dumpsys deviceidle force-idle" in order to force device into doze.
I did this on the device via terminal emulator as:
"dumpsys deviceidle force-idle" and it did take effect.
also the dumpsys batterystats command worked.
be careful with commands with extensive text output, as the screen will be flooded with the output and will be unresponsive for some time.
EDIT
I originally answered this without the termux tag in mind. This worked for me while trying to execute shell commands on a vanilla emulator and saw this question while researching, so I tried to answer it differently.
You almost had it there in your question. You only need to execute sh:
int result = -1;
try {
final Process shell = Runtime.getRuntime().exec("sh");
final DataOutputStream commands = new DataOutputStream(shell.getOutputStream());
commands.writeBytes("write a series");
commands.writeBytes("of commands here");
commands.writeBytes("exit\n");
commands.flush();
result = shell.waitFor();
}
} catch (Exception e) {
e.printStackTrace();
}
If result == 0 the commands were succesful, else otherwise
Only rooted android
Busybox must be installed (though you can try without it)
Just write the normal command without the prefix adb

Getting 'root" permission for Android App

I would like to know how can we get root permission from android app? Are there any app out there in android market?
I tried out the below line of code to list out files but nothing happened
Process process = Runtime.getRuntime().exec(new String[] { "su", "-", "root"});
I tried to give TEST_FACTORY permission in my manifest file but I got an error "permitted to system app"
How can I make my app system app?
I want help to get started with these stuff (make app if possible to get root permission) any help on this is very much appreciated. Thanks in advance :)
Theres a good answer here - ANDROID: How to gain root access in an Android application?
"As far as I know, you can only run command-line commands using root privileges. You can use this generic class I made that wraps the root access in your code: http://muzikant-android.blogspot.com/2011/02/how-to-get-root-access-and-execute.html"
First: note that you can only execute shell commands using su (= you can only use shell commands as root, not java code).
Second: Not sure if this applies to all su apps out there, but this is the help message of su on my phone:
Usage: su [options] [--] [-] [LOGIN] [--] [args...]
Options:
--daemon start the su daemon agent
-c, --command COMMAND pass COMMAND to the invoked shell
-h, --help display this help message and exit
-, -l, --login pretend the shell to be a login shell
-m, -p,
--preserve-environment do not change environment variables
-s, --shell SHELL use SHELL instead of the default /system/bin/sh
-u display the multiuser mode and exit
-v, --version display version number and exit
-V display version code and exit,
this is used almost exclusively by Superuser.apk
This means: you have to run su -c something (or su -c something - root, but rootis the default anyway). essentially this is equal to su on most Linux systems, except the daemon-thing, as there is no daemon ahndling su calls on regular linux systems.
If other su commands behave differently (which is possible), it's more secure to open a stream to a shell, execute su, evaluate it's return code, then proceed to execute other commands, finally execute exit.

Piping output from 1 command to other command in an adb shell command line

I wish to send an adb shell command to an Android device that pipes output from 1 command to other command, but when I try to do that, only the 1st command is executed on the device, and the 2nd one is executed on the host machine. Here's what I tried:
adb shell command1 | command2
command1 is executed on the device, and command2 on the host machine.
How can I get this to work properly?
Thanks!
You could use something like this:
adb shell "command1 | command2"
One way is to create a shell script containing the commands you want and then run the shell script.
Since the Android root filesystem is not writeable at run time (usually, unless you have rooted your device and remount it), you can copy the file to the removable (or emulated) storage, for example /sdcard.
Then run the script using the command adb shell sh /sdcard/your-script-name. Because each script runs in its own subshell, both of your commands will be executed in the same shell on the device (you can confirm it with ps).
adb shell "command1 && command2"
example:
Recursive listing of all files under /system/lib that contain 'foo':
adb shell "cd /system/lib&&ls -lR .|grep -i foo"
The important thing is the double quotes and the double ampersand.
The only thing is that you cannot use it for input as well, meaning that running an executable that requires stdin using one-liner wouldn't work as it requires user intervention.

Run adb shell command using android code

echo 0 > /sys/class/leds/button-backlight/brightness
The above command is working perfectly through adb shell.But when I try to run through my code there is no effect.Here is my code.
Process mSuProcess;
mSuProcess = Runtime.getRuntime().exec("su");
DataOutputStream mSuDataOutputStream = new DataOutputStream(mSuProcess.getOutputStream());
mSuDataOutputStream.writeBytes("echo 0 > /sys/class/leds/button-backlight/brightness \n");
mSuDataOutputStream.flush();
mSuDataOutputStream.close();
Please help me out on this.
If the device which you are working on is not rooted then this may not work..
The google original su binary checks for UID and only works if run by root or shell users. This is why it works when you run your command from adb shell interactively. In order to run this code from a java app you need to use a patched su binary - without UID checks.

Is it possible to run a shell command as root with only the su binary and no SuperSU or Superuser apk installed?

I have an Android phone that has only su binary installed and it works, meaning I can adb shell into the phone and run an 'su' command and I will be root.
When I try to run a command via code, it doesn't seem to work no matter which way I try to run it. I've tried many different variants of the following command.
Runtime.getRuntime().exec("su -c ps");
When I run this command on another rooted phone with a Superuser.apk or SuperSU.apk app installed, I get a dialog asking if I want to allow it to run with root permissions. When the apks are not there, it never asks and the command never works.
I've tried installing the apks on the first phone but they don't seem to do anything. So, as the original question asks --> Is there any way to run the elevated command from within the app without the SU apps installed?
It might be because you need to pass the commands to su as parameters like this:
su -c 'ls -l'
Or you might need to specify the full path to su, but I don't see why it wouldn't work the way you have it:
Runtime.exec("/system/bin/su -c ps")Or maybeRuntime.exec("/system/bin/su -c \'ps\'")
Try checking the output of this command too: System.getenv("PATH")
Another variant could be Runtime.exec("su -c \'ls -s \'")
Make sure you don't forget to escape the single quotes as they are part of the actual String.
Thats the way that I've found works most consistently, and it has also worked on devices that don't have Superuser or SuperSU installed, as those apps only listen for the Broadcast that is sent out when an application tries to run a command as root. #Boardy SuperSU and Superuser intercept the broadcast and so act as a middle man between the app and root privileges, but its not necessary for a rooted device. It IS necessary if you want to have more control over the applications that are running commands as root, but even then it still only limits you to deciding which applications, not which commands, are given root privileges.
Also, you might wanna take a look at RootTools and more specifically, the RootTools.isAccessGiven() command, which requests root privileges for your app.
Source: Launch a script as root through ADB
Not all versions of an 'su' for Android will accept a command to execute from the command line parameters.
Where they do not, you will need to let 'su' launch a privileged shell, obtain its input file descriptor, and pipe command(s) into that. This has been covered numerous times here on Stackoverflow.
I believe you would need to have the SU apps installed as they are what provide the user the question as to whether the app should be allowed to run as root or not.
You should be able to do this.
try :
adb root shell ls -l

Categories

Resources