PrxEncrypter Mod v1.0.0.1 - Full Range Demo Game Sign
PrxEncrypter Mod
Подписываем приложения оригинальными заголовками
Как вы знаете, оригинальная версия Энкриптера содержит в себе только 3 заголовка для подписи приложений, диапазон размеров которых бывает явно недостаточен для более тонкого шифрования исполняемых файлов. Поэтому я собрал все имеющиеся в наличии заголовки демо-версий игр и портировал их в классический PrxEncrypter.
Что это за мод?
Это версия шифровальщика, собранного на основании предыдущей подготовительной темы, включающего 103 заголовка демонстрационных версий игр, способного подписывать приложения для запуска с карты памяти на официальных прошивках.
Способен подписывать исполняемые файлы DATA.PSP в диапазоне ~ 368 kb - 8 Mb
Для подписи автоматически подбирается самый маленький из 103-ёх по размеру заголовок
Используются "теги" категории "MG Demo" (MemoryStick Game Demo) - 0x0C000000 и 0xADF305F0
Можно подписывать только DATA.PSP для использования в контейнере EBOOT.PBP
Но никак не EBOOT.BIN для способа NP.ISO => EBOOT.PBP, т.к. для этого контейнера требуются теги другого диапазона "EG" - 0xD916xxF0
Для этого случая уже имеется прекрасный инструмент - SEBOOT (Sign EBOOT.BIN)
Подписываемые приложения не должны иметь Kernel-модулей, только User-режим.
Для запуска приложений, использующих kernel-режим, требуется внедрение rebootex модуля, что пока лично мной не изучено. Если кто-то имеет информацию по данному вопросу, то можете поделиться ей. Например неплохо было бы заставить работать PSPident на официальных прошивках...
В папку "PrxEncrypter Mod" скопируйте для подписываения файлы EBOOT.PBP, DATA.PSP или EBOOT.BIN. Так же, чтобы сразу собралась подписанная программа со всеми ресурсами, можете в папку добавить файлы ICON0.PNG ICON1.PNG PIC0.PNG PIC1.PNG SND0.AT3 DATA.PSAR.
Запустите программу "PrxEncrypterMod.exe" для подписи.
Заберите создавшуюся папку "SIGNED GAME" с подписанным EBOOT.PBP и положите её на карту памяти в папку ms0(ef0):/PSP/GAME/
Папку можете переименовать по названию вашей игры или программы.
Changelog PrxEncrypterMod:
Добавлено 100 заголовков от демоверсий для подписи, к 3-ём ранее имеющимся. Итого 103 заголовка.
Добавлена проверка на ~PSP и ELF
Заменён механизм сжатия в GZIP библиотекой zlib на консольный 7-Zip.
Исправлен баг, когда файл всегда подписывался бОльшим заголовком, чем он сам, несмотря на используемое сжатие. То есть, даже если файл сжимался намного меньшим размером и свободно помещался в меньший заголовок, то заголовок всё равно брался бОльший, чем несжатый файл.
Автоматизирован процесс подписи.
Таблица включённых в PrxEncrypter заголовков по алфавиту:
Таблица демонстрационных игр, выпущенных для Sony PSP (по алфавиту)
Тут в PrxDecrypter я заметил некорректно написанный код сжатия. Вернее он сжимает и всё подсчитывает корректно, но алгоритм сжатия у него работает не так, как надо.
В ообщем тут такое дело, что если декриптовать тот же Astinishia Story 2 и попытаться обратно зашифровать его же родным заголовком, то так не получится, потому что декриптованный ELF-файл уже не поместится по размеру в свой родной заголовок - будет ошибка: Elf is to big. И это при том, что якобы в алгоритме энкриптера используется сжатие , причём после шифровки и последующей декриптовке явно отображается, что файл:
Аналогичная ситуация происходит со всеми файлами, например при попытке подписать файлы прошивки своими же заголовками.
Короче, я так понял, алгоритм шифрования происходит в следующем порядке:
Сравнение по размеру ELF-файла с размером, записанном в шифрованном заголовке по адресу 0x2C минус 0x15С
Если ELF-файл больше, то выдаётся сообщение об ошибке: Elf is to big
Затем, если файл меньше, то он в конце забивается нулями до размера, прописанного в шифрованном заголовке по адресу 0x28 (размер декриптованного ELF)
После применяется сжатие GZIP
Добивается архив в конце нулями до размера, указанного в шифрованном заголовке по адресу 0xB0 (размер архива)
И наконец файл шифруется и добавляется заголовок.
Тут требуется только поправить порядок действий на такой:
Если сжатый файл меньше, то он в конце забивается нулями до размера, прописанного в шифрованном заголовке по адресу 0x28
Применить сжатие GZIP
Добивается архив в конце нулями до размера, указанного в шифрованном заголовке по адресу 0xB0
Сравнение по размеру сжатого ELF-файла с размером, записанном в шифрованном заголовке по адресу 0x2C
Если ELF-файл больше, то выдаётся сообщение об ошибке: Elf is to big
И наконец файл шифруется и добавляется заголовок.
Это моё видение навскидку, но возможно там происходят более масштабные преобразования и придётся не просто поменять местами порядок выполнения функций, а ещё и переписывать код.
Хотя, сам код довольно короткий и простой, но я так и не понял, каким же образом происходит порядок сжатия.
Я хотел сказать, что СЖАТИЕ здесь вообще не имеет никакого смысла и эффекта, хотя оно явно используется.
То есть, файл размером 1 Мб должен ужаться и подписаться маленьким заголовком, однако он всегда подписывается большим заголовком, чем сам файл.
Провёл такой эксперимент. За основу взял оригинал DATA.PSP - Astinishia Story 2.
0x2C = 0x00059FA0 = 368'544 byte - размер всего файла с заголовком.
0xB0 = 0x00059E44 = 368'196 byte - размер архива.
Чтобы файл работал, все эти данные должны совпадать. Ну а мы пока работаем с оригинальным файлом, поэтому тут и так всё должно быть чётко.
Так как я знаю, что файл пожат в GZIP, то теперь я в PrxDecrypter отключаю декомпрессию (тупо в коде меняю сигнатуру 1F8B на любую другую, по которой программа определяет, что перед ней GZIP-архив). Это находится здесь:
// GZIP DECOMPRESSION
if (*(u16 *)&g_dataOut2[0] == 0x8B1F) {
Теперь программа будет только декриптовать шифрованный файл, но разархивировать не будет.
Декриптуем оригинальный DATA.PSP от Astinishia Story 2
В папке "enc" обнаруживаем декриптованный файл, но конечно там нет знакомой сигнатуры ELF, а видим знакомые цифры 1F8B - архив GZIP.
Смотрю его размер. Он в точности совпадает с указанным в заголовке:
0xB0 = 0x00059E44 = 368'196 byte - размер архива.
Смотрю у архива последние 4 байта -> 0x000EF008.
Они по спецификации GZIP указывают на размер разархивированного файла, что в точности совпадает с указанным в заголовке:
Для уверенности разархивирую с помощью 7-zip этот архив и получаю чистый ELF, как и положено ему быть.
Ликбез №3
Поехали дальше... Теперь проводим эксперимент с фейковой подписью.
Беру чистый декриптованный ELF от Astinishia Story 2 (978'952 byte - довольно большой )
Подписываю через PrxEncrypter.
Получаю на выходе подписанный файл размером 0x00164000 = 1'458'176 byte заголовком от Dynasty Warriors Strikeforce
Вот те ппц, приехали, наглядный пример сжатия PrxEncrypter
Ну это не удивительно, он всегда так подписывал, потому что сначала подбирает под декриптованный ELF подходящий заголовок, не меньше размером, забивает до нужного размера 0x28 нулями, а только потом сжимает, опять добивает уже архив всяким мусором до указанного в заголовке 0xB0 размера архива и затем шифрует.
Короче, подписанный фейковый файл опять декриптуем без декомпрессии.
Получаем на выходе архив 1F8B размером 0х00163EAE = 1'457'838 byte - собственно, как и указано в заголовке 0xB0Dynasty Warriors Strikeforce
Сразу разархивирую его с помощью 7-Zip и получаю декриптованный ELF размером 0x00433DBC = 4'406'716 - как и указано в заголовке 0x28.
1. По первому пункту получаем такой прикол - ищу конец архива - последние 4 байта в архиве, по уже известному размеру разархивированного файла BC3D4300 - настоящий архив кончается в 1/3 от начала и составляет 0x0005DD59 = 384'345 byte. Остальная 2/3 части забито оставшейся частью декриптованного ELF-файла и далее нулями. То есть, берётся сам декриптованный файл, архивируется в GZIP и затем архив вставляется в этот же файл в начало, и есстественно конец декриптованного файла остаётся. Но это не беда, архив GZIP имеет потоковый формат и разархивируется потоково, пока не дойдёт до своего конца, а что там после конца - ему на это пофиг. Не зря GZIP не имеет меток размера и конца, но в конце обязательно имеет последние 4 байта метки разархивированного размера.
Да, настоящий архив, без нулей и мусора от ELF, немного не дотягивает до "Astonishia Story 2" (368'544), но зато свободно бы влез в заголовок от "Everybody's Sukkiri #1" (430'176 byte).
2. По второму пункту - разархивированный файл так же забит на 2/3 нулями, чтобы подогнать его под размер заголовка в 0x28
В общем, суть в том, что энкриптер сначала подбирает заголовок под ELF-файл, потом под этот заголовок подгоняет его, а только потом архивирует и опять подгоняет.
А нужно, чтобы он сначала архивировал ELF, а только потом под архив подбирал заголовок.
Прошу любить и жаловать, Ваш Добро пожаловать в наш Чат в Telegram
Последний раз редактировалось ErikPshat; 28.04.2013 в 20:11.
А что в итоге нужно я так и не понял. Проверку на размер по 0xB0 вместо 0x28?
Да нет, не совсем так. Выше 2 моих лигбеза специально сравнивают 2 механизма сжатия - оригинальное и фейковое.
В оригинальном механизме файл почти в 1 Мб сжимается в 368 Кб и потом шифруется.
В фейковом механизме файл почти в 1 Мб сначала подбирается под заголовок большего размера, потом ЗАЧЕМ-ТО сжимается и шифруется.
Вопрос в том - нафига тогда вообще используют сжатие, если всё получается так же, как без сжатия.
Должно быть не так. Файл сначала должен сжаться, а только потом подбираться заголовок под маленький сжатый файл, а потом всё остальное.
Прошу любить и жаловать, Ваш Добро пожаловать в наш Чат в Telegram
Для запуска приложений, использующих kernel-режим, требуется внедрение rebootex модуля, что пока лично мной не изучено. Если кто-то имеет информацию по данному вопросу, то можете поделиться ей. Например неплохо было бы заставить работать PSPident на официальных прошивках...
Ну во-первых rebootex не есть модуль. Чтобы досконально изучить это дело можешь посмотреть Davee's Downgrader. Схема работы такая.
1. Использование kernel-эксплоита под определённую прошивку.
2. rebootex по сути это код с kernel правами, который так и так выполняется каждый раз при перезагрузке или смене режима (VSH, GAME...).
Так вот он внедряется. Он патчатит необходимые модули: LoadExec в первую очередь. И только потом можно уже стандартно загрузить модуль с правами ядра.
Что мы сейчас написали? Угу, прошивку. Поэтому, предположение было в корне неправильное
Что насчет енкриптера. Я не совсем понял о чем ты говоришь. То есть тебя смущает что заголовок подбирается под несжатый файл, а только потом жмется?
P.S. Если ты хочешь чтобы подборка хедера работала корректно, то их нужно располагать в строгом порядке возрастания размера подписи, т.к. этого требует алгоритм. Он буквально берет первый подходящий, а не самый оптимальный из списка. Нужно или переписать алгоритм или располагать в порядке возрастания.
их нужно располагать в строгом порядке возрастания размера подписи
Они именно так расположены.
Сами хедеры идут сверху вниз по убыванию размера в заголовке, а листинг, список хедеров, идёт по возрастанию размеров.
Таблица в шапке уже составлена по возрастанию, а я располагал хедеры именно в том порядке, как было подготовлено в таблице.
Тут всё правильно, подпись берётся именно по возрастанию. Я проверял, если файл не умещается в заголовок, то берётся следующий.
А вот со сжатием в энкриптере совсем не правильно. Что оно есть, что его нет - один фиг.
Просто сжатие есть и сжимает, но потом подписывает заголовком большим, чем декриптованный файл.
Ну если бы ты повнимательнее почитал бы, что я написал и вник бы, то наверное бы всё понял.
Прошу любить и жаловать, Ваш Добро пожаловать в наш Чат в Telegram
frostegater, да, именно так, но немного не так. Ещё нужно, чтобы математика была точной и опираться на указанные в заголовке размеры:
0x28 - размер ELF декриптованного файла.
0x2C - размер всего файла с заголовком.
0xB0 - размер архива.
Только по твоей формуле как мы будем забивать декриптованный ELF нулями до размера 0x28, если он уже будет запакован
Тут нужно как-то изловчиться по другому...
Считали некриптованый ELF файл
Подобрали заголовок >= по позиции 0х28
Забили ELF нулями до этого размера 0х28
Зажали его
Измерили размер архива
(размер разархивированного архива записан в последних 4-ёх байтах GZ-архива, должен равняться позиции 0x28 - это и есть конец архива)
Забили конец архива нулями до размера в позиции 0xB0
Подписали
Я не понимаю, как у них внутри архива оказывается конец на 1/3 архива, а остальное забито остатками декриптованного незаархивированного ELF. Они наверное архивируют не в чистое место памяти, а прямо туда же в начало, где находится ELF, потом отрезают по размеру 0xB0 и получается хвост не просто забитый нулями, а забитый остатками ELF
Причём зачем-то в последней строчке нулевого архива вставляют какой-то код. Оно ведь и так конец читать не будет и правильно разархивируется.
Прошу любить и жаловать, Ваш Добро пожаловать в наш Чат в Telegram
Последний раз редактировалось ErikPshat; 28.04.2013 в 09:56.
Другие консоли: Все PSP, все PSV, SCPH-1002, SCPH-102, SCPH-77008, CECH-4208C, SCPH-1000R
Регистрация: 19.03.2008
Адрес: Россия
Сообщений: 5,733
Вы сказали Спасибо: 819
Поблагодарили 3,835 раз(а) в 2,013 сообщениях
Сила репутации: 1
Репутация: 3835 
(репутация неоспорима)
Сообщение от frostegater
Ну во-первых rebootex не есть модуль. Чтобы досконально изучить это дело можешь посмотреть Davee's Downgrader. Схема работы такая.
Я ему в личку про это писал.
Сообщение от ErikPshat
Ну если бы ты повнимательнее почитал бы, что я написал и вник бы, то наверное бы всё понял.
Что я, что Фрости могут сделать что нужно, но оба нифига не поняли. У тебя, как я и говорил у тебя в гостях, в тексте слишком много воды. Как всё работает я спокойно могу прочесть в исходниках. А вот что не так по твоему мнению приходится выискивать в дебрях букв. Единственное, что я нормально понял, так это то, что эльф своим же родным заголовком не подписывается - вот от этого утверждения ещё можно плясать.
эльф своим же родным заголовком не подписывается - вот от этого утверждения ещё можно плясать.
Ну да, я об этом постоянно твержу ))
Просто я более подробнее описываю суть проблемы и в каком месте, что программа работает не так, как должно быть.
И подробно описал принцип ихней упаковки на примере последующей распаковки.
Можешь сам проверить на оригинальных исходниках.
Удаляешь оттуда все лишние хедеры с кирками и оставляешь только 1 кирк с хедером от того же файла, который хочешь подписать.
Взять тот же Astonishia Story 2 или vshmain.prx, или любой другой.
Ессно файл не влезет обратно в свой родной заголовок и будет ошибка "ELF is to big"
P.S. Порядок упорядочивания кода я уже написал в предыдущем посту.
Прошу любить и жаловать, Ваш Добро пожаловать в наш Чат в Telegram
Yoti
1) Я вроде ничего такого не ставил, но вроде Cygwin.exe всё решает.
2) Попробую...
3) А ты его в SDK положил )) Ну я так сделал, чтобы в папке не затирался декриптованный исходник DATA.PSP. Поначалу исходник сразу копировал в папку SOURCE, да потом что-то решил так сделать.
А кстати, всё-таки ведь файл подбирается не по порядку списка, а наверное выбирается наименьший подходящий размер.
Блин, сижу щас таблицу заполняю по размерам декриптованных ELF, чтобы понять почему так прыгает далеко. Просто у Astonishia Story размер декриптованный очень большой, поэтому наверное не может найти более подходящий хедер поменьше. Но полюбэ должен же подойти свой родной.
Кстати, размер архива берётся из kirk_header 0x70 - там дублируется тот же размер, что и в psp_header 0xB0. Ну ты и сам знаешь ))
Прошу любить и жаловать, Ваш Добро пожаловать в наш Чат в Telegram
1. А может список хедеров нужно было выстраивать по ELF размеру, а не по размеру всего файла? Или всё-таки он не находит подходящий из всего списка...
2. Может он тупо не может сжать файл до 0xB0? Потому что я смотрел сжатый файл Astonishia, так он больше получается, чем записано в 0xB0. Но в коде не заметил, чтобы он по этому параметру производил листинг.
Странно, через 7-Zip он у меня сжимается значительно сильнее в GZIP. Вот с такими параметрами:
Библиотека в SDK вроде использует урезаный механизм:
ret = deflateInit2(&strm, 9, Z_DEFLATED, 15+16, 8, Z_DEFAULT_STRATEGY);
Уровень сжатия максимум = 9
Метод сжатия для GZ только = Z_DEFLATED
windowBits состоит из двух логарифмов и может быть в пределах 8-15. Если добавить +16, то не будет включаться название файла, подсчитываться CRC и прочие плюшки.
memLevel может быть в пределах 1-9, здесь стоит = 8
Ну вот тогда, нашёлся здесь: C:\cygwin\usr\x86_64-w64-mingw32\sys-root\mingw\lib
Кстати, разработчики игры Astonishia ведь как-то ужали так сильно файл в GZ какой-то библиотекой, значит должно ужаться с совместимостью.
Короче, тут дело в сжатии. Он просто не может сжать файл до исходного размера, как он был сжат ранее, поэтому сжимает и потом ищет не среди psp_header по размеру файла 0x28, а по размеру архива из KIRK-заголовков, продублированного в 0x70 в кирке (0xB0 в psp_header):
krawSize - это и есть размер архива, записанного в kirk_header по адресу 0x70.
Поэтому, даже если размер ELF >= размера в psp_header, то он берёт нужный хедер, но, если после сжатия размер архива не подходит к kirk_header, то он по списку ищет следующий подходящий по размеру среди kirk_header-ов.
Другой вопрос - действительно ли он ищет по порядку в списке или всё-таки из всего списка выбирает наиболее подходящий?
Прошу любить и жаловать, Ваш Добро пожаловать в наш Чат в Telegram
Последний раз редактировалось ErikPshat; 02.05.2013 в 06:27.
Насколько знаю, архиватор 7-Zip всегда сжимает в правильный GZIP с любыми настройками сжатия, поэтому провёл ещё эксперимент...
Отключил в PrxEncrypter сжатие в GZIP /* закомментил */
Подключил внешнее сжатие через 7-Zip по максимуму (-mx=9 -mfb=128 -mpass=10 - Ультра)
Кидаем декриптованный ELF (DATA.PSP) в папку и запускаем SIGN.BAT - файл сжимается через 7-Zip и подписывается.
Собственно ELF Astonishia подписалась своим собственным заголовком и прекрасно функционирует на оффпрошивке.
Причём энкриптер по прежнему автоматом сам добавляет нули к архиву до размера в кирке 0x70.
Но есть одно но, т.к. мы подсовываем Энкриптеру готовый архив, предварительно прогнанный через 7-Zip, то к ELF-файлу нули не добавляются до размера 0x28, потому что он заархивирован ))) У Astonishia ничего добавлять не нужно, т.к. ELF уже имеет нужный размер к своему же заголовку.
Поэтому, если мы берём декриптованный файл меньше указанного в заголовке, то сначала добиваем его нулями, а потом кидаем для сжатия и подписи.
Так же чётко подписался архив "Cube Sample", предварительно конечно добитый нулями до указанного в заголовке размера в 0x28.
Можете сами потестить, всё в архиве заготовлено.
Как можно подключить библиотеки 7-Zip к исходникам? И где их ваще взять?
Кстати, Zlib в SDK лежит версии 1.2.5, а на оффсайте уже zlib 1.2.8 (April 28, 2013)
Прошу любить и жаловать, Ваш Добро пожаловать в наш Чат в Telegram
Последний раз редактировалось ErikPshat; 01.05.2013 в 09:30.