Подписывайтесь на наш Telegram и не пропускайте важные новости! Перейти

Вопрос Реверс Unity Android — как правильно патчить массивы в IL2CPP (ARMv7)

Sloppy
Начинающий
Начинающий
Статус
Оффлайн
Регистрация
13 Фев 2026
Сообщения
538
Реакции
14
Здорово, реверсеры. Залетел тут технический вопрос по мобильному Unity и препарированию libil2cpp.so на ARMv7. Ситуация классическая: есть функция, возвращающая массив байт (byte[]), и нужно подменить этот возврат, но только в одном конкретном месте (func2), не трогая оригинал во всем остальном коде.

Суть идеи была в том, чтобы просто впихнуть свои байты в .data или .rodata и подменить вызов BL func1 на загрузку адреса через LDR R0, [R1].

Почему это не сработает в лоб?
В Unity (через призму IL2CPP) массивы C# — это не просто «голый» кусок памяти с данными, как в C++. Это полноценные объекты. Если ты просто подставишь указатель на свой DCB массив в R0, игра моментально отлетит в краш.

  1. Структура Il2CppArray всегда начинается с заголовка (Il2CppObject), где лежат метаданные (ссылки на класс и т.д.).
  2. Далее идет поле max_length (иногда еще Il2CppArrayBounds), которое хранит размер массива.
  3. Только после этих полей в памяти начинаются реальные байты данных.

Когда func2 получит твой «голый» указатель, она попытается прочитать Length или обратиться к элементу. Проц полезет по смещению искать метаданные объекта, увидит там твои мусорные байты вместо валидных указателей и выдаст Access Violation.

В рантайме это выглядит примерно так:
Код:
Expand Collapse Copy
typedef struct {
    Il2CppObject obj; 
    Il2CppArrayBounds *bounds;
    uint32_t max_length;
    uint8_t vector[VARIABLE_SIZE];
} Il2CppArray;
Чтобы твой патч сработал, R0 должен указывать на начало такой структуры, а не на начало данных.

Как это разрулить?
Варианта два. Первый — патчить не возврат функции, а саму логику в func2, чтобы она брала данные из твоего адреса напрямую, минуя методы массива. Второй (более цивильный) — использовать хуки. Через какой-нибудь Dobby или KittyMemory можно вызвать оригинальную il2cpp_array_new, которая создаст честный массив в куче, заполнить его своими данными и вернуть в R0.

Если же нужно именно статикой в либе — придется либо искать в памяти уже готовый массив нужной длины, либо имитировать всю структуру объекта в .data, что на мобилках может быть нестабильно из-за динамических адресов классов.

Кто пробовал собирать фейковые Il2Cpp-объекты прямо в секции данных, насколько это вообще жизнеспособно без инициализации метаданных в рантайме?
 
Назад
Сверху Снизу