Подтвердить что ты не робот

Запустите службу с привилегиями Root или добавьте разрешения с правами root

В настоящее время я разрабатываю приложение, которое считывает SMS/электронную почту во время вождения. Многие пользователи пожелали поддержки WhatsApp/KakaoTalk.

Однако, поскольку нет "официального" способа получения своих сообщений, будет только три варианта, требующих root:

Более простой способ сканирования своей базы данных в заданной интервал.

  • Легко реализовать.
  • Однако не эффективен аккумулятор
  • Также сообщения сразу не считываются.

Другой способ - запустить службу с правами root и зарегистрировать приемник, который будет слушать свои push-уведомления. Это необходимо сделать с помощью root, так как для обоих пакетов требуется разрешение на основе подписи для получения своих push-уведомлений.

  • Сложнее реализовать
  • Лучший пользовательский интерфейс

Также мне пришло в голову следующее: можно ли вручную добавить разрешения в APK после установки? В этом случае я мог бы добавить разрешения c2dm в свой пакет.

  • Это упростит работу.
  • Тем не менее, я немного боюсь изменить права доступа к приложениям, поскольку это полностью противоречит принципу Android Sandbox.
  • Тем не менее, если бы это было возможно, дайте мне знать!

Проблема в том, как именно я запускаю службу с правами root (действительно ли это возможно)? Я знаю, как запускать команды оболочки или двоичные файлы с помощью root, но я не знаю, как запустить часть APK как root.

Кроме того, можно ли интегрировать BroadcastReceiver в двоичный файл? У меня нет опыта работы с C/С++, особенно в среде Android.

Можете ли вы мне помочь? Благодарю.

edit: Как я уже сказал в комментарии, я не хочу использовать AccesibilityService, так как он не соответствует моим потребностям (например, он даст мне "2 непрочитанных сообщения", если более одного непрочитана, также она не включает полное тело).

edit2: Просто для разъяснения вещей: я знаю, как запускать команды с помощью root. Мне нужно знать, как зарегистрировать Broadcastreceiver, который получает определенные "обычные" приемники вещания, которые не получают, поскольку сам Broadcast требует разрешения на основе подписи, которого у меня нет.

4b9b3361

Ответ 1

Это далеко не тривиально, но должно работать, когда приложения, которые вы хотите контролировать, используют базы данных sqlite или, что более общие, пишут сообщения в файл, когда они приходят.

Вам действительно нужно иметь root-доступ к устройству, так как это нарушает систему безопасности Android:

Напишите собственный процесс, который запускается как демон с NDK и запускает его один раз после загрузки с правами root. У вас есть 3 основные проблемы:

Как узнать, что-то изменилось?

Это легкая часть. Вам нужно будет использовать интерфейс linux inotify, который должен быть доступен на каждом телефоне Android, поскольку SDK имеет FileObserver, поскольку API 1, поэтому вы находятся на стороне сохранения здесь.

Еще одна интересная вещь - поймать сообщения C2DM. Я нашел класс NDK, который называется BroadcastReceiver, поэтому NDK может их поймать. Но я лично этого не сделал бы, мне нехорошо украсть намерения. Также вам придется перераспределить их или позволить им путешествовать к реальному получателю, поэтому я не буду описывать это подробно здесь. Он может работать, но может быть сложнее и должен быть только резервным.

Итак, когда вы это решили, возникает следующая проблема:

Как читать изменения в экономном режиме?

У вас есть проблема, большая, здесь. Файл не принадлежит вам, вы даже не имеете права знать, где он (обычно). Таким образом, контролируемое приложение не осведомлено о вас и будет действовать так, как будто файл принадлежит ему исключительно. Если они используют какой-то простой старый текстовый файл для записи сообщений, вам нужно найти способ безопасного его чтения, поскольку он может быть перезаписан или расширен в любое время. Но вам может повезти, когда они используют sqlite, в соответствии с this он полностью действителен, чтобы иметь более одного одновременного читателя, всего лишь одного автора. Мы в спецификации, все хорошо. Когда вы сейчас зачитали новые данные, вам нужно решить больше проблем:

Как вернуть новые данные в основное приложение?

В этой программе c/С++ вы должны делать только минимальный минимум, потому что он работает от имени root. Вы также должны защищать пользователей приложений от нарушений безопасности, поэтому, пожалуйста, запрограммируйте демона на это. У меня нет реальной идеи, что это может работать действительно хорошо, но вот некоторые из них:

  • Напишите собранные данные в вашу собственную базу данных sqlite (легко в c/С++ и java).
  • Запишите собранные данные в обычный файл (не рекомендуется вообще, боль в задней части)
  • Отправить намерение, которое содержит новые данные (может быть, это не так просто в c/С++, но легко в java)
  • Сокеты/трубы/..., только каждый механизм rpc, который вы можете себе представить, который вам привнес Linux (так же, как и файл, не делайте этого)

Как указано в приведенном выше тексте, будьте осторожны, когда вы пишете этого демона, так как это потенциальная угроза безопасности. Также может быть трудно сделать это, когда вы вообще не знаете о c/С++, и даже когда вы написали простые программы, это должно быть нетривиальной задачей.

В моем поиске через Интернет я нашел эти классы NDK С++, о которых я говорил выше. Его можно найти в коде Google. У меня нет опыта работы с NDK или с оболочкой С++, но, возможно, стоит посмотреть, когда вы планируете это написать.

Ответ 2

запустить что-то, как root, не является правильным способом решения этого вопроса.

вместо этого рассмотрите службу доступности, которая может следить за новыми уведомлениями:

AccessibilityEvent

Ответ 3

Невозможно запустить службу (или любой другой компонент приложения, если на то пошло) в качестве пользователя root, если вы настроили таргетинг на неизменные, некорневые устройства. Это позволит сделать все механизмы безопасности в Android бессмысленными.

Невозможно также изменить разрешения APK во время выполнения. Разрешения всегда предоставляются или отклоняются при установке APK. Пожалуйста, обратитесь к http://developer.android.com/guide/topics/security/security.html для получения дополнительной информации по этому вопросу.

Ответ 4

Сила, я должен сказать вам, что Служба Android не требует доступа root, а некоторые действия (т.е. доступ, чтение, запись системных ресурсов) требуют Root Permissions. Каждый Android-сервис, предоставляемый в Android SDK, может работать без ROOT ACCESS.

Вы можете выполнить действия с правами root с помощью команд оболочки.

Я создал абстрактный класс, который поможет вам с этим

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import android.util.Log;

public abstract class RootAccess {
    private static final String TAG = "RootAccess";
    protected abstract ArrayList<String> runCommandsWithRootAccess();

    //Check for Root Access
    public static boolean hasRootAccess() {
        boolean rootBoolean = false;
        Process suProcess;

        try {
            suProcess = Runtime.getRuntime().exec("su");

            DataOutputStream os = new DataOutputStream(suProcess.getOutputStream());
            DataInputStream is = new DataInputStream(suProcess.getInputStream());

            if (os != null && is != null) {
                // Getting current user UID to check for Root Access
                os.writeBytes("id\n");
                os.flush();

                String outputSTR = is.readLine();
                boolean exitSu = false;
                if (outputSTR == null) {
                    rootBoolean = false;
                    exitSu = false;
                    Log.d(TAG, "Can't get Root Access or Root Access deneid by user");
                } else if (outputSTR.contains("uid=0")) {
                    //If is contains uid=0, It means Root Access is granted
                    rootBoolean = true;
                    exitSu = true;
                    Log.d(TAG, "Root Access Granted");
                } else {
                    rootBoolean = false;
                    exitSu = true;
                    Log.d(TAG, "Root Access Rejected: " + is.readLine());
                }

                if (exitSu) {
                    os.writeBytes("exit\n");
                    os.flush();
                }
            }
        } catch (Exception e) {
            rootBoolean = false;
            Log.d(TAG, "Root access rejected [" + e.getClass().getName() + "] : " + e.getMessage());
        }

        return rootBoolean;
    }

