Декодируем структуру Xom через IDA
|
|
Сообщений: 1042
|
Опубликовано: 05.05.2023, 21:37:42
Как же происходит декодирование XOM?
Инструменты Для работы нам нужен дизассемблер IDA желательно от 7.5 версии.
Теория Все основные классы Xom создаются функцией XContainerClass::XContainerClass Выглядит это примерно так:
Код XContainerClass::XContainerClass( &XResourceDetails::c_class, &XResourceDetails::c_typeinfodata, &XContainer::c_class, XResourceDetails::CreateInstance_, 2, XResourceDetails::InitClass);
Что нам дает эта функция? Она присутствует почти во всех играх Worms серии 3D начиная от Worms Blast и заканчивая WUM, а часть осталась и в WMD.
В эту функцию передаются параметры: - создаваемый XClass - структура XBase::TypeInfo::TypeInfoData - XClass родитель - функция CreateInstance - тип класса 2 - функция InitClass
Тут нам нужна структура XBase::TypeInfo::TypeInfoData. В структуре TypeInfoData содержится ссылка на название класса, ссылка на GUID, номер версии, и тип класса. Код XResourceDetails__c_typeinfodata XBase::TypeInfo::TypeInfoData <offset aXresourcedetai, \\ XName "XResourceDetails" 1C0000h, offset XResourceDetails__GUID, \\ XGuid offset g_XrmUnit, \\ Type 0, 0, \\ Xver 0>
Нам важно название XName, XGuid и версия XVer. XGuid используется в начале всех Xom файлов для определения типа контейнеров. Код XResourceDetails__GUID XGuid <0E77556F2h, 491AA495h, 6C006385h, 447257E2h>
в xml он выглядит так:
Код guid="{E77556F2-A495-491A-8563-006CE2577244}"
Версия Xver нужна для совместимости, некоторые поля игнорируются в зависимости от версии.
Дальше нам важна функция InitClass. Она есть не во всех классах, но в ней содержатся все поля для контейнера. Внутри этой функции инициализируются поляКод XResourceDetails::InitClass(void *this) { XSFStringDescriptor::Initialize(this, &XResourceDetails::FieldInfo_Name); XSFUint32Descriptor::Initialize(this, &XResourceDetails::FieldInfo_Flags); }
FieldInfo это описание полей, оно обычно динамической длины, но основа всегда общая Код XResourceDetails::FieldInfo_Name FieldInfo < offset aName, \\ FieldName "Name" 14h, \\ FieldOffset 0, \\ FieldID 8, \\ FieldМask offset XBase::StringTypeInfo::c_class, \\ FieldClass XString 0, \\ SubType 0 \\ Xcomment >
Из этой структуры нам важно FieldName , FieldClass, FieldМask и Xcomment FieldМask работает следующем образом: - FieldМask = 8, поле присутствует всегда - FieldМask = 9, поле присутствует с данной версией - FieldМask > 9, поле отсутствует в данной версии или вообще
Кроме информации по полю важно еще функция Initialize. Есть два вида функций: - XSFTypeDescriptor::Initialize - XMFTypeDescriptor::Initialize
Первая XSF для одного значения, вторая XMF для коллекции XCollection Каждый XClass имеет в себе все поля своих родителей.
|
|
|
|
Сообщений: 1042
|
Опубликовано: 05.05.2023, 21:49:00
Практика
Как же распознать названия всех этих функций и полей? Тут нам пригодится встроенный скриптовой язык idc для автоматизации процесса. И необходимо вручную назвать базовые типы XInt, XUInt, XInt8, XUInt8, XInt16, XUInt16, XString, XFloat, XBool, XEnum, XColor4ub, XVector2f, XVector3f, XVector4f, XMatrix34, XMatrix, XBoundBox. Это можно легко сделать ориентируясь по классу XResourceDetails.
Итак мы открыли WormsMayhem.exe в IDA и прошли первое сканирование, переключаемся в окне IDA View-A на Text view. Теперь нам нужно найти XContainerClass::XContainerClass и назвать ее для простоты XContainerClass Вбиваем в поиск (Alt +T) "XResourceDetails" и получаем вот такой вид:
Эта и есть функция которую мы рассматривали в теории, она создает класс XResourceDetails::c_class Переименовываем sub_6C3C99 в XContainerClass. Далее нам нужно создать упрощенные структуры. Переходим в окно Local Types (Shift+F1) и нажимаем "Insert..." . Создаем XGuid Код struct XGuid { int d1; int d2; int d3; int d4; };
и XClass для структуры XBase::TypeInfo::TypeInfoData. Синхронизируем их кликая на каждую после создания Код struct XClass { void *XName; int Xflag; void *PXGuid; void *XType; int unk; int Xver; void *Xcomm; };
Все наша основа для работы скрипта готова!
Запускаем скрипт XomClassFound.idc (Alt+F7) Итог работы скрипта:
Теперь выбрав XContainerClass и нажав X мы получим список всех функций для инициализации контейнеров
|
|
|
|
Сообщений: 1042
|
Опубликовано: 05.05.2023, 21:59:23
Далее нужно создать еще две структуры, для работы второго скрипта: XComment Код struct XComment { void *name; void *comment; void *used; void *version; };
XValue он же ::FieldInfo
Код struct XValue { char *FieldName; __int16 FieldOffset; char FieldID; char FieldMask; void *FieldClass; void *SubType; XComment *Xcomment; };
Запускаем скрипт XomReadTypeWUM_XML.idc (Alt+F7) Получаем в Output window следующее Код <XResourceDetails guid="{E77556F2-A495-491A-8563-006CE2577244}" Xver="0" id="XRef"> <Name>dword_967698</Name> <Flags>dword_967650</Flags> </XResourceDetails> <XIntResourceDetails guid="{7D889B8D-2C14-445E-961F-5E0E5520416A}" Xver="0" id="XRef"> <Value>dword_96765C</Value> </XIntResourceDetails> <XUintResourceDetails guid="{93E5117C-8ADA-4AFB-B17A-668D0BDD15E6}" Xver="0" id="XRef"> <Value>dword_967650</Value> </XUintResourceDetails> <XStringResourceDetails guid="{7CDC5872-2CA3-4FCC-AE66-431071E5CE67}" Xver="0" id="XRef"> <Value>dword_967698</Value> </XStringResourceDetails> <XFloatResourceDetails guid="{08889D5F-8039-4CEA-BA5B-9C059AC0570E}" Xver="0" id="XRef"> <Value>dword_967680</Value> </XFloatResourceDetails> <XVectorResourceDetails guid="{071F4563-8CB3-4996-B79F-B0F5CAEC9D99}" Xver="0" id="XRef"> <Value>unk_96EBE0</Value> </XVectorResourceDetails> <XContainerResourceDetails guid="{E0B6BF20-F80B-4329-B6EB-1998ED8AEC1F}" Xver="0" id="XRef"> <Value>dword_970B94</Value> </XContainerResourceDetails> <XColorResourceDetails guid="{7804BA7B-C6FD-4E8E-AFFF-8E266B6A5544}" Xver="0" id="XRef"> <Value>unk_96E988</Value> </XColorResourceDetails> <XDataBank guid="{93E661AC-D941-442A-A18E-E99B795879DC}" Xver="0" id="XRef"> <Section>dword_967620</Section> <IntResources>dword_970B94</IntResources> <UintResources>dword_970B94</UintResources> <StringResources>dword_970B94</StringResources> <FloatResources>dword_970B94</FloatResources> <VectorResources>dword_970B94</VectorResources> <ContainerResources>dword_970B94</ContainerResources> <StringTableResources>dword_970B94</StringTableResources> <ColorResources>dword_970B94</ColorResources> </XDataBank>
Как видно у нас много не известных типов dword_970B94, dword_967620 , unk_96E988 их нужно в ручном режиме назвать соответственно ресурсам. У нас должен получится такой вывод: Код <XResourceDetails guid="{E77556F2-A495-491A-8563-006CE2577244}" Xver="0" id="XRef"> <Name>XString</Name> <Flags>XUInt</Flags> </XResourceDetails> <XIntResourceDetails guid="{7D889B8D-2C14-445E-961F-5E0E5520416A}" Xver="0" id="XRef"> <Value>XInt</Value> </XIntResourceDetails> <XUintResourceDetails guid="{93E5117C-8ADA-4AFB-B17A-668D0BDD15E6}" Xver="0" id="XRef"> <Value>XUInt</Value> </XUintResourceDetails> <XStringResourceDetails guid="{7CDC5872-2CA3-4FCC-AE66-431071E5CE67}" Xver="0" id="XRef"> <Value>XString</Value> </XStringResourceDetails> <XFloatResourceDetails guid="{08889D5F-8039-4CEA-BA5B-9C059AC0570E}" Xver="0" id="XRef"> <Value>XFloat</Value> </XFloatResourceDetails>
За вывод в формате XML отвечает функция скрипта XMLPrint. Она закомментирована для остальных типов, с помощью ее можно узнать структуру любого контейнера.
Структура этих общих функций EXE отличается в разных играх, поэтом скрипт не универсален и его необходимо переписывать, но суть работы не меняется.
При должном желании можете глубже разобраться.
|
|
|
|
Сообщений: 1463
|
Опубликовано: 06.05.2023, 17:20:30
Цитата AlexBond ( ) - тип класса 2 это ComponentCategoryEnum Код enum ComponentCategoryEnum { Generic = 0x0, Action = 0x1, Container = 0x2, RenderAttribute = 0x3, Type = 0x4, ActionMethods = 0x5, HttpCallback = 0x6, Singleton = 0x7, TypeConverter = 0x8, Entity = 0x9, Service = 0xA, LogicEntity = 0xB, ContainerBinding = 0xC, };
|
|
|
|