[Q] su -c not working in root app - Android Q&A, Help & Troubleshooting

I am currently trying to write a root app.
I know that I can execute shell commands in a root shell like this.
However, I also want to execute some commands that way:
Code:
su -c[command]
But I can't get it to work if I use commands with parameters like ls -l or mkdir <path>. Executing something like su -c reboot works fine.
According to this it should work.
If I execute these commands using an adb shell or the Terminal Emulator app, they work fine.
This is my code:
Code:
package de.nikwen.sutest;
import java.io.IOException;
import android.os.Bundle;
import android.app.Activity;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Runtime runtime = Runtime.getRuntime();
try {
runtime.exec("su");
runtime.exec("su -c 'mkdir /data/data/abcdef'");
runtime.exec("su -c \"print asdf\"");
//However, this works:
// runtime.exec("su -c 'reboot'");
} catch (IOException e) {
e.printStackTrace();
}
}
}
I get this logcat:
Code:
04-02 21:03:14.509: D/su(3620): su invoked.
04-02 21:03:14.519: E/su(3624): Unknown id: /data/data/abcdef'
04-02 21:03:14.519: E/su(3624):
04-02 21:03:14.529: D/su(3623): su invoked.
04-02 21:03:14.539: D/su(3625): su invoked.
04-02 21:03:14.559: E/su(3626): Unknown id: asdf"
04-02 21:03:14.559: E/su(3626):
04-02 21:03:14.639: D/su(3629): 10079 de.nikwen.sutest executing 0 /system/bin/sh using shell /system/bin/sh : sh
Does anybody have an idea to solve my problems?
Could anybody please test this code on his device? I would really appreciate this as it could be ROM related. (http://forum.xda-developers.com/showthread.php?t=2180669)

Well, as far I know if you already used su you don't need to use it in the other commands, like this:
Code:
runtime.exec("su");
runtime.exec("mkdir /data/data/abcdef");
Anyway, to run commands as root easily, I recommend you RootTools

RoberGalarga said:
Well, as far I know if you already used su you don't need to use it in the other commands, like this:
Code:
runtime.exec("su");
runtime.exec("mkdir /data/data/abcdef");
Anyway, to run commands as root easily, I recommend you RootTools
Click to expand...
Click to collapse
First of all: Big thanks for your answer. :good:
Well, it doesn't work if I do not use
Code:
runtime.exec("su");
And not using the su command again works, but only if you write the commands into the OutputStream of the process which is returned.
You have to call it at least once after installation to make the SU app ask the user for permission. Then the other lines should work on its own.
The advantage of using su -c [command] is that the user isn't shown all these annoying Toasts like "App x has been granted Su permissions", just the first time when it requests su rights after each launch of the app. My app has to call these functions very often and all these Toasts are VERY annoying. If you look at apps like file managers, there is also just one Toast at launch time and then they execute all commands without any Toast.
According to this you should execute everything like this:
Usage: su -c 'command'
su -c 'command1; command2; .... ; commandN'
Click to expand...
Click to collapse
My question is just if this works on other devices or ROMs. I will really appreciate if you try it.
And if it doesn't, then my question will be why it doesn't.
EDIT: And I don't want to use any libraries, even though it would be much easier.

The strange thing is that the last quotation mark is seen as a part of the argument.
EDIT: Inserting a space before the quotation mark doesn't work:
Code:
04-03 00:02:59.129: E/su(13793): Unknown id: /data/data/abcdef
04-03 00:02:59.129: E/su(13793):
04-03 00:02:59.139: D/su(13790): su invoked.
04-03 00:02:59.139: D/su(13792): su invoked.
04-03 00:02:59.159: D/su(13794): su invoked.
04-03 00:02:59.169: E/su(13795): Unknown id: asdf
04-03 00:02:59.169: E/su(13795):
04-03 00:02:59.189: D/su(13796): db allowed
04-03 00:02:59.219: D/su(13798): 10079 de.nikwen.sutest executing 0 /system/bin/sh using shell /system/bin/sh : sh
EDIT2: Deleting the last quotation mark also didn't help:
Code:
04-03 00:05:18.409: D/su(14117): su invoked.
04-03 00:05:18.439: D/su(14120): 10079 de.nikwen.sutest executing 0 /system/bin/sh using shell /system/bin/sh : sh
04-03 00:05:18.439: D/su(14118): db allowed
04-03 00:05:18.459: E/su(14123): Unknown id: /data/data/abcdef
04-03 00:05:18.459: E/su(14123):
04-03 00:05:18.469: D/su(14122): su invoked.
04-03 00:05:18.489: D/su(14124): su invoked.
04-03 00:05:18.489: E/su(14125): Unknown id: asdf
04-03 00:05:18.489: E/su(14125):

Ok, in Terminal Emulator this works fine (2.3.7, CM-bassed):
su -c "ls /sys"
So it's kinda weird =/

RoberGalarga said:
Ok, in Terminal Emulator this works fine (2.3.7, CM-bassed):
su -c "ls /sys"
So it's kinda weird =/
Click to expand...
Click to collapse
Yes, it is.
Did you try the source code?
If you want, I can compile it for you.

Flashed this and it doesn't work, too.

Here is the compiled apk.
Could somebody please test this?

Tested, don't seems to work (it should create the folder /data/data/abcdef right?)

RoberGalarga said:
Tested, don't seems to work (it should create the folder /data/data/abcdef right?)
Click to expand...
Click to collapse
Yes, it should.
Thank you very much for your answer as you have been the only one giving me answers. :good:
EDIT: The link in your signature is broken.

However, I don't understand why this works here:
Code:
Runtime.getRuntime().exec("/system/bin/su -c 'setprop ctl.stop zygote'");
Something else I found:
Usage:
su --> becomes root (starts /bin/sh as root)
su -c '' --> run a command or many commands separated by ; as root.
Click to expand...
Click to collapse
(http://de.appszoom.com/android_applications/tools/superuser-su_feoig.html)

I have solved the problem now:
Code:
package de.nikwen.sutest;
import java.io.IOException;
import android.os.Bundle;
import android.app.Activity;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Runtime runtime = Runtime.getRuntime();
try {
runtime.exec("su");
runtime.exec(new String[] {"su", "-c", "mkdir /data/data/abcdef"});
runtime.exec(new String[] {"su", "-c", "print asdf"});
//do this to execute two ore more commands at once
runtime.exec(new String[] {"su", "-c", "mkdir /data/data/aaab; mkdir /data/data/aaac"});
} catch (IOException e) {
e.printStackTrace();
}
}
}
I know that I shouldn't run this on the main thread but in a service or at least in a different thread. This is for testing purposes only.
I missunderstood this blog entry.
But now everything works fine.
However, I still don't know why my first code example doesn't work. If anybody has an idea, please still answer my question as it hasn't been answered completely yet.
Again: Big thanks to RoberGalarga! :good:

