• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Что и как можно достать из Android - Теория + код

zebra0_0

RAID-массив
Пользователь
Регистрация
05.10.2024
Сообщения
68
Реакции
45
Всем привет,
решил написать стать по тому что можно достать из android устройства. Ну или по крайней мере всё то что приходит мне в голову. В статье буду использовать JAVA в качестве инструмента для получения данных и буду приводить мелкие но рабочие примеры кода с пояснением как и что использовать. Постараюсь идти максимально плавно. Начать с того что не требует дополнительных разрешений и не считается системой android опасным разрешение и буду продвигаться к более сложно получаемым но в теории более полезным для тех или иных сфер.

В статье будут:

  • Данные об устройстве
  1. Модель и производитель устройства
  2. Версия Android
  • Данные сети к которой подключено устройство
  1. Тип сети
  2. Имя Wi-Fi сети
  3. IP-адрес
  • Геолокация
  • Данные о пользователе
  1. номера телефонов
  2. Список установленных приложений
  3. список контактов
  • журнал вызовов


Данные об устройстве

Данные об устройстве можно сказать наименее полезные так как их сложно как-то самостоятельно использовать в зловредных целях. Но и бесполезными их назвать нельзя. Так-как в любом адекватном рат на android есть версия adnroid, имя устройства и подобное.
Версия android:
Тут всё банально и просто. Никаких дополнительных разрешений. Достаточно просто вызвать:
Build.VERSION.RELEASE

Имя устройства:

Точно так-же, просто вызываем:

Build.MODEL

Данные сети к которой подключено устройство

Данные о сети нужны можно применять в различных целях. Таких как:

Определять страну откуда устройство
Если крупный то город
определять есть-ли подключение к сети чтобы не слать запросы в пустоту
имя сети для дальнейших атак


Тип и статус сети

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

Так что вот функция которая проверяет если ли подключение и если да то к какому типу оно относится:

Java:
public String getConnectionType(Context context) {
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

    if (cm == null) return "Неизвестно";

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        Network network = cm.getActiveNetwork();
        if (network == null) return "Нет подключения";

        NetworkCapabilities caps = cm.getNetworkCapabilities(network);
        if (caps == null) return "Нет подключения";

        if (caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
            return "Wi-Fi";
        } else if (caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
            return "Мобильная сеть";
        } else {
            return "Другое подключение";
        }
}

Тут во второй строке получается состояние сети и далее с помощью многочисленных проверок выясняется что да как.

Как применять:

Java:
String status = getConnectionType(getApplicationContext());
Log.d("Сеть", "Тип подключения: " + status);


SSID

Для того чтобы получить ssid(Имя сети ) уже нужно разрешения. А именно надо добавить внутрь манифеста:

XML:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

и потом запрашиваем их внутри activity:

Java:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
        != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
}

и потом вызываем getWifiSSID(getApplicationContext()); например внутрь какой-нибудь переменой. Например:
Java:
String wifiName = getWifiSSID(getApplicationContext());


IP
Наверное самое полезное и часто используемое это IP (Internet Protocol address).

Его можно использовать для получения приёмной геолокации устройства. Точного получения страны. Или ещё довольно большого количества других применений.

К сожалению прямое его получение из adrodiAPI было ограниченно в последних версия андроида и получить его напрямую нельзя во избежание утечки данных и слежки . Но это легко обходит прямым http запросом на любой сайт который возвращает твой API адрес. Например https://api.ipify.org/ .

пример запроса:

Java:
URL url = new URL("https://api.ipify.org?format=json");
HttpURLConnection conn = (HttpURLConnection) url.openConnection()

Таким же методом можно вычислить страну и примерно город.


Геолокация

её проще у точнее всего получить с помощью Google Location Services (FusedLocationProviderClient). Его встроенным в андроид изначально нету и надо добавлять отдельную зависимость.

А именно в файл build.gradle
Код:
implementation ("com.google.android.gms:play-services-location:21.0.1")

Далее необходимо добавить и запросить в обязательном порядке разрешение ACCESS_FINE_LOCATION или ACCESS_COARSE_LOCATION

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

Код запроса внутри activity модно взять выше просто заменить разрешение

Далее нам надо понять как будет выглядеть геолокация. С помощью Google Location Services можно получить широту и долготу (Пример: 55.75371657187264, 37.61993133146647) .

код:

