![]() |
Добро пожаловать, гость ( Вход | Регистрация )
![]() |
-=CHE@TER=- |
![]()
Сообщение
#1
|
Walter Sullivan ![]() ![]() ![]() Группа: Root Admin Сообщений: 1,371 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 318 раз(а) ![]() |
На форуме Extractor.ru товарищ Axsis утверждал, что файлы там не запакованы, однако, судя по тому, что в Интернете нигде нет распаковщика и народ жалуется, что никто не может достать оттуда музыку - следовательно не всё так просто.
Скачал демку: _ttp://www.ag.ru/games/soldier-elite-zero-hour/demos/14368 Увы, отдебажить игру не могу, т.к. она падает до того места, где расшифровываются файлы - при инициализации графики (чего-то у меня в видеокарте нехватает, поэтому получаю ошибку чтения памяти по адресу 0x0000000c). Что успел отдебажить, так это открытие файлов. Кстати, кто тоже будет ковырять демку - там после первого запуска появится файл в каталоге /bin/, где можно поменять настройки и запустить игру в окне, чтобы отлаживаться не мешала. Так вот, всё что я смог узнать: 1) При открытии файла игра считывает 20 последних байт с конца: DWORD sign; // 0x20031031 DWORD vers; // 0x00000004 DWORD off1; DWORD off2; DWORD unkn; а) Первые два поля игра проверяет именно на эти значения - первое это сигнатура, второе - версия. б) offs1 < offs2, в файле textures.zap разница между ними 32 байта и оба смещения указывают примерно на конец файла (они оба проверяются, правда не понял с каким значением - с размером файла?). в) unkn - неизвестное поле, но небольшое. В том же textures.zap оно было равно 0xDB (но это точно не количество файлов - файлов там меньше было - штук 10). 2) Дальше игра, убедившись что файл верный, делает FileMapping() + MapView() всего файла, отчего ставить бряки на ReadFile() становится бессмысленным. (*улыбается*) 3) Интересен алгоритм определения архива свой/чужой - там также проверяется, а не .ZIP ли это архив. И, если .ZIP, то обрабатывается другим куском кода уже как .ZIP. В целом структура .ZAP похожа на .ZIP из чего делаю вывод, что: ZAP = ZIP Aurora Package Напомню, структура .ZIP выглядит примерно так: PK-заголовок|Файл-1|PK-заголовок|Файл-2|PK-заголовок|Файл-3|...|PK-заголовок|Файл-N А далее снова идут PK-заголовоки, но уже без файлов ("Файл-#" - это тело сжатого файла). Так вот, такое ощущение, что в .ZAP оставили именно этот хвост в конце с заголовками, а начало архива зашифровано. Причём ключ либо записан в самом архиве, либо игра генерит его как-то по другому (по имени, например), потому что все .ZAP архивы начинаются по разному. Какое шифрование - стандартное для .ZIP или своё - не знаю. Затрудняет это всё к тому же то, что файлы, видимо, сжаты, а уже потом зашифрованы. В упомянутом файле textures.zap в начале должен был идти .TGA файл - так вот, количество одинаковых полей по три байта (24 BPP видимо) в начале впечатляет. Однако, я перепробовал все XOR от 0 до 255, также rol и даже инверсию битов в байте слева на право - ничего хорошего так и не вышло. Кстати, в одном файле там вообще есть поле байт, эдак, под 200, если не больше, просто одинакового байта. Возможно, шифрование как-то меняет ключ или от чего-нибудь зависит (кстати, шифровать на предыдущий байт, как было в Runaway 2, я тоже пробовал). В файле с музыкой я нашёл две OggS сигнатуры незашированные. Но это два жалких фрейма, а не целые .OGG файлы. 4) Для тех, кто заинтересуется по адресу .692DE0 идёт чтение архива описанное в 1). Кто-нибудь желает помочь? |
![]() ![]() |
-=CHE@TER=- |
![]()
Сообщение
#2
|
Walter Sullivan ![]() ![]() ![]() Группа: Root Admin Сообщений: 1,371 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 318 раз(а) ![]() |
Распаковал программу при помощи .NET Reflector 7.5.2.1
CODE private void button1_Click(object sender, EventArgs e) { if (this.OpenZAP()) { byte[] buffer = new byte[4]; this.m_zap.Position = this.m_zap.Length - 8L; this.m_zap.Read(buffer, 0, 4); int treeOffset = BitConverter.ToInt32(buffer, 0); this.m_zap.Position = this.m_zap.Length - 12L; this.m_zap.Read(buffer, 0, 4); this.sizeOfPackedStream = BitConverter.ToInt32(buffer, 0); this.treeView1.Nodes.Add(this.m_zap.Name); this.getDirFiles(treeOffset, this.treeView1.Nodes[this.treeView1.Nodes.Count - 1].Nodes); } } private void getDirFiles(int treeOffset, TreeNodeCollection currentNode) { byte[] buffer = new byte[4]; this.m_zap.Position = treeOffset; this.m_zap.Read(buffer, 0, 2); short num = BitConverter.ToInt16(buffer, 0); this.m_zap.Read(buffer, 0, 2); short num2 = BitConverter.ToInt16(buffer, 0); this.m_zap.Read(buffer, 0, 4); int num3 = BitConverter.ToInt32(buffer, 0); for (int i = 0; i < num2; i++) { this.m_zap.Position = num3 + (i * 4); this.m_zap.Read(buffer, 0, 4); int num5 = BitConverter.ToInt32(buffer, 0); this.m_zap.Position = num5 + num3; FAS fas = new FAS(); buffer[0] = 0; buffer[1] = 0; buffer[2] = 0; buffer[3] = 0; this.m_zap.Read(buffer, 0, 1); fas.nameLenght = BitConverter.ToInt32(buffer, 0); byte[] buffer2 = new byte[0x100]; this.m_zap.Read(buffer2, 0, fas.nameLenght); fas.filename = Encoding.ASCII.GetString(buffer2, 0, fas.nameLenght); this.m_zap.Read(buffer, 0, 4); fas.offsetInZap = BitConverter.ToInt32(buffer, 0); this.m_zap.Read(buffer, 0, 4); fas.unpackedSize = BitConverter.ToInt32(buffer, 0); this.m_zap.Read(buffer, 0, 4); fas.packedSize = BitConverter.ToInt32(buffer, 0); this.m_zap.Read(buffer, 0, 4); fas.unk1 = BitConverter.ToInt32(buffer, 0); this.m_zap.Read(buffer, 0, 4); fas.unk2 = BitConverter.ToInt32(buffer, 0); this.m_zap.Read(buffer, 0, 4); fas.unk3 = BitConverter.ToInt32(buffer, 0); TreeNode node = new TreeNode(fas.filename) { ImageIndex = 1, SelectedImageIndex = 1 }; currentNode.Add(node); fas.NodePath = node.FullPath.Substring(this.m_zap.Name.Length + 1); this.fasArray.Add(fas); } int num6 = treeOffset + 8; for (int j = 0; j < num; j++) { this.m_zap.Position = num6 + (j * 4); this.m_zap.Read(buffer, 0, 4); int num8 = BitConverter.ToInt32(buffer, 0); this.m_zap.Position = num8 + num6; DAS das = new DAS(); buffer = new byte[4]; this.m_zap.Read(buffer, 0, 1); das.dirNameLen = BitConverter.ToInt32(buffer, 0); byte[] buffer3 = new byte[0x100]; this.m_zap.Read(buffer3, 0, das.dirNameLen); das.dirName = Encoding.ASCII.GetString(buffer3, 0, das.dirNameLen); this.m_zap.Read(buffer, 0, 4); das.offsetToTree = BitConverter.ToInt32(buffer, 0); TreeNode node2 = new TreeNode(das.dirName) { ImageIndex = 0, SelectedImageIndex = 0, Name = das.dirName, Text = das.dirName }; currentNode.Add(node2); this.getDirFiles(das.offsetToTree, node2.Nodes); } } zlib распаковывается, если packedSize != UnpackedSize. |
![]() ![]() |
Упрощённая версия | Сейчас: 1st May 2025 - 01:25 |