Начинающий
- Статус
- Оффлайн
- Регистрация
- 31 Окт 2021
- Сообщения
- 141
- Реакции
- 3
Гайд как расшифровать любой файл игры на il2cpp / mono
Наши инструменты - HxD, Ghidra, il2cppinspector, python.
Все делаем по классике - вытягиваем валидную либку с метаданными, прогоняем через дампер и получаем обычное сообщение что метадата неверная (не нужно верить сообщению так как это обычный шифр на ней)
Открываем HxD и вставляем свою метадату, там мы должны увидеть не нули а AF B1 и так далее, если вы такое видите значит идем дальше - если нули то ищем другую метадату.
Открываем гидру и ищем указатель update(или что то может быть похожее)
По указателю мы должны попасть в модульную структуру il2cpp, а именно загрузку всех классов до их определения
данная таблица определяет место и вывод вхождения всех будущих загруженных классов с учетом всех смещений, записываем подробные результаты в txt
Дальше отправляемся в go - to
и мы должны будет с псевдокода update взять валидный fun для глубокого определения их взаимодействия, в моем же случае это FUN_00f6acac
видим такую картину, если вы видите что то похожее то вы на верном пути, это поисковой алгоритм самой либки которая отвечает за хеширование специальных обьектов, функция uVar3 = FUN_00f6adc0(param_2,param_3) отвечает что функция 00f6adc0 отвечает за указатель данного применения хеширования
данный код весь выполняется как хеш-таблица, которая вычисляет индекс uVar9-7 на основе полученных данных.
из всего вышеперечисленного мы можем уверенно сказать что 8 битный long в структуре il2cpp класса является указателем на следующий элемент в списке.
следующая функция FUN_00f66f90
и еще
и еще
puvar32 является указателем il2cpptypedefinition которая так же создается в метадате игры, а вот 0x5c является размером записи
сохраняем данную информацию в голове
далее -
из всего кода можно понять что базовый размер структуры составляет 0x130 байт что подтверждает что данный псевдокод указывает нам на валидную структуру в метадате
так же если вы заметили то puvar32 и 38 часто встречается в псевдокоде из-за чего можно подтвердить что наша метадата перед дампом проверяет все классы
из чего можно сделать следующую структуру нашего анализа
long* image; 0x00: *plVar24 = lVar39;
uint typeDefinitionIndex; 0x04: Из FUN_00f65494: `*(uint *)(plVar1 + 4)`.
uint flags_or_padding_0x08; 0x08: В FUN_00f6acac - здесь был names_hash.
.
const char* name; 0x10: plVar24[2] = (long)puVar29
const char* namespaze; 0x18: plVar24[3] = (long)puVar29; (
long* parent; 0x58: plVar24[0xb] = (long)plVar23;
long* declaringType; 0x50: plVar24[10] = (long)plVar23;
long* element_class; 0x48: plVar24[9] = (long)plVar24;
long* castClass; 0x40: plVar24[8] = (long)plVar24;
// Метаданные //
void* typeMetadataHandle; 0x68: plVar24[0xd] = (long)puVar32;
uint field_count; 0x110: *(uint *)(plVar24 + 0x22) = puVar32[8]; количество полей
uint method_count; 0x114: *(uint *)((long)plVar24 + 0x114) = puVar32[0x16];
зная уже эти базовые параметры можно предположить что загрузка классов в любом случае происходит в этой либке
вспомните что мы разбираем с вами только функцию update, и только с нее мы по отношениям узнали очень много всего полезного, детально разобрались как и кто загружает зашифрованные классы, что в дальнейшем нам очень сильно поможет в расшифровке
конец 1 части
Наши инструменты - HxD, Ghidra, il2cppinspector, python.
Все делаем по классике - вытягиваем валидную либку с метаданными, прогоняем через дампер и получаем обычное сообщение что метадата неверная (не нужно верить сообщению так как это обычный шифр на ней)
Открываем HxD и вставляем свою метадату, там мы должны увидеть не нули а AF B1 и так далее, если вы такое видите значит идем дальше - если нули то ищем другую метадату.
Открываем гидру и ищем указатель update(или что то может быть похожее)
По указателю мы должны попасть в модульную структуру il2cpp, а именно загрузку всех классов до их определения
данная таблица определяет место и вывод вхождения всех будущих загруженных классов с учетом всех смещений, записываем подробные результаты в txt
Дальше отправляемся в go - to
и мы должны будет с псевдокода update взять валидный fun для глубокого определения их взаимодействия, в моем же случае это FUN_00f6acac
видим такую картину, если вы видите что то похожее то вы на верном пути, это поисковой алгоритм самой либки которая отвечает за хеширование специальных обьектов, функция uVar3 = FUN_00f6adc0(param_2,param_3) отвечает что функция 00f6adc0 отвечает за указатель данного применения хеширования
данный код весь выполняется как хеш-таблица, которая вычисляет индекс uVar9-7 на основе полученных данных.
из всего вышеперечисленного мы можем уверенно сказать что 8 битный long в структуре il2cpp класса является указателем на следующий элемент в списке.
следующая функция FUN_00f66f90
и еще
и еще
puvar32 является указателем il2cpptypedefinition которая так же создается в метадате игры, а вот 0x5c является размером записи
сохраняем данную информацию в голове
далее -
из всего кода можно понять что базовый размер структуры составляет 0x130 байт что подтверждает что данный псевдокод указывает нам на валидную структуру в метадате
так же если вы заметили то puvar32 и 38 часто встречается в псевдокоде из-за чего можно подтвердить что наша метадата перед дампом проверяет все классы
из чего можно сделать следующую структуру нашего анализа
long* image; 0x00: *plVar24 = lVar39;
uint typeDefinitionIndex; 0x04: Из FUN_00f65494: `*(uint *)(plVar1 + 4)`.
uint flags_or_padding_0x08; 0x08: В FUN_00f6acac - здесь был names_hash.
.
const char* name; 0x10: plVar24[2] = (long)puVar29
const char* namespaze; 0x18: plVar24[3] = (long)puVar29; (
long* parent; 0x58: plVar24[0xb] = (long)plVar23;
long* declaringType; 0x50: plVar24[10] = (long)plVar23;
long* element_class; 0x48: plVar24[9] = (long)plVar24;
long* castClass; 0x40: plVar24[8] = (long)plVar24;
// Метаданные //
void* typeMetadataHandle; 0x68: plVar24[0xd] = (long)puVar32;
uint field_count; 0x110: *(uint *)(plVar24 + 0x22) = puVar32[8]; количество полей
uint method_count; 0x114: *(uint *)((long)plVar24 + 0x114) = puVar32[0x16];
зная уже эти базовые параметры можно предположить что загрузка классов в любом случае происходит в этой либке
вспомните что мы разбираем с вами только функцию update, и только с нее мы по отношениям узнали очень много всего полезного, детально разобрались как и кто загружает зашифрованные классы, что в дальнейшем нам очень сильно поможет в расшифровке
конец 1 части