Java:
FusedLocationProviderClient fusedClient = LocationServices.getFusedLocationProviderClient(this);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
    return;
}
fusedClient.getLastLocation()
    .addOnSuccessListener(location -> {
        if (location != null) {
            double lat = location.getLatitude();
            double lon = location.getLongitude();
            Log.d("Geo", "Широта: " + lat + ", Долгота: " + lon);
        } else {
            Log.d("Geo", "Нет данных. Возможно GPS выключен.");
        }
    });


Как это работает:


FusedLocationProviderClient - Класс, через который Google даёт геолокацию,

getLastLocation() - Получает последнюю известную точку,

if (location != null) - Проверка: есть ли данные

location.getLatitude() - Получаем широту

location.getLongitude() - Получаем долготу

Номера телефона

Номера с sim-карт хранятся в поле MSIISDN на самой sim-карте, если оно есть.
Но оно не читается из файлов — это нечто вроде системной метаинформации, к которой даёт доступ Android через SubscriptionManager.

Чтобы его/их получить надо вызвать subscriptionInfoList.getNumber() . getNumber запрашивает их у системы. Но важно учесть что требуется разрешение READ_PHONE_STATE иначе getNumber вернёт null.
В манифест:
XML:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

Готовое решение в виде кода:
Java:
if (subscriptionInfoList != null && !subscriptionInfoList.isEmpty()) {
                if (subscriptionInfoList.size() > 0) {
                    sim1 = subscriptionInfoList.get(0).getNumber();
                    if (sim1 == null || sim1.isEmpty()) {
                        sim1 = "SIM-карта отсутствует";
                    }
                }

В данном коде проверяется не является ли subscriptionInfoList пустым, если нет то запрашивает getNumber для sim1. Точно так-же можно получать номер для sim2 и т.д. заменяя sim1 на sim2.
Для более гибкого использования можно добавить получения второго номера не прям точно так-же а сначала проверять количество элементов в subscriptionInfoList и если их больше чем 1 то запрашивать второй номер.

код для получения второго номера:
Java:
if (subscriptionInfoList.size() > 1) {
                    sim2 = subscriptionInfoList.get(1).getNumber();
                    if (sim2 == null || sim2.isEmpty()) {
                        sim2 = "SIM-карта отсутствует";
                    }
                }

и в конце возвращаем sim1, sim2 .
Java:
return new String[]{sim1, sim2};

дальше можно легко использовать в других функциях:

String[] simNumbers = getSimNumbers();
String sim1 = simNumbers[0];
String sim2 = simNumbers[1];

Список установленных приложений
В Android список установленных приложений можно получить через PackageManager. Но начиная с версии Android 11 появились ограничения и теперь для получения списка установленных приложений надо QUERY_ALL_PACKAGES

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

Далее всё просто надо получить объект PackageManager он позволяет нам работать с установленными приложениями, разрешениями, компонентами и т.д. Это как менеджер программ.
PackageManager pm = getPackageManager();

Второй шаг это получить List ApplicationInfo и поставить флаг GET_META_DATA - это флаг, говорящий системе: «дай мне ещё и метаинформацию, если она есть.
List<ApplicationInfo> apps = pm.getInstalledApplications(PackageManager.GET_META_DATA);

Пробегаемся по всем найденным приложениям.
for (ApplicationInfo app : apps) { ... }

Остается просто получить человеческое имя приложения. То есть: "YouTube", "WhatsApp"
String appName = pm.getApplicationLabel(app).toString();
и получить уникальное имя пакета - например

  • com.google.android.youtube
  • com.whatsapp
com.имя - формат имени пакетов в Android для установленных приложений

Тут по факту всё, Вот полный код для этого:
Java:
PackageManager pm = getPackageManager();

List<ApplicationInfo> apps = pm.getInstalledApplications(PackageManager.GET_META_DATA);

for (ApplicationInfo app : apps) {
    String appName = pm.getApplicationLabel(app).toString();
    String packageName = app.packageName;
}

Но тут нету никакого вывода, можно добавить например вывод в логи или то что вам нужно
Java:
Log.d("AppList", appName + " - " + packageName);


Список контактов

Как по мне то самое то для офисников. Так-как с помощью этого можно узнавать номера друзей или родственников жертвы, короче говоря работать по всем фронтам.
И к сожалению или к счастью получить их как и всё выше не составляет особой проблемы. Тут тоже надо просто получить одно разрешение: READ_CONTACTS
В манифест:

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

Далее делаем его запрос и с помощью ContentResolver, который позволяет читать данные из системных источников запрашиваем CONTENT_URI где Android хранит телефоны контактов. Для с помощью Cursor перебираем записи. И остаётся только извлечь параметры, например: DISPLAY_NAME и NUMBER.

Код:
Java:
public void getContacts(Context context) {
    if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.READ_CONTACTS}, 1);
        return;
    }

    ContentResolver cr = context.getContentResolver();
    Cursor cursor = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
            null, null, null, null);

    if (cursor != null) {
        while (cursor.moveToNext()) {
            String name = cursor.getString(
                cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
            String number = cursor.getString(
                cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER));
            
            Log.d("Contact", name + ": " + number);
        }
        cursor.close();
    }
}

Для вывода я просто добавил вывод в логи с помощью Log.d(

Log.d("Contact", name + ": " + number);

И ещё для работы важно учесть что:
  • Не все контакты могут содержать номера телефонов.
  • Контактов может быть много, поэтому всегда закрывайте Cursor
журнал вызовов
И завиральной часть в этой статье я бы хотел сделать журнал вызовов. Прям какое-то конкретное применение мне придумать сложно но думаю для конкретное спецификации подойдёт отлично.

Для доступа к журналу вызовов необходимо указать разрешение в AndroidManifest.xml:

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

и конечно-же запросить его в рантайме,

После чего используя ContentResolver для доступа к CallLog.Calls.CONTENT_URI перебираем записи журнала вызовов и от туда можно извлечь:

  • имя - если оно было сохранено
  • номер телефона
  • дату звонка
  • тип - входящий/исходящий
  • длительность звонка
Пример кода:
Java:
public void getCallLogs(Context context) {
    if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.READ_CALL_LOG}, 100);
        return;
    }

    ContentResolver cr = context.getContentResolver();
    Cursor cursor = cr.query(CallLog.Calls.CONTENT_URI, null, null, null, CallLog.Calls.DATE + " DESC");

    if (cursor != null) {
        while (cursor.moveToNext()) {
            String number = cursor.getString(cursor.getColumnIndexOrThrow(CallLog.Calls.NUMBER));
            String name = cursor.getString(cursor.getColumnIndexOrThrow(CallLog.Calls.CACHED_NAME));
            long dateMillis = cursor.getLong(cursor.getColumnIndexOrThrow(CallLog.Calls.DATE));
            int type = cursor.getInt(cursor.getColumnIndexOrThrow(CallLog.Calls.TYPE));
            int duration = cursor.getInt(cursor.getColumnIndexOrThrow(CallLog.Calls.DURATION));

            String callType = "";
            switch (type) {
                case CallLog.Calls.INCOMING_TYPE:
                    callType = "Входящий";
                    break;
                case CallLog.Calls.OUTGOING_TYPE:
                    callType = "Исходящий";
                    break;
                case CallLog.Calls.MISSED_TYPE:
                    callType = "Пропущенный";
                    break;
                case CallLog.Calls.REJECTED_TYPE:
                    callType = "Отклонённый";
                    break;
                default:
                    callType = "Неизвестный";
                    break;
            }

            String date = DateFormat.format("dd.MM.yyyy HH:mm", new Date(dateMillis)).toString();

            Log.d("CallLog", "Имя: " + (name != null ? name : "Неизвестно") +
                    ", Номер: " + number +
                    ", Тип: " + callType +
                    ", Дата: " + date +
                    ", Длительность: " + duration + " сек");
        }
        cursor.close();
    }
}
В данном примере я перебираю тип звонка чтоб удобно вывести текстом и далее вывожу всё просто в логи ну или вы можете поменять на то как вам удобно.

На этом всё, надеюсь был полезен. если про что-то не рассказал пишите в кометы может сделаю 2ю часть.
Всем хорошего времени суток и пока!
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Почему на сервере базу ip не деражть? Как по мне это лишнее
Если делать через сервак то да. Просто я часто через тг бота делал и это было необходимо
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Если делать через сервак то да. Просто я часто через тг бота делал и это было необходимо
через тг бота спиздят твоего бота и будут межать не лучшее решение, научись сервера делать
 
та я умею, просто со старых версию оставался тг бот и мне было в падлу переписывать. Сейчас я кнч не юзаю тг бота
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх