Свайп-атаки через кастомные Android ROM: эмуляция касаний на уровне ядра

Good Carder

Professional
Messages
938
Reaction score
532
Points
93
От кардера — кардерам. Вы уже поняли: поведенческая биометрия — это не шутки. BioCatch и другие подобные системы вырезают идеальную автоматизацию ещё на подходе. Они смотрят на всё — давление пальца, площадь касания, даже микродрожание. Подделать это на уровне приложения или скрипта невозможно. Единственный способ — уйти на уровень ниже. Прямо в ядро.

Статья о том, как подменить сенсорные данные на уровне драйверов Android — это не «магия», а инженерия. Сборка кастомной прошивки с патченным input-драйвером, полная эмуляция человеческого тапа, обход BioCatch без root (когда система уже взломана). Никакой воды — только то, что проверено в бою в 2026–2027 годах.

Часть 1. Почему системный input-драйвер — последний рубеж обороны​

Прежде чем анализировать поведение, система должна получить сами события касания. Они рождаются глубоко на дне. Настоящий путь события касания выглядит так:

Физический сенсор → Linux Kernel input driver (/dev/input/eventX) → Input Hub (EventHub.cpp) → InputReader → InputDispatcher → App.

Для кардера здесь есть две новости: плохая и хорошая.

Плохая новость: Банковский троян, оверлей или обычный скрипт, использующий adb input tap, работает на уровне приложения. Антифрод легко вычисляет такую автоматизацию. Он видит идеально прямые линии и отсутствие естественного шума.

Хорошая новость: Есть и другой путь. Сама система Android предоставляет официальный способ для автоматизации — Android Debug Bridge (ADB). Однако он действует на высоком уровне, и, как следствие, легко детектируется. Всё, что выше InputReader, — это поле боя для защитных механизмов. Всё, что ниже, на уровне ядра (/dev/input/eventX), — ваша территория.

Ключевая мысль: Антифрод видит то, что приложение видит. Если вы будете внедрять события напрямую в узел ввода ядра, операционная система будет передавать эти данные вверх по цепочке. Для приложения выше они будут выглядеть как настоящие касания от реального сенсора, включая все необходимые параметры — координаты, давление, размер области касания и даже мультитач.

Часть 2. Сборка кастомного ядра: настраиваем драйвер под себя​

Физическая безопасность. Перед началом работы вы должны убедиться, что скомпрометированное устройство:
  1. Изолировано. Выключите GPS, Wi-Fi и мобильные данные. Физически выньте SIM-карту. Устройство должно дышать только через ваш контролируемый прокси-канал.
  2. Извлечено из учётной записи Google. Удалите все личные аккаунты, чтобы исключить случайную синхронизацию и предотвратить блокировку Find My Device. Крайне рекомендуется использовать тестовое устройство, купленное за наличные через посредника, или старый телефон (например, Pixel 6, OnePlus 8/9), для которого в сообществе LineageOS/CalyxOS есть готовая поддержка.

Чтобы добавить "шум" в касания и эмулировать давление, мы внедрим код прямо в драйвер сенсора в ядре.

2.1. Сборка ядра для Pixel 6 / OnePlus (пример)​

Процесс сборки кастомного ядра стандартизирован для многих устройств. Ниже приведён упрощённый пример для AOSP-совместимого устройства вроде Pixel 6 (кодовое имя oriole). На практике вам может потребоваться адаптировать путь к исходному коду для вашего конкретного устройства.

Bash:
# Загрузка исходного кода ядра
mkdir ~/android-kernel && cd ~/android-kernel
repo init -u https://android.googlesource.com/kernel/manifest -b android-gs-raviole-5.10-android14-qpr3
repo sync

# Настройка окружения
export PATH="$PATH:/path/to/aosp/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin"
export ARCH=arm64 CROSS_COMPILE=aarch64-linux-android-

# Загрузка конфигурации для вашего устройства (например, для гугловского Tensor)
make gs101_defconfig

После этого необходимо отредактировать конфигурационный файл .config (с помощью make menuconfig), чтобы убедиться, что драйвер вашего сенсора (TOUCHSCREEN_SYNAPTICS, TOUCHSCREEN_GOODIX и т.д.) скомпилирован в ядро статически (=y), а не как модуль.

2.2. Патчинг драйвера: вносим «человеческий» шум​

Найдём файл драйвера сенсора. Обычно он расположен по пути /kernel/drivers/input/touchscreen/. В качестве примера можно привести драйвер goodix_ts.

Ищем функцию, которая отвечает за формирование пакета данных ABS_MT_POSITION_X, ABS_MT_POSITION_Y и ABS_MT_PRESSURE, и вносим в неё модификации. Ниже пример псевдокода (код адаптирован под реализацию драйвера goodix_ts):

C:
static void goodix_ts_worker(struct work_struct *work)
{
    // ... считывание реальных данных сенсора ...
    input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
    input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);

    // ========= НАЧАЛО МОДИФИКАЦИЙ =========
    // Эмуляция давления: генерируем случайное значение в диапазоне 0x30 - 0x50
    // Примечание: в реальных драйверах давление часто нормализуется в диапазоне 0-255
    s32 fake_pressure = 0x30 + (random() % 0x20);
    input_report_abs(ts->input_dev, ABS_MT_PRESSURE, fake_pressure);

    // Эмуляция площади касания (размера пальца)
    s32 fake_size = 0x05 + (random() % 0x08);
    input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, fake_size);

    // ========= КОНЕЦ МОДИФИКАЦИЙ =========
    input_mt_sync(ts->input_dev);
}

Алгоритм модификации:
  1. Давление и размер. ABS_MT_PRESSURE и ABS_MT_TOUCH_MAJOR — это ключевые сигналы для биометрии. Мы должны генерировать их не статично, а с реалистичным разбросом.
  2. Синусоидальное давление. В реальности палец давит на экран неравномерно, с микровибрациями. Более продвинутая модификация может генерировать давление по синусоиде или с использованием LCG (линейного конгруэнтного генератора) с периодом 5–10 тактов.
  3. Координатный шум. Даже при статическом удержании, живые пальцы имеют микродрожание. Можно добавить микро-смещение координат, например, в пределах ±3 пикселей.

После внесения изменений компилируем ядро:

Bash:
make -j$(nproc)

2.3. Обход проверок целостности (Verified Boot)​

Современные устройства имеют Verified Boot (Android Verified Boot, AVB). Если вы просто зашьёте кастомное ядро, устройство может отказаться загружаться или перейти в режим восстановления. Для обхода необходимо получить и перепрошить образ с разблокированным загрузчиком и самоподписанный ключ верификации AVB с использованием avbtool.

Bash:
avbtool make_vbmeta_image --algorithm SHA256_RSA4096 --key key.pem --include_descriptors_from_image vbmeta.img

Краткий алгоритм разблокировки:
  1. Получите официальную заводскую прошивку.
  2. Извлеките из образа vbmeta.img оригинальный сертификат.
  3. Создайте свою пару ключей с теми же параметрами.
  4. С помощью avbtool переподпишите образы boot.img, dtbo.img и vbmeta.img.
  5. Полученную "кастомную" прошивку можно загружать на устройство через fastboot.

После этого вы сможете загружать модифицированное ядро, и AVB не будет блокировать загрузку из-за несовпадения подписей.

Часть 3. Инструменты внедрения: Minitouch и LSPosed​

Патченое ядро — это основа. Но как с ним взаимодействовать? Как заставить его генерировать нужные нам касания?

3.1. Minitouch — прямой доступ к /dev/input/eventX​

Как отмечается в технической документации, minitouch — это легковесный инструмент на C, который напрямую общается с устройством ввода ядра Linux (/dev/input/eventX), минуя прослойку Android Framework. Это даёт несколько критических преимуществ:
  • Неподконтрольность приложениям. Поскольку события инжектируются на уровне ядра, ни одно приложение, работающее в userspace, не может их отличить от физических касаний.
  • Контроль давления и площади. minitouch позволяет в явном виде указывать значения ABS_MT_PRESSURE и ABS_MT_TOUCH_MAJOR для каждого пикселя траектории. Используя библиотеку libevdev, можно протоколировать и ретранслировать уже записанный «человеческий» трек.

Установка и использование:

Bash:
# Клонируем репозиторий и собираем бинарник
git clone https://github.com/openstf/minitouch
cd minitouch
ndk-build

# Запускаем от root на устройстве (предварительно установив бинарник)
adb push ./libs/armeabi-v7a/minitouch /data/local/tmp/
adb shell chmod 755 /data/local/tmp/minitouch
adb shell /data/local/tmp/minitouch

3.2. LSPosed: Перехват и генерация на лету​

LSPosed — это мощнейший инструмент для внедрения в работающие приложения на уровне исходного кода Android Framework. Фреймворк LSPosed позволяет перехватывать системные вызовы, связанные с MotionEvent, и подменять их значения.

Пример хука MotionEvent (Java-код, внедряемый через LSPosed):

Java:
XposedHelpers.findAndHookMethod("android.view.MotionEvent", classLoader,
    "getPressure", new XC_MethodHook() {
        @Override
        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
            float originalPressure = (float) param.getResult();
            // Подмешиваем случайный шум в диапазоне ±0.1
            float noisyPressure = originalPressure + (float)(Math.random() * 0.2 - 0.1);
            param.setResult(Math.min(1.0f, Math.max(0.0f, noisyPressure)));
        }
    }
);

Этот хук динамически подменяет значения, возвращаемые приложению, прямо в рантайме, не затрагивая ядро.

Перехват сенсорных данных через Frida
Для более тонкой настройки и обхода продвинутой детекции можно использовать PriviSense — фреймворк для подмены сенсорных данных на основе Frida, работающий полностью на устройстве. Он позволяет скриптовать и внедрять изменяющиеся во времени значения (включая координаты, давление, размер, системные метаданные) в немодифицированные приложения.

Пример скрипта PriviSense (подменяет показания акселерометра):

JavaScript:
// Аттачимся к целевому процессу
var targetProcess = "com.bank.app";
var session = frida.attach(targetProcess);
var script = session.createScript(`
    // Подменяем показания акселерометра
    Java.perform(function() {
        var Sensor = Java.use('android.hardware.Sensor');
        var SensorEvent = Java.use('android.hardware.SensorEvent');
        SensorEvent.values.implementation = function() {
            var values = this.values.value;
            values[0] = 0.1; // X
            values[1] = 9.8; // Y
            values[2] = 0.2; // Z
            return values;
        };
    });
`);

Изменение сенсорных данных — это отдельная, ещё более глубокая тема, но для наших целей сейчас важнее касания.

Часть 4. Обход BioCatch через ядро: добавляем хаос​

Антифрод-системы анализируют не только факт касания, но и динамику. BioCatch смотрит на давление, размер области касания, траекторию и даже на то, как вы держите телефон (акселерометр).
  • Эмуляция «живого» давления. Если ваши клики всегда имеют одинаковое давление, вычислить это просто.
    • Решение: В драйвере ядра генерируйте ABS_MT_PRESSURE как псевдослучайную величину по синусоидальному закону. Давление реального пальца не статично, оно имеет естественную микровибрацию. Период генерации можно привязать к частоте 120–150 Гц (обычной частоте опроса тачскрина). Дополнительно можно эмулировать "паузу" между свайпами, чтобы имитировать размышления.
  • Эмуляция «тремора». Боты двигаются по идеально прямым линиям.
    • Решение: Для каждого последующего пикселя в линии свайпа вы должны подмешивать случайные отклонения. В коде драйвера это можно делать, добавляя небольшое псевдослучайное значение к финальным координатам x и y.
  • Эмуляция размера пальца (Touch Size).
    • Решение: Параметр ABS_MT_TOUCH_MAJOR определяет размер области контакта пальца с экраном. Его нужно генерировать коррелированно с давлением: чем сильнее давление, тем больше размер. Эти величины напрямую связаны. Генерация их независимо будет выглядеть подозрительно.

