среда, 22 февраля 2006 г.

Как я правил прошивку своего сотового телефона

В общем решил я тут починить джойстик у своего Siemens CX65 (ношу телефон в кармане джинс вот выпирающая часть джойстика и отломилась еще месяц назад). Взял телефон, снял панель съемную, достал клей моментальный, взял хреновину одну, чтобы приклеить её к остаткам джойстика, намазал джойстик, приставил хреновину, подождал - хреновина прилипла к рукам, а не куда надо. Проделал еще пару попыток, поматерился своей лени на тему зачистить, обезжирить и тд, одел съемную панель обратно, включил телефон и заметил, что джойстик теперь совсем перестал работать, наверное капелька клея скатилась по остаткам джойстика к контактам и изолировала их. Если раньше остатки джойстика можно было как-то ногтем или вспомогательным предметом двигать, чтобы добиться нажатия в нужном направлении, то теперь это стало бесполезно.

Для исправления новоявленной проблемы можно было бы до конца разобрать телефон и сам джойстик, а потом химическим путем убрать клей. Только есть шанс, что после этого может стать только хуже :), да и не факт, что там все дело в моем предположении. И выбрал я другой путь - надо подправить прошивку телефона, чтобы сочетания работающих клавишь имитировали джойстик.

Первым делом требовалось вытащить эту самую прошивку из телефона, а для этого необходим шнур и програмное обеспечение. За четыре дня до прошлого нового года я купил шнур "телефон<->usb" за 1000 рублей, после чего, буквально в тот же день улетел на родину в Омск (из Москвы) на неделю, а потом в Киев еще недели на две. Когда же я вернулся в Москву и попробовал тот шнур, что купил вскрылись две детали: для телефонов сименс существует множество шнуров различающихся как по моделям телефонов, так и по функциональности. Мой шнур тогда не завелся ни в винде (с родными и не родным дровами), ни в линухе. А гарантия на обмен (15 дней) истекла, пока я мотался Москва->Омск->Москва->Киев->Москва. Но теперь, начитавшись форумов, я твердо решил взять этот шнур и переделать его из нерабочего в рабочий. Подключив его для верности в linux 2.6.15, дабы убедится, что он таки не работает, но по dmesg я увидел обратное:
drivers/usb/serial/usb-serial.c: USB Serial support registered for pl2303
pl2303 3-1:1.0: pl2303 converter detected
usb 3-1: pl2303 converter now attached to ttyUSB0

Поискав драйвера под винду конкретно для pl-2303 я завел его и в винде без всяких передлок. Теперь нужно программное обеспечение... к счастью, с ним никаких проблем, его полно в интернете.

Когда телефон подружился с компьютером, настало время сделать backup этого телефона: рассчитать все коды (HASH, SKEY, IMEI, BKEY, ESN) и записав их в файлик, сделать дампы фулфлэша, буткора (на всякий), лэнгпака (на всякий), еелайта и еефула. Теперь душа спокойна, шансы окончатильно убить тело уменьшились. Для того, чтобы не патчить старую прошивку, я заодно поставил sw50 взамен стоявшей 12 версии (обновил фуллфлэш, обновил файловую систему и мэппинг). На всякий случай снова сделал бэкапы всего подрят.

Бэкапы сделаны, прошивка лежит на винте, самое время поставить IDA, изучить ассемблер ARM710, найти в прошивке нужный код и наконец сделать патч. Для верности и на всякий случай (вдруг пригодится), собрал и поставил на свой debian binutils-arm-linux и компилятор gcc-arm-linux. Изучать набор инструкций ARM было достаточно необычно, интересно и приятно, все-таки набор отличается от x86 в лучшую сторону.

А дальше началось изучение прошивки. Процесс надо сказать неоднозначный.. то ты начинаешь впадать в уныние не знаешь с какой стороны подойти и понять какой вызов был для чего сделан, а то вдруг неожиданно находишь интересные куски кода. Процесс изучения прошивки напоминает следующую ситуацию: вас помещают в произвольное место гиганского лабиринта из которого вам надо найти выход, у вас есть возможность телепортироваться в случайное место лабиринта по желанию, в лабиринте темно, а на полу начерчена замкнутая схема, которую можно использовать на ощупь. Сравнение может быть не очень корректное, но процесс перемещения по функциям немного напоминает.. Радостными моментами в таком деле стали: распознавание стандартных функций типа memset, strcpy, strchr, strlen, printf и т.д., обнаружении функции вызываемой в случае ошибки (не понятно правда куда она ошибку девает, толи в лог, толи еще куда, но это и не важно, а важно, что она вызывается с текстовым описанием ошибки), функции isKeyGood и наконец функции KeyPress!!! А я ведь все время был рядом с этой заветной функцией... всего-то надо было внимательнее смотреть на BFC, хотя наверное эта внимательность пришла как раз в процессе разгребания прочих участков.