    //Execute commands with ROOT Permission
    public final boolean execute() {
        boolean rootBoolean = false;

        try {
            ArrayList<String> commands = runCommandsWithRootAccess();
            if ( commands != null && commands.size() > 0) {
                Process suProcess = Runtime.getRuntime().exec("su");

                DataOutputStream os = new DataOutputStream(suProcess.getOutputStream());

                // Execute commands with ROOT Permission
                for (String currentCommand : commands) {
                    os.writeBytes(currentCommand + "\n");
                    os.flush();
                }

                os.writeBytes("exit\n");
                os.flush();

                try {
                    int suProcessRetval = suProcess.waitFor();
                    if ( suProcessRetval != 255) {
                        // Root Access granted
                        rootBoolean = true;
                    } else {
                        // Root Access denied
                        rootBoolean = false;
                    }
                } catch (Exception ex) {
                    Log.e(TAG, "Error executing Root Action", ex);

                }
            }
        } catch (IOException ex) {
            Log.w(TAG, "Can't get Root Access", ex);
        } catch (SecurityException ex) {
            Log.w(TAG, "Can't get Root Access", ex);
        } catch (Exception ex) {
            Log.w(TAG, "Error executing operation", ex);
        }

        return rootBoolean;
    }


}

Расширьте свой класс с помощью RootAccess или создайте экземпляр класса RootAccess и переопределите метод runCommandsWithRootAccess().

Ответ 5

"Мне нужно знать, как зарегистрировать Broadcastreceiver, который получает определенные" обычные "приемники вещания, которые не получаются, так как сам Broadcast требует разрешения на основе подписи, которого у меня нет".

Вы не можете. Период. Конец истории. И спасибо за это за это.

Да, если вы используете объекты с ужасным корневым устройством, чтобы иметь некоторый код, выполняемый как root, вы можете теоретически делать все, что захотите. На практике это может быть довольно сложно обойти это ограничение, и платформа часто разработана таким образом. Вам, по крайней мере, нужно будет возиться с состоянием, поддерживаемым и/или сохраненным менеджером пакетов, и, вероятно, вам придется заставить пользователя перезагрузить устройство, чтобы получить изменения, которые вы делаете как root, чтобы на самом деле повлиять. И, конечно же, вы тогда возитесь с глубоко внутренними деталями реализации платформы, что означает разброс повсюду в разных версиях платформы и разных сборках от разных производителей.

Ответ 6

вы можете использовать

pm grant your.permission

в качестве команды оболочки для предоставления дополнительных разрешений для вашего приложения. Я думаю, что команда была добавлена ​​совсем недавно, поэтому, если вы нацелились на более старые версии, вам может потребоваться прямое изменение "package.xml".

Можно выполнить файл app/dex как root с помощью команды app_process, но я еще не понял, как получить допустимый контекст (с этим вы можете использовать java.io.File api для доступа ко всем файлы, но не статические андроидные методы, такие как bindService и т.д., будут терпеть неудачу, потому что вы работаете без контекста приложения).

Ответ 7

Конечно, вы можете изменить разрешения своих приложений. Если разрешения будут изменены, пользователю просто нужно будет вручную обновить приложение, и новое разрешение будет отображаться пользователю. Но я точно не знаю, как изменение разрешения вашего приложения поможет вам в решении этой проблемы.

Еще одна вещь, которую я могу вам сказать, заключается в том, что вы не можете запускать Service или как-то как root, только на корневых устройствах, и будет непростой задачей укоренять устройства через ваше приложение, а также это не будет то, что многие пользователи захотят.

Как вы в настоящее время обращаетесь к SMS? Если у вас есть BroadcastReceiver, вы можете установить MAX_PRIORITY для своего receiver и, возможно, перехватите сообщения перед другими приложениями. Это можно сделать следующим образом:

   <receiver android:name=".SmsReceiver" >
        <intent-filter android:priority="100" >
            <action android:name="android.provider.Telephony.SMS_RECEIVED" />
        </intent-filter>
    </receiver>

Вы также можете использовать SMS Provider, который теперь не является общедоступным, но, возможно, если вы запросите с заданным интервалом этот Provider, вы можете проверить наличие новых сообщений. Вы также можете посмотреть эту тему: Android SMS Provider, если вы еще не сделали этого allready.