Related

[Q] Read commands' output inside su process

Hello, maybe here someone will help me
I'm writing a file manager app and I want to allow it for browsing with root permissions.
All I have so far is creation of a Process object using Runtime.exec("su"). Then I get output stream from it and write "ls" command. And here goes the question. How to read the output of the "ls"? Getting the input stream from the process gives me stdout of the "su" which is useless.
glodos said:
Hello, maybe here someone will help me
I'm writing a file manager app and I want to allow it for browsing with root permissions.
All I have so far is creation of a Process object using Runtime.exec("su"). Then I get output stream from it and write "ls" command. And here goes the question. How to read the output of the "ls"? Getting the input stream from the process gives me stdout of the "su" which is useless.
Click to expand...
Click to collapse
Use the -c option of su:
Code:
su -c 'ls -l /system/'
I think I'm closer, but still it doesn't work
I have this:
Code:
p = Runtime.getRuntime().exec("/system/bin/su -c 'ls -d -1 "+directory.getAbsolutePath()+"/*'");
So the command for a directory /data will be:
Code:
/system/bin/su -c 'ls -d -1 /data/*'
But it gives me:
Code:
W/su (13979): request rejected (0->0 'ls)
I have tried putting the command's parts into array but then system asks for su permission on every command. For ex. ls /data needs permission and ls /system needs another permission beacuse the command is different.
Not much I can think of to do about that. I had a similar issue once upon a time and I dealt with it by using a script that read its commands from a data file. I'd write the datafile to my program's designated directory (no special permissions required), then run a single command with su and that script would read the datafile to know what to do, otherwise, I had a ****load of su requests bothering the user.
You've got a point there, but making it work with a file manager, where the commands are related to user interaction would be very difficult. Anyway I will put it into my consideration.
I wonder how all these root explorers are made but none of the developers, which I asked so far, were so kind to give me some tips
glodos said:
You've got a point there, but making it work with a file manager, where the commands are related to user interaction would be very difficult. Anyway I will put it into my consideration.
I wonder how all these root explorers are made but none of the developers, which I asked so far, were so kind to give me some tips
Click to expand...
Click to collapse
Well, I suppose you could keep a process open to a shell with root permissions and once open, keep input and output pipes routed to it and send and receive commands as needed.
Gene Poole said:
Well, I suppose you could keep a process open to a shell with root permissions and once open, keep input and output pipes routed to it and send and receive commands as needed.
Click to expand...
Click to collapse
Well, that's what I've tried to do, but as I mentioned in the first post, output pipe gives me stdout of the su process which doesn't write any output (but "ls" does).
glodos said:
Well, that's what I've tried to do, but as I mentioned in the first post, output pipe gives me stdout of the su process which doesn't write any output (but "ls" does).
Click to expand...
Click to collapse
No, I don't think you're following me. Just run su -c 'sh' and it should run a shell and keep it open. From there, you create an input stream, output stream and possibly an error stream, then write commands like "ls -l /system\n" (the \n triggers the shell to execute it) to the output stream, then read the results form the input stream. You keep doing this as needed and when you're done just send "exit\n".
Oh, I understand now. I'll try it ASAP.
Edit:
It works now, but I have problems with stopping the loop. Here is my piece of code:
Code:
String[] cmd = new String[]{"su", "-c", "/system/bin/sh"};
console = Runtime.getRuntime().exec(cmd);
BufferedWriter stdin = new BufferedWriter(new OutputStreamWriter(console.getOutputStream()));
stdin.write("ls -d -1 "+directory.getAbsolutePath()+"/*\n");
BufferedReader stdout = new BufferedReader(new InputStreamReader(console.getInputStream()));
String read;
data1 = new String();
while((read=stdout.readLine())!=null){
data1+=read + "\n";
}
The problem is, that it hangs at some point on invocation of "stdout.readLine()". I have read that it waits for some data to come and it will never be null.
Furthermore if my ls command returns nothing (which can happen) it always hangs forever on readLine().
Anyway I'll try to do something with this. Maybe there is a workaround and reading will not block.
Thank you for your effort, it was really helpful.
glodos said:
The problem is, that it hangs at some point on invocation of "stdout.readLine()". I have read that it waits for some data to come and it will never be null.
Furthermore if my ls command returns nothing (which can happen) it always hangs forever on readLine().
Anyway I'll try to do something with this. Maybe there is a workaround and reading will not block.
Thank you for your effort, it was really helpful.
Click to expand...
Click to collapse
Sorry to ressurect such an old thread. I'd been having the same problem with reads blocking using BufferedReader, InputStream and other variants. Turns out BufferedReader has a ready() method which indicates whether a read() will block. This code works for me:
Code:
String outputStr;
BufferedReader reader = new BufferedReader(new InputStreamReader(suProcess.getInputStream()));
while (reader.ready()) {
outputStr += reader.readLine();
}
Hope it helps someone from the repeating the same frustrations. Heck I hope it helps me in the future in case I forget this

[Q] got exception when executed "am start" command on xt720

To use adb shell, I executed the following command on motorola xt720:
===============
C:\Documents and Settings\guominl>adb -s 040394FD1901500C shell
$ am start -a android.intent.action.CALL tel:10086
===============
And got the following responses from console:
===============
am start -a android.intent.action.CALL tel:10086
Starting: Intent { act=android.intent.action.CALL dat=tel:10086 }
java.lang.SecurityException: Permission Denial: starting Intent { act=android.in
tent.action.CALL dat=tel:10086 flg=0x10000000 cmp=com.android.phone/.OutgoingCal
lBroadcaster } from null (pid=-1, uid=-1) requires android.permission.CALL_PHONE
======================================
My XT720 software version is STR_U2_01.18.2, there is somebody to know the reason? why? I need ugrade my XT720 software to 2.2 version?
thanks
guomin

[Q] App development using su permission causes SuperSU problem with su binary file

Hello everyone,
An error related to SuperSU's su binary file occured when i try to run "mount" linux command through background sh process.
Everything is ok in the process of running su and a root permission is properly got by SuperSU, code is here:
Code:
Process process = (new ProcessBuilder("/system/bin/sh")).redirectErrorStream(true).start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
PrintWriter writer = new PringWriter(process.getOutputStream());
writer.println("echo start");
writer.println("su");
writer.println("echo end");
String res = null;
while ((res = reader.readLine()) != null) {
if (res.equals("end")) break;
}
Of cause i run it in a sub thread and won't block the UI thread.
And in the click listener of a button i trigger the mount command in the similar process.
writer.println("toolbox mount -o rw,remount /system");
But when i successfully mount that path and return to SuperSU, the error occurs with no doult.
An error dialog will be poped up like this: There is no SU binary installed, and SuperSU cannot install it. This is a problem!
Any one have an idea that why running a single linux mount command can cause that problem? And how couldi do?
More information: I have tried several other command like pwd, ls and other basic command, but all of them work well, except
mount, who would like to explain this problem?

[Q] Android 4.3, upgrading file's permissions

I have an app, pushing it to in /data/local/tmp/myapp
I have root access for a while in exploit, so my goal is to setup "privileges" to /data/local/tmp/myapp, so it will be running as root even if was called from sh ( sh is running with shell privilleges )
_________________________________
BEFORE 4.3. code works fine ( executing in a context of process with root privileges ):
Code:
chown( "/data/local/tmp/myapp", 0 , 0); //owner to root
chmod("/data/local/tmp/myapp" 06777); //chmod myapp to suid
ls shows cute output after that:
-rwxrwxrwx root root myapp
Click to expand...
Click to collapse
Thats enough so myapp starts with uid == 0 even when was launched from "sh" with shell's uid.
4.3 this is NOT ENOUGH. Additional SE policies comes here ...
ls -Z shows the next output:
-rwxrwxrwx root root u: object_r:shell_data_file:s0 myapp
Click to expand...
Click to collapse
When i'm starting myapp from sh BEFORE 4.3 everything goes fine, but on 4.3 myapp launches with uid != 0.
PS: modifying context through chcon to u: object_r:system_file:s0 of myapp didnt help
_________________________________
Maybe someone have some ideas where i can continue research? :crying:

Circumventing root detection with custom kernel

Hi everyone (and sorry, can't post proper links yet),
I'm a security/pentester looking for a generic way of circumventing root detection. Only thing I'm usually interested is to have full filesystem access (check how apps encrypt their data), start a couple of execs with root (eg. frida-server) and have a root shell in general. I have a Nexus 5 "hammerhead", installed full stock image MOB30Y, then checked the kernel and downloaded the kernel source code for the matchin 3.4.0-gcef4f17. I added a backdoor to the kernel code, similar to this backdoor: github.com/allwinner-zh/linux-3.4-sunxi/blob/bd5637f7297c6abf78f93b31fc1dd33f2c1a9f76/arch/arm/mach-sunxi/sunxi-debug.c#L41 , then recompiled the kernel, and booted the device with that kernel. So far so good:
Code:
[email protected]:/ $ id
uid=2000(shell) gid=2000(shell) groups=2000(shell),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats) context=u:r:shell:s0
*trigger the backdoor*
Code:
[email protected]:/ $ id
uid=0(root) gid=0(root) groups=0(root),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats) context=u:r:shell:s0
So I'm uid 0 now. Now I just need to get around the SELinux mess. Problem:
Code:
[email protected]erhead:/data/data $ ls /data/data
opendir failed, Permission denied
My question: Anybody knows how I can call functions from android.googlesource.com/platform/external/libselinux/+/jb-mr1-dev-plus-aosp/include/selinux/selinux.h so I get the init context?
I'm not too familiar with these calls.... I think something along:
Code:
#include <selinux/selinux.h>
if is_selinux_enabled(){
struct security_context_t *cont;
getcon(cont); //This should get the kernel's context
//How do I assign the kernel's context to the "current" process context?
//?
freecon(cont);
}

Categories

Resources