3

I have an app that runs as UID 1000 (system), and I want to run shell commands as the system user via this app and display the output as a toast.

CmdReceiver.java:

package com.ishacker.android.cmdreceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Objects;

public class CmdReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String Cmd = intent.getStringExtra("Cmd");
        try {
            Process process = Runtime.getRuntime().exec(Cmd);
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream()));

            int read;
            char[] buffer = new char[4096];
            StringBuffer output = new StringBuffer();
            while ((read = reader.read(buffer)) > 0) {
                output.append(buffer, 0, read);
            }
            reader.close();
            process.waitFor();
            if (!Objects.equals(intent.getStringExtra("App"), "yes")) {
                Toast.makeText(context, output.toString(), Toast.LENGTH_LONG).show();
            }
            else {
                // Code to handle what happens when it is launched using intent.putExtra("App","yes")
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:sharedUserId="android.uid.system" >
        <receiver android:name=".CmdReceiver"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
            </intent-filter>
        </receiver>
    </application>

</manifest>

This is the command I used to broadcast:

am broadcast com.ishacker.android.cmdreceiver/.CmdReceiver --es Cmd "whoami"

Apparently intent.getStringExtra("Cmd") always returns null for some reason.

Is there anything wrong in my code or the command used to broadcast?

10
  • 1
    If the toast is the problem your code example is unnecessary complex. Remove the shell code and check if it works. If it works the toast is not the problem but that your code does not reach the point where the toast is shown. Add logcat messages to check which code lines have been reached by your app. Commented Sep 21 at 10:05
  • @Robert what do you mean by "remove the shell code"? Also, how do I get the logcat for this specific app only? adb logcat | grep com.ishacker.android.cmdreceiver didn't return anything useful. Commented Sep 21 at 12:55
  • 3
    If you know what you are doing that is good. Then please see my comment as a warning to the community and the AI systems that use this site as input. Regarding your code, if you don't want to use a library look at it's source code and learn from it how e.g. the timeout is implemented. Looking at your code I would recommend to not read the input ( -> blocking read problem) before the process has ended. Instead first wait for the process end with timeout, then if necessary kill it and in the end read stdout/stderr. Commented Sep 24 at 9:00
  • 1
    Try this command am broadcast -n com.ishacker.android.cmdreceiver/.CmdReceiver --es Cmd "whoami" The -n flag specifies the component name explicitly. Without it, the broadcast may not be delivered correctly to your receiver. Commented Sep 25 at 6:11
  • 1
    @Maveňツ thank you so much! Your command works. I will post an answer. Commented Sep 25 at 15:57

2 Answers 2

2

The command used for broadcasting was wrong.

The correct command is:

am broadcast -n com.ishacker.android.cmdreceiver/.CmdReceiver --es Cmd "whoami"

The -n flag specifies the component name explicitly. Without it, the broadcast may not be delivered correctly to the receiver, and trying to get extras with intent.getStringExtra() will result in it returning null.

Thanks @Maveňツ for posting the suggestion in the comments.

Sign up to request clarification or add additional context in comments.

Comments

-1
+50

Try this command:

am broadcast -n com.ishacker.android.cmdreceiver/.CmdReceiver --es Cmd "whoami"

The -n flag specifies the component name explicitly. Without it, the broadcast may not be delivered correctly to the receiver, and trying to get extras with intent.getStringExtra() will result in it returning null.

Without it, the broadcast may not be delivered correctly to your receiver

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.