• Познакомьтесь с пентестом веб-приложений на практике в нашем новом бесплатном курсе

    «Анализ защищенности веб-приложений»

    🔥 Записаться бесплатно!

  • CTF с учебными материалами Codeby Games

    Обучение кибербезопасности в игровой форме. Более 200 заданий по Active Directory, OSINT, PWN, Веб, Стеганографии, Реверс-инжинирингу, Форензике и Криптографии. Школа CTF с бесплатными курсами по всем категориям.

Гостевая статья Способы распаковать мобильное вредоносное ПО

В этой статье кратко описываются методы распаковки мобильных вредоносных программ. Он будет сосредоточен на Anubis, так как это последнее популярное вредоносное ПО уже почти год. Актеры используют приложения-капельницы в качестве основного метода распространения. Дропперы находят свои пути в магазин Google Play под общими именами, заражая устройства Anubis. Пример такой капельницы можно найти в ссылках. Прошлой осенью в Google Play было как минимум сорок случаев, нацеленных на турецких пользователей. может быть полезен для обзора таких кампаний. Вредоносные программы Anubis уже детально проанализированы коллегами из отрасли. Поэтому читателям следует посчитать более ценным иметь статью, посвященную механизмам упаковщиков Anubis.

Образец, использованный в этой статье, доступен в разделе ссылок. Я настоятельно рекомендую скачать образец и следовать статье. Я буду делить этот пост на три раздела.
    • динамично
    • Статически
Упаковщики в экосистеме Android
Мобильные вредоносные программы также используют упаковщики, чтобы скрыть свою вредоносную нагрузку от исследователей и антивирусных программ. Это включает отражение, запутывание, выравнивание потока кода и мусорные коды, чтобы сделать процесс распаковки незаметным. Все упомянутые механизмы используются пакером Anubis и поэтому будут рассмотрены в этой статье.

Загрузка классов во время выполнения

Приложения Android должны определить используемые ими сервисы, получатели, классы активности в файле AndroidManifest, чтобы использовать их. В примерах Anubis ясно, что есть много классов, не определенных в файле манифеста, которые просто присутствуют в исходном коде.
mani.png

Это означает, что файл с неопределенными классами должен быть загружен в приложение во время выполнения. Существует два основных способа загрузки во время выполнения в Android:

Из файла:
  • dalvik.system.DexFile.loadDex устарела после API 26
  • dalvik.system.DexClassLoader
  • dalvik.system.PathClassLoader
Из памяти:
  • dalvik.system.InMemoryDexClassLoader (не распространен среди вредоносных программ)
Загрузка из файла требует наличия файла dex / jar в файловой системе. Anubis распаковывает файл с зашифрованными данными и затем удаляет расшифрованную версию. Затем вредоносная программа продолжает загружать дешифрованный код в приложение. После загрузки с DexClassLoader вредоносная программа удаляет расшифрованный файл dex. Отслеживание dexClassLoader должно прояснить процедуру загрузки. Поскольку dexClassLoader является классом dalvik.system, пакет «dalvik.system.dexClassLoader» должен быть в коде, но его нигде нет.



Рефлексия
Еще один полезный метод борьбы с вредоносными программами - рефлексия. Отражение является важной концепцией в Java, которая позволяет вам вызывать методы / классы, не зная о них во время компиляции. Есть несколько классов / методов для размышления.
  • java.lang.Class.forName
  • java.lang.ClassLoader.loadClass
  • java.lang.reflect.Method
  • java.lang.Class.getMethods
Пример использования forName
cObj = Class.forName("dalvik.system.dexClassLoader");
Переменная cObj содержит объект класса dexClassLoader. Это позволяет программе вызывать методы любого заданного класса. Проблема состоит в том, чтобы найти, где выполняются вызовы функций для методов отражения.

Ловля пакеров с Фрида
- это динамический инструментарий инструментария, поддерживаемый почти каждой операционной системой. Frida позволяет внедрить фрагмент кода для управления целевой программой, а также для отслеживания вызовов программы. В этом случае он будет использоваться для отслеживания того, какие вызовы отражения сделаны, тем самым анализируя потоки. Когда выполняются ранее упомянутые вызовы функций, будет вызван console.log дополнительно. Но перед этим давайте кратко рассмотрим, как настроить Frida на эмуляторе Android.

Загрузите frida-сервер, подходящий для вашего эмулятора, по
адресу : (например, Genymotion использует архитектуру x86.)
Https://github.com/frida/frida/releases .
Код:
adb push frida-сервер / данные / локальный / tmp
adb shell
cd / data / local / tmp
chmod + x фрида-сервер
./frida-server &
Инструменты Frida должны быть установлены на хост-машине, запустив
pip install frida-tools

После установки мы можем написать скрипт для подключения наших целевых методов. Мы начнем с определения переменных для классов наших методов.
JavaScript:
var classDef = Java.use('java.lang.Class');
var classLoaderDef = Java.use('java.lang.ClassLoader');
var loadClass = classLoaderDef.loadClass.overload('java.lang.String', 'boolean');
var forName = classDef.forName.overload('java.lang.String', 'boolean', 'java.lang.ClassLoader');
var reflect = Java.use('java.lang.reflect.Method')
var member = Java.use('java.lang.reflect.Member')
var dalvik = Java.use("dalvik.system.DexFile")
var dalvik2 = Java.use("dalvik.system.DexClassLoader")
var dalvik3 = Java.use("dalvik.system.PathClassLoader")
//var dalvik4 = Java.use("dalvik.system.InMemoryDexClassLoader")
var f = Java.use("java.io.File")
var url = Java.use("java.net.URL")
var obj = Java.use("java.lang.Object")
var fo = Java.use("java.io.FileOutputStream")
Мы будем использовать этот фрагмент кода, чтобы изменить реализацию метода.
Код:
class.targetmethod.implementation = function(){
    console.log("[+] targetmethod catched !")
    stackTrace()
    return this.targetmethod()
}
console.log("[+] {x} function catched !") позволит нам увидеть, если функция вызывается. Если функция принимает какие-либо параметры, например строку, их регистрация может оказаться полезной во время анализа. Затем мы можем получить больше информации о потоке, в котором мы находимся. Фрида может вызывать любую функцию Android, включая getStackTrace(). Но это требует ссылки на текущий объект потока. Давайте начнем с получения экземпляра класса потока:
Код:
var ThreadDef = Java.use('java.lang.Thread');
var ThreadObj = ThreadDef.$new();
ThreadObj содержит экземпляр класса Thread и currentThread()может использоваться для получения потока в соответствии с .
Теперь мы можем использовать, getStackTrace() а также перебирать stackElements для печати стека вызовов.
JavaScript:
   function stackTrace() {
        console.log("------------START STACK---------------")
        var stack = ThreadObj.currentThread().getStackTrace();
        for (var i = 0; i < stack.length; i++) {
            console.log(i + " => " + stack[i].toString());
        }
        console.log("------------END STACK---------------");
    }
Печать стека вызовов помогает идентифицировать график вызовов отражений и механизмы распаковки. Например, dexClassLoader мог быть создан с отражением. Но когда frida подключается к dexClassLoader и печатает стек вызовов, мы можем увидеть функции до вызова dexClassLoader. Процедуры распаковки вызываются в самом начале приложения. Поэтому фрида должна быть прикреплена как можно скорее, чтобы успеть распаковать процесс. К счастью, опция -f в frida позволяет frida порождать само целевое приложение. Фрида принимает скрипты с параметром -l.
frida -U -f appname -l dereflect.js
Затем Фрида ждет ввода от пользователя, чтобы продолжить. %resume возобновит процесс. Полный скрипт доступен в моем репозитории github.
eybisi/nwaystounpackmobilemalware

ppp_1.png

Вывод без stackTrace ()

ppp_2.png

С stackTrace ()
Вуаля .
Вы можете увидеть функции, вызываемые перед методом записи. После отслеживания этих интервальных функций вы можете видеть RNlkfTEUXи lqfRafMrGewвызываться прямо перед ними. И оказывается, что они являются очень важными функциями, используемыми для расшифровки зашифрованного файла, о котором мы еще поговорим позже.

Как победить пакеров
Мы можем разделить методы распаковки на два раздела. Оба пути ведут к расшифрованному файлу.

Динамически
  • Подключив:
    • Перехватить file.delete (уровень Java)
    • Перехватить связь с системным вызовом (системный уровень)
  • Из памяти:
    • Дамп памяти с Gameguardian
    • Дамп памяти с помощью пользовательских инструментов
Статически:
  • Руки на ручную распаковку
Динамически:
перехват методов - самый простой способ.

Перехватывая: Уровень Java
Когда я впервые столкнулся с Anubis и понял, что он сбрасывает файл, моим первым решением было подключение к функции file.delete.
JavaScript:
Java.perform(function() {
   var f = Java.use("java.io.File")
   f.delete.implementation = function(a){
       s = this.getAbsolutePath()
       if(s.includes("jar")){
          console.log("[+] Delete catched =>" +this.getAbsolutePath())
       }
       return true
   }
})
Этот фрагмент кода всегда возвращает true в функцию file.delete. После перехвата мы можем вытащить сброшены jar файл . ✔
del.png

В дополнение к этому мы можем автоматизировать нашу работу с привязками python к frida и просмотреть папку, в которой находятся наши целевые файлы. Обычно с этих серверов C&C генерируются тысячи apks. Поскольку каждый из них может иметь разные IP-адреса, инструмент может облегчить нашу жизнь.

Подсказка: системный уровень.
Но что, если вредоносная программа использует собственный код для удаления файлов? Мы не всегда можем подключиться на уровне Java. Нам нужно глубже. Какой системный вызов отвечает за удаление файла из файловой системы и в libc?
155136004439210407.png

Функция Unlink принимает один параметр, указатель на имя файла. Мы можем перехватить связь с помощью findExportByName. Код взят из но я немного подправил, поэтому удаленный файл будет напечатан.
JavaScript:
var unlinkPtr = Module.findExportByName(null, 'unlink');
Interceptor.replace(unlinkPtr, new NativeCallback( function (a){
    console.log("[+] Unlink : " + Memory.readUtf8String(ptr(a)))
    }, 'int', ['pointer']));
Давайте запустим скрипт.
u.png

Мы перехватили вызов unlink, поскольку наш скрипт просто заменил код исходной функции на console.log (), файл не будет удален из файловой системы. ✔

Из памяти:
даже когда файл удален из файловой системы, поскольку файл был загружен в процесс, мы можем получить следы удаленного файла из памяти этого процесса. Поскольку Android наследуется от Linux, мы можем использовать папку /proc/pid для предоставления нам информации об областях памяти указанного процесса. Давайте посмотрим на нашу цель с cat /proc/pid/maps | grep dex фильтрацией Dex.
4-1024x113.png

Мы нашли следы декс-файлов. Теперь нам нужно сбросить эти разделы.

Дамп памяти с Gameguardian:

Первый способ - «обман». Существует инструмент GameGuardian, который используется для взлома игр. С GameGuardian вы можете делать много интересного, но пока мы будем использовать только механизм дампа.

gg1.png

gg2.png

gg3.png


Давайте начнем с установки и запуска APK. Затем запустите GameGuardian и выберите название приложения слева вверху. Выберите правую верхнюю кнопку и ту, что под ней. Теперь вы можете увидеть опцию дампа памяти в меню. Введите шестнадцатеричные коды регионов или выберите регионы, нажимая кнопки со стрелками и нажимая «Сохранить». Ура!
Мы можем вытащить выгруженные области с помощью:
adb pull /storage/emulated/0/packer .✔
Тогда вы увидите 2 файла в папке упаковщика.
com.eqrxhpdv.cbunlkwsqtz-dfb5a000-e0080000.bin com.eqrxhpdv.cbunlkwsqtz-maps.txt

При проверке с помощью команды file он обнаруживает наш dex-файл как файл данных.
Мы должны исправить это, удалив части, не принадлежащие нашему файлу.

Дамп памяти с помощью пользовательских инструментов:
благодаря мы можем областей памяти целевого приложения с помощью C-программы.
https://github.com/CyberSaxosTiGER/androidDump
Вот как сделать дамп региона с помощью androidDump.
Код:
adb push androidDump /data/local/tmp
adb shell
cd /data/local/tmp
chmod +x androidDump
./androidDump appname
Это сбрасывает 3 капли данных. ✔

Но после сброса file команда все равно не дает нам правильный тип 🙁 Оказывается, мы должны немного изменить файл. Чтобы найти волшебный байт dex, я написал этот скрипт.
Код:
import binascii
import sys
filename = sys.argv[1]
with open(filename, 'rb') as f:
    content = f.read()
h = binascii.hexlify(content).split(b'6465780a')
h.pop(0)
h = b'6465780a' + b''.join(h)
dex = open(sys.argv[1][:-4]+".dex","wb")
dex.write(binascii.a2b_hex(h))
dex.close()
eybisi/nwaystounpackmobilemalware
После запуска нашего сценария для файла мы открываем его.
tadaa_1.png

yes.gif

Мы нашли наши потерянные классы 🙂

Статически:
вот сообщение в блоге, объясняющее процесс распаковки с другой точки зрения.
Я нашел ключ rc4 с помощью stackTrace. Но очевидно, что поиск ^значения - очень эффективный способ найти подпрограммы RC4 для Anubis.
Чтобы легко найти ключ rc4 в JADX, вот быстрый совет:
  • search “% length”
  • щелкните правой кнопкой мыши метод, который вы используете, нажмите найти использование
  • bArr2 будет использоваться как ключ rc4 для расшифровки.
Вот ключ расшифровки нашего образца как bArr2. Это выглядит знакомо?
barr_1.png

С bArr2 мы можем расшифровать зашифрованный файл из папки изображений APK. Вот фрагмент для расшифровки файла с помощью bArr2. Скрипт принимает 2 параметра, bArr2 и зашифрованный файл. Для нашего случая это средний урожай. APK-файлы могут быть просто разархивированы для доступа к его содержимому. ✔

eybisi/nwaystounpackmobilemalware
dec.png

После расшифровки и распаковки мы получаем наш dex.
target_1.png

После извлечения конфигурации, есть еще один шаг, чтобы получить адрес сервера C & C. Вредоносное ПО получает страницу с адресом телеграммы и заменяет китайские символы буквами ASCII. Затем он обрабатывает строку base64. После декодирования base64 он использует serviceдля дешифрования данные, зашифрованные по схеме rc4. Вот фрагмент кода для расшифровки китайских символов на адреса C & C.

eybisi/nwaystounpackmobilemalware
solve.png

Мне удалось расшифровать полезную нагрузку Anubis с помощью Androguard без запуска APK в эмуляторе! После сброса файла dex мой скрипт найдет класс config, печатающий c2 и ключ шифрования. Класс конфигурации находится в одном из классов a,b or c или ooooooooooooo{0,2}o в более новых версиях.
Проверив количество ключевых слов «this» в исходном коде класса, мне удалось расшифровать все версии anubis (lazy: P). Вот вывод моего скрипта для получения c2 и ключа из образца Anubis. eybisi/nwaystounpackmobilemalware
dump.png

Вывод
Существует много способов распаковать мобильное вредоносное ПО и отследить механизмы упаковки. Мы могли бы увидеть dalvik.system.InMemoryDexClassLoader в будущем. Если это используется, ловушки удаления не смогут отловить пропущенные файлы, потому что все будет сделано в памяти 🙂 Но дамп памяти будет ловить эти методы. Знание разных способов всегда помогает.

Источник:
 

Вложения

  • mzw9z.gif
    mzw9z.gif
    337,3 КБ · Просмотры: 199
Последнее редактирование:
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!