Изучение приложений на платформе iOS - это достаточно сложная задача, которая разрешима, если использовать правильный набор инструментов. Основа такого набора - устройство с установленным jailbreak и инструмент frida Frida.

Далее будет рассказано о нескольких способах детектирования инструмента frida из приложения. Заметим, что статья не преследует цели описания всех возможных подходов обнаружения frida, поскольку любая защита может быть снята: всё упирается во время, которое необходимо для анализа.

Теория

Для успешного детектирования любого вмешательства в работу приложения необходимо включить в алгоритм его работы несколько логик:

  1. Детектирование jailbreak

  2. Детектирование frida

Каждый из этапов включает в себя знание особенностей работы операционной системы iOS и инструмента, который необходимо продетектировать. Начнем с обнаружения инструмента. Обратимся к документации frida, здесь описываются несколько методов, за счет которых работает инструмент. Всего их 3, но самых популярных 2:

Injected - способ, при котором в код оригинального приложения добавляется специальная расшариваемая библиотека, которая может работать в том же процессе, что и приложение. Главная особенность такого подхода заключается в том, что приложение уже может работать на момент добавления библиотеки. После добавления с помощью командного интерфейса можно искать данные и функции приложения, а так же производить их модификации. По сути, это самый гибкий функционал, который и делает этот инструмент настолько мощным. Взаимодействие с библиотекой производится через использование сетевого соединения, т. е. через tcp сокет. Стандартная настройка, которая поставляется в инструменте - localhost:27042.

Embdedded - способ, при котором расшириваемая библиотека добавляется в переупакованное приложение. При этом изменяются самые первые команды алгоритма, чтобы библиотека могла быть загружена в память стартуемого приложения. Командный интерфейс так же может быть доступен через tcp сокет localhost:27042, точно так же можно выполнять команды автономно.

Следовательно, чтобы детектировать присутствие инструмента необходимо:

  • Проверить список модулей приложения

  • Зарезервировать сокет tcp/localhost:27042

  • Проверить исполняемый файл приложения перед загрузкой в оперативную память

Перейдем к детектированию jailbreak. Эта характеристика устройств достаточно давно детектируется с помощью свободно распространяемого ПО. Например, этот проект. Стоит только учитывать, что подобное детектирование известно большому количеству исследователей, поэтому его может быть недостаточно. Чтобы дополнить детект, стоит использовать собственную "фишку", например, детектирование прав доступа к корневой директории файловой системы или создание симлинки для директории "/Applications/" и записи туда тестового файла.

Практика

Так как мы имеем дело с инструментами, которые будут анализировать приложение на этапе выполнения алгоритма, то стоит добавить несколько "подарков". Приложение сложнее исследовать, если будут применяться методы антиотладки:

void testKill() {
  const int pid = getpid(); 
  int ret = kill(pid, 0);
}

Дополнительно можно проверить, есть ли какой-то отладчик, который мог зафризить приложение для инъекции или модификации:

inline bool detectPtrace() {
  int32_t opt[4] = {
    CTL_KERN,
    KERN_PROC,
    KERN_PROC_PID,
    getpid(),
  };
  kinfo_proc info;
  sysctl(opt, 4, &info, sizeof(kinfo_proc), nullptr, 0);
  return info.kp_proc.p_flag & P_TRACED;
}

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

FastSocket *client = [[FastSocket alloc] initWithHost:@"localhost" andPort:@"27042"];
[client connect];

Детектирование количества модулей приложения, которые загружены в оперативную память:

bool fridaInjectCheck()
{
    //количество всех модулей в памяти
    uint32_t count = _dyld_image_count();
    for(uint32_t i = 0; i < count; i++)
    {
        //имя модуля, вуключая его полный путь
        const char *dyld = _dyld_get_image_name(i);
        if(!strstr(dyld, "FridaGadget")) { // <<= сюда можно указать имя файла, который 
            continue;
        }
        else {
            return true;
        }
    }
    return false;
}

И детектирование, которое может помочь защитить приложение - проверка целостности исполняемого файла приложения. Для этой проверки лучше использовать контрольную сумму от всего файла, но какую выбрать, стоит решить самостоятельно.

Выводы

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


Статья подготовлена в преддверии старта специализации "iOS Developer".

Также приглашаем всех желающих на бесплатный вебинар по теме: Новые инструменты Swift, для работы с асинхронностью Async/Away/Actor

Комментарии (2)


  1. kunitsyn
    09.08.2021 18:29
    +2

    И детектирование, которое может помочь защитить приложение - проверка целостности исполняемого файла приложения. Для этой проверки лучше использовать контрольную сумму от всего файла

    Осталось только понять, как внедрить контрольную сумму файла в сам файл :)


    1. spiceginger
      10.08.2021 16:59

      +1