Если приложение данных, подписанное ключом поставщика, сможет запустить su

Фон: Я разрабатываю устройство для вывесок, которым нужно управлять удаленно. Мне нужно приложение, которое может

  • Получите и установите новые пакеты
  • Перезагрузите устройство (для устранения неполадок)

У меня не рутированное устройство Android. У меня также есть файлы, которые, как мне сказали, являются ключами платформы.

Я разработал приложение, которое пытается запустить процесс su.

Process p = Runtime.getRuntime().exec("su");

До того, как я подписал приложение ключами платформы, он выбрасывал IOException с сообщением Permission Denied.

Я подписал приложение этими ключами платформы, но все еще получаю исключение Permission Denied.

Вот три противоречивых утверждения. Какое из этих утверждений (если есть) верно?

Положение 1: Это должно сработать. Приложение, даже если оно хранится в /data/app, должно иметь возможность запускать su. Либо у меня неправильные ключи, либо есть другая запись, которую мне нужно добавить в манифест, чтобы заставить его работать.

Положение 2: Это не должно работать. Несмотря на то, что оно подписано ключом платформы, приложение находится в /data/app, поэтому это приложение для обработки данных, а не системное приложение. Приложения данных не могут запускать su на некорневых устройствах. Если бы это приложение было установлено в /system/app, оно могло бы запускать su. (И я не могу вставить его в /system/app, потому что он не рутирован, поэтому я застрял).

Положение 3: Это никогда не сработает. Если устройство не рутировано, то НИЧТО не сможет запустить su, даже если это подписанное системное приложение.

0
0
159
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я бы выбрал утверждение 3. Это никогда не будет работать на некорневом устройстве Android. По крайней мере, не в последних версиях ОС Android (я понятия не имею, может ли это работать на действительно старых устройствах Android).

«su» - это приложение - на диске должен быть двоичный файл «su» для его выполнения, а Android по умолчанию не предоставляет двоичный файл «su» в целях безопасности. Когда вы используете сторонние руткиты, они устанавливают свой собственный двоичный файл «su», чтобы предоставить пользователю механизм для повышения себя до привилегий root.

Если ваше приложение подписано специальным ключом и ему при запуске предоставлены повышенные привилегии, зачем вам все равно нужно выполнять «su»?

В ответ на вопрос, почему мне нужно выполнить «su» - мне нужно автоматически перезапустить устройство, а также автоматически установить новые пакеты. Может, вместо su я должен просто запустить reboot или pm?

Andrew Shepherd 08.09.2018 03:53

Да, это было бы то, что я бы попробовал. Однако у меня никогда не было ключа платформы, поэтому я не могу говорить по опыту.

K9spud 08.09.2018 19:48

Непосредственное выполнение процесса reboot или pm действительно работает.

Andrew Shepherd 10.09.2018 04:10
Ответ принят как подходящий

В Android даже не должно быть двоичного файла su, если вы не установили на устройство какой-либо корневой метод, такой как Magisk или SuperSU.

Даже если у него есть двоичный файл su, я бы не ожидал, что он будет работать по одной из двух причин. Предполагая, что на вашем устройстве предустановлен двоичный файл su, кто им управляет? Если он неуправляемый, он должен просто отклонять все запросы. Если вы запускаете корневой метод, то этот менеджер должен решить, получит ли ваше приложение доступ к su, независимо от того, есть ли у вас разрешения на уровне подписи или нет (в конце концов, корневой менеджер использует другую подпись).

И зачем вам вообще нужен доступ к su в качестве приложения для подписи? В любом случае у вас есть полный доступ к устройству. Если вам нужно запустить команду, у вас не должно возникнуть проблем, независимо от того, что вы запускаете, если это делается из вашего пакета, подписанного платформой. Но поскольку у вас есть полный доступ, собственные API-интерфейсы должны позволить вам делать все, что вам нужно.

Что касается исключения IOException, возвращаемого при попытке выполнить su в процессе, это просто странная причуда Android. Если двоичный файл su не установлен, он иногда возвращает command not found, а иногда - permission denied, в зависимости от устройства.

Я думаю, что я хочу сказать, что, если ваше приложение не является корневым менеджером, вы можете быть частью system_server и по-прежнему иметь такой же доступ к su, как и все остальные. Что касается утверждения, с которым я согласен, я думаю, № 3, хотя я не полностью согласен с ним, потому что есть вероятность, что su просто не существует, или это плохой двоичный файл.

Я объяснил, почему №1 не должен быть правдой, а №2 просто неверен. Если вы посмотрите на манифест платформы, каждое разрешение, для которого требуется привилегированное приложение, также может быть предоставлено приложениям для подписи. Так что даже если вы переместите свое приложение на /system/priv-app/ (/system/app/ не сделает его привилегированным), это не будет иметь никакого значения. По сути, если ваше приложение подписано подписью платформы, не имеет значения, где оно установлено.

Обновлено:

Вы можете легко перезагрузиться, просто запустив reboot как команду, поскольку у вас есть доступ к системе на уровне подписи, но для этого немного более элегантно использовать соответствующий API. Если вы используете API, вы получаете анимацию выключения, но вы также позволяете системе корректно завершать работу, останавливая службы и отправляя широковещательную рассылку ACTION_REBOOT всем приложениям, которые могут ее прослушивать.

Чтобы использовать API, сначала добавьте следующее разрешение к вашему AndroidManifest:

<uses-permission android:name = "android.permission.STATUS_BAR_SERVICE" />

Теперь, когда вам нужно вызвать действие перезагрузки, используйте следующий код:

IStatusBarService bar = IStatusBarService.Stub.asInterface(ServiceManager.getService(Context.STATUS_BAR_SERVICE));
bar.reboot(false); //using true here will reboot to Safe Mode

Этот метод является скрытым, поэтому, если вы используете Android Studio для редактирования и компиляции, он выдаст ошибку. Вы можете использовать отражение или использовать Скрытый API Android для прямого доступа к нему.

Вот как это реализовано в системном интерфейсе в меню питания: https://github.com/aosp-mirror/platform_frameworks_base/blob/master/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java

Это класс, реализующий сервис IStatusBar: https://github.com/aosp-mirror/platform_frameworks_base/blob/master/services/core/java/com/android/server/statusbar/StatusBarManagerService.java#L969

Спасибо. Никогда бы не догадался, что permission denied означает it is not even there. В ответ на вопрос, почему мне нужно выполнить su - мне нужно удаленно перезапустить устройство, а также удаленно обновить существующие пакеты. Может быть, вместо запуска su я могу напрямую выполнить reboot или pm?

Andrew Shepherd 08.09.2018 03:58

Да, у тебя должно получиться это сделать. Однако вы также можете использовать API для правильного выключения устройства (позволить ему остановить все службы, вызвать намерение выключения и т. д.). Я отредактирую свой ответ этим

TheWanderer 08.09.2018 04:02

Непосредственное выполнение процесса pm работает! Спасибо, что направили меня на правильный путь.

Andrew Shepherd 10.09.2018 04:09

Кажется, проще перезагрузить устройство через службу PowerManager. Есть ли техническая причина, по которой вы предпочитаете службу строки состояния службе PowerManager, или это просто путь, по которому вы пошли? stackoverflow.com/a/32984952/25216

Andrew Shepherd 12.09.2018 02:36

@AndrewShepherd именно то, что я нашел. Вы можете использовать и то, и другое. Я думаю, что они оба оказываются в одном месте.

TheWanderer 12.09.2018 02:37

Другие вопросы по теме