Некоторое время назад мне в руки попал телефон Nokia N80, который имеет на борту Symbian 9.1. Естественно, по началу всё было хоршо, но в какой-то момент я понял, что мне вдруг стало интересно, что же там внутри. Утилит для распаковки инсталляционных пакетов .sis и .sisx существует не мало, но как же я удивился, когда увидел, что исполняемые файлы содержат подозрительный код. Подозрительный он был потому, что абсолютно не похож на код, а похож на запакованные или закриптованные данные.
Вооружившись гуглем, узнал, что это нововведение такое - запаковывать весь исполняемый файл за исключением заголовка. Но ведь как-то это люди обходят, подумал я, набирая во всё том же гугле "unpacking symbian os 9.1 executables". Увы. Если люди как-то и обходят, то способ этот малоизвестен и поисковые сервера о нём не знают. А знают они только о подобных же мучениях других людей. Единственное, что удалось узнать - используется метод deflate якобы из библиотеки zlib.
Взяв в руки библиотеку zlib, компилятор и пошаманив пару часов выяснил, что всё несколько сложнее. И встал вопрос - каким образом не имея возможности отлаживать код и проверять догадки, можно распаковать исполняемый файл? Вооот...
Самым логичным было, как можно легко догадаться, скачать SDK, который подобные файлы создаёт. Из всего этого SDK нам оказался нужен один единственный файл, который называется "elf2e32.exe" (Symbian Post Linker). Если запустить этот файл с параметром "--e32input=", то он покажет всю информацию из исполняемого файла включая распакованные секции кода, данных, релоков, импортов, экспортов. Дальше уже - дело техники.
Загрузив elf2e32.exe в IDA, довольно быстро была найдена процедура, выводящая на экран распакованные данные:
Параметрами к этой процедуре являются смещение на данные и их размер. Но это не самое интересное. Самое интересное, что в регистре EDX в это же время находится смещение на... Правильно, на полностью распакованный образ исполняемого файла. После этого нам остаётся лишь в начало этой процедуры вставить переходник на собственную функцию, которая бы записывала нужные нам данные в отдельный файл и возвращалась обратно сделав вид, что ничего не происходило.
По адресу 00418197 мы заменяем инструкцию "sub esp, 120h" на переход на наш код. Впоследствии, при выходе из нашей функции, мы выполним эту инструкцию, чтобы код исполнялся именно так, как и должно быть.
Мы находим пустое место в конце секции кода в elf2e32.exe и вписываем туда вызов нашей функции из нашей же DLL:
Сама DLL и функция так же не представляют из себя ничего выдающегося, мы просто парсим заголовок исполняемого файла, смещение на которое мы поймали в регистре EDX ранее. Сначала убираем флаг, отвечающий за то, что файл был запакован, а затем пересчитываем контрольную сумму заголовка. Всё.
Как видите, не обладая практически никакими познаниями в программировании, а особенно на архитектуре ARM, не имея возможности отлаживать код, можно вполне успешно обходить некоторые ступени защиты, на которые программисты иногда не очень обоснованно возлагают свои надежды.