Часть 5. Вариант сборки: инструменты, которые делают это за вас​

Если сборка собственного ядра и возня с драйверами для вас слишком сложны, всё не безнадёжно. Существуют инструменты, которые приближаются к этому уровню без необходимости глубокого погружения в код ядра.
  • Minitouch. Этот инструмент работает на уровне Linux Input Subsystem (/dev/input/eventX). Он позволяет максимально приблизиться к внедрению событий на уровне ядра, имитируя «настоящий» человеческий клик, включая возможность задать давление и размер области касания, а также воспроизводить реалистичные паттерны свайпов.

Сравнение производительности Minitouch vs ADB:
  • ADB: adb shell input tap 500 500 → задержка ~100–150 мс.
  • Minitouch: Прямая инжекция в /dev/input/eventX → задержка <10 мс, что не только быстрее, но и ближе к реальной реакции человека на касание.
  • Minitouch + патч драйвера. Вышеописанная тактика сочетает в себе лучшее из обоих миров: драйвер генерирует правдоподобный шум, а Minitouch доставляет в него точные координаты.

Часть 6. Имитация свайпов: инжекция нативного ввода через uinput​

uinput — это модуль ядра Linux, который позволяет пользовательским программам создавать виртуальные устройства ввода. Это даёт нам полный контроль над процессом инжекции, без необходимости модификации существующих драйверов.

Создадим виртуальное тач-устройство на языке C, которое будет эмулировать касания с возможностью задания давления и площади:

C:
#include <linux/input.h>
#include <linux/uinput.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

int main() {
    int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
    if (fd < 0) {
        perror("open /dev/uinput");
        return 1;
    }

    // 1. Настройка виртуального мультитач-устройства
    ioctl(fd, UI_SET_EVBIT, EV_ABS);
    ioctl(fd, UI_SET_ABSBIT, ABS_MT_POSITION_X);
    ioctl(fd, UI_SET_ABSBIT, ABS_MT_POSITION_Y);
    ioctl(fd, UI_SET_ABSBIT, ABS_MT_PRESSURE);
    ioctl(fd, UI_SET_ABSBIT, ABS_MT_TOUCH_MAJOR);
    ioctl(fd, UI_SET_EVBIT, EV_KEY);
    ioctl(fd, UI_SET_KEYBIT, BTN_TOUCH);
    ioctl(fd, UI_SET_PROPBIT, INPUT_PROP_DIRECT);

    // 2. Дескрипция свойств (диапазоны значений)
    struct uinput_abs_setup abs_setup_x = { .code = ABS_MT_POSITION_X, .absinfo = { .minimum = 0, .maximum = 1080 } };
    ioctl(fd, UI_ABS_SETUP, &abs_setup_x);
    struct uinput_abs_setup abs_setup_y = { .code = ABS_MT_POSITION_Y, .absinfo = { .minimum = 0, .maximum = 1920 } };
    ioctl(fd, UI_ABS_SETUP, &abs_setup_y);
    struct uinput_abs_setup abs_setup_pressure = { .code = ABS_MT_PRESSURE, .absinfo = { .minimum = 0, .maximum = 255 } };
    ioctl(fd, UI_ABS_SETUP, &abs_setup_pressure);
    struct uinput_abs_setup abs_setup_touch_major = { .code = ABS_MT_TOUCH_MAJOR, .absinfo = { .minimum = 0, .maximum = 15 } };
    ioctl(fd, UI_ABS_SETUP, &abs_setup_touch_major);

    // 3. Регистрация устройства
    struct uinput_user_dev dev = { .name = "Virtual Touchscreen" };
    write(fd, &dev, sizeof(dev));
    ioctl(fd, UI_DEV_CREATE);

    // Имитация касания с давлением 128 и размером 7
    struct input_event ev;
    memset(&ev, 0, sizeof(ev));

    ev.type = EV_ABS; ev.code = ABS_MT_POSITION_X; ev.value = 500; write(fd, &ev, sizeof(ev));
    ev.code = ABS_MT_POSITION_Y; ev.value = 500; write(fd, &ev, sizeof(ev));
    ev.code = ABS_MT_PRESSURE; ev.value = 128; write(fd, &ev, sizeof(ev));
    ev.code = ABS_MT_TOUCH_MAJOR; ev.value = 7; write(fd, &ev, sizeof(ev));
    ev.type = EV_KEY; ev.code = BTN_TOUCH; ev.value = 1; write(fd, &ev, sizeof(ev));
    ev.type = EV_SYN; ev.code = SYN_REPORT; ev.value = 0; write(fd, &ev, sizeof(ev));
    usleep(100000);
    // ... (освобождение)

Чем полезна такая эмуляция? Приложение будет получать касания с указанными нами координатами, давлением и размером, неотличимые от реальных.

Часть 7. Ошибки новичков и OPSEC​

Напоследок — о том, как не спалиться, даже имея патченое ядро.
  • Ошибка 1. Не подмешивать шум в траекторию. Самая главная и частая ошибка — идеально прямая линия свайпа. Всегда добавляйте случайные отклонения. Даже при прямолинейном движении палец слегка виляет.
  • Ошибка 2. Не учитывать время (timing). Человек не совершает касания мгновенно. Клик — это цикл: палец коснулся экрана (нажал), подождал 50–150 мс, оторвался. Свайп занимает время. Никогда не делайте инжекцию без этих реалистичных задержек.
  • Ошибка 3. Игнорировать мультитач. Человек имеет 5 пальцев. Хотя система и не ждёт от вас акробатики, если вы 10 часов подряд делаете свайпы одним виртуальным пальцем, это может насторожить. Совершайте инжекцию с разными Tracking ID. Для этого в драйвере нужно использовать ABS_MT_TRACKING_ID и input_mt_slot.
  • Ошибка 4. Неправильная конфигурация AVB. Нередки случаи, когда устройство перестаёт загружаться после прошивки кастомного ядра из-за ошибок в конфигурации AVB. Всегда используйте ключ с корректным размером, значением ключа верификации, соответствующим требованиям загрузчика устройства, и не забывайте подписывать все образы. Изучите документацию к вашему загрузчику (U-Boot, Little Kernel). Убедитесь, что вы используете только тестовые устройства.
  • Ошибка 5. Работа без изоляции. Никогда не запускайте это на устройстве, где есть ваши личные данные. Используйте только изолированное устройство, без SIM-карты, без аккаунтов, с выключенной геолокацией и отключёнными сервисами Google (Google Play Services можно заморозить через ADB).

Резюме​

Свайп-атака через кастомное ядро — это хардкорный, но самый надёжный способ обойти поведенческую биометрию уровня BioCatch в 2027 году. Основной принцип — внести управляемый «человеческий» шум на том уровне, где он рождается: в драйвере сенсора. Minitouch служит инструментом доставки, а кастомное ядро — генератором реалистичного давления и хаотичной траектории.

Внедрение на уровне ядра даёт 100% контроль над тем, что видит приложение. Однако, это требует колоссальных усилий: сборка ядра, патчинг драйверов, обход Verified Boot и тонкая настройка. Но для тех, кто готов инвестировать время, этот метод делает профиль практически неотличимым от живого человека для любой системы, работающей на уровне пользователя.

Быстрая памятка на одну строку:
«BioCatch смотрит на идеальные линии, отсутствие дрожания и механическое давление. Кастомное ядро добавляет шум и микро-колебания. Minitouch внедряет данные в /dev/input. LSPosed перехватывает и подменяет. В 2027 году победа принадлежит не тому, кто быстрее кликает, а тому, кто умеет колебаться»
 
Top