Теперь появилось чувство определенности. Самое главное - это найти где править, а это я уже сделал. Дело за малым - найти свободные участки прошвки, озу и написать патч. К сожалению скачать keil arm не получается - траффик на интернет аккаунте кончился, а keil весит под 50м, поэтому решаю покомпилировать с помощью arm-linux-as.

Правлю участок прошивки отвечающий за обработку нажатия клавиши таким образом, чтобы он передавал управление на мой основной код (который еще не написан), а также добавляю в прошивку псевдофункцию для выполнения оригинального кода. Теоретически это все не сложно, а на практике приходится набирать команды чуть-ли не побитно, подбирая смещения - это ужасно, хотя кажется где-то я уже этим когда-то занимался. Вспомогательный код готов, можно приниматься за основной, формулирую для себя, что он должен делать.

При нажатии на клавишу green (start) происходит переход в режим имитации джойстика. а при ее отжатии мы возвращаемся в нормальный режим, причем если в режиме имитации прочих нажатий не было, то трактуем нажатие на кнопку green как в обычном режиме. В результате при одиночном нажатии (нажали и отпустили) клавиша выполняет свою обычную функцию, а в сочетании с цифровыми клавишами - является модификатором. В свою очередь, при нажатии на цифровую клавишу смотрим, в каком режиме мы находимся: если режим расширенный, то трактуем нажатие как действие джойстика, в противном случае клавиша выполняет свои обычные действия; похожим образом обрабатываем отпускание цифровой клавиши, но тут нужно смотреть, что если мы сейчас в режиме имитации, или эта клавиша была ранее нажата в этом режиме, то имитируем отжатие джойстика, в противном случае ничего не имитируем, а трактуем отжатие как есть. При таком подходе получается следующая клавиатура телефона:




1, left-up 2, up 3, right-up
4, left 5, click 6, right
7, left-down 8, down 9, right-down

Как нетрудно заметить из функционального описания, программа должна использовать состояние. Выделяем под него 32 бита и находим свободную память для переменной с помощью ArmDebugger'а.

Алгоритм при любом подходе получается немного сложноватый, чтобы тратить время на его реализацию на ассемблере, поэтому я набросал его на C и скомпилировал с помощью arm-linux-gcc в объектный файл. Но не все так просто, как хотелось бы. Замечательный GCC сгенерировал код использующий не хилую таблицу абсолютных адресов (для switch'а), а так как этот код будет располагаться в совершенно другом участке памяти, то надо либо править адреса руками, либо думать как объяснить gcc/as, что я хочу код для определенного участка памяти. Как объяснить GCC/AS я не нашел :(. Но зато разобрался с ld, которым слинковал объектный файл, указав, что хочу секцию .text расположить строго по такому-то адресу. Получилось! Для того, чтобы получить vkp патч на основе elf файла, пишу скрипт на perl'е, на выходе которого получаю заветный патч.

Почти все сделано, напряжение и нетерпение растет! Загружаю патч в IDA, правлю в патче адрес переменной и адрес оригинального обработчика на реальные. Добавляю в патч изменения связанные с изменениями самой прошивки и вот патч готов!

Немного волнуясь, загружаю v_klay, заливаю патч в телефон.

Нажимаю кнопку включения - черный экран и ничего не происходит, что-то внутри опустилось. Нажимаю кнопку включения еще раз! О! Телефон включается - уже хорошо. Робко набираю первую цифру pin кода.. телефон издает характерный звук нажатия и цифра появляется на экране - значит нормальный режим отрабатывает верно. Захожу в меню и пробую режим имитации - работает, я могу бегать по меню.. работает все в том числе диагональные перемещения!

Даже не ожидал, что патч получится с первой попытки! Какой я молодец! :)))

А вот и сам патч.