Осторожно: помните ли вы, как в вашем телефоне Siemens, Motorola и Sony поселились маленькие программы — ‭‭«эльфы»? В рамках этой статьи мы во всех деталях исследуем прошивку бюджетного кнопочника, разберемся в её архитектуре, хакнем и напишем загрузчик тех самых эльфов с MicroSD-флэшки. При этом я постараюсь объяснить всё максимально простым и доступным языком!

Недавно я познакомился с легендой форума allsiemens.ru — Ilya_ZX, который известен своим огромным вкладом в тему реверса и моддинга телефонов на платформе E-Gold и S-Gold. Илья поведал мне интересную историю о том, как в начале нулевых, будучи студентом, поспорил с одногруппником, сможет ли он добавить ‭‭«змейку‭‭» в свой Siemens A60. И спор он этот выиграл, путем бессонных ночей ковыряния прошивки в IDA Pro! Я подумал ‭‭— «а чем я хуже?‭‭». Взял в руки кнопочный телефон на платформе Spreadtrum, сдампил прошивку и загрузил в дизассемблер...

Если вам интересен подробный процесс реверса различных модулей прошивки, как они взаимодействуют между собой, как я написал программу для применения патчей к фуллфлэшу и, собственно, бинлоадер с первой программой — жду вас под катом!

❯ Предисловие

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

Поиск SKey и HASH в адресном пространстве телефона через уязвимость в Java-машине
Поиск SKey и HASH в адресном пространстве телефона через уязвимость в Java-машине

Но общими усилиями сообщество моддеров делало невозможное. Люди искали уязвимости и патчили загрузчики на телефонах Motorola для обхода проверки подписи RSA, резали тест-поинты и разбирались в BootROM'е процессоров S-Gold в телефонах Siemens, чтобы написать генератор BootKEY для возможности прошивки кастомов и немного ковыряли телефоны Samsung, где не только не было никакого секьюрбута, но ещё и прошивки утекали со всей информацией о символах (файлы .lst).

Razr V3i
Razr V3i

Но что самое интересное — эльф-сцена до сих пор живая и в профильных чатах уже повзрослевшие ребята до сих пор обсуждают то, как им ускорить порт эмулятора NES путем перемещения кода в IRAM, разогнать процессор Freescale Argon LV и... кто бы мог подумать — написать эмулятор периферии S-Gold для запуска прошивки Benq-Siemens E71 в QEMU. И хотя форумы по Siemens'ам уже давно не работают, MotoFan всё ещё жив и хранит кладезь полезной информации для моддеров и реверсеров!

Одним из таких парней был и @ILYA_ZX, который сделал большой вклад в моддинг-сцену телефонов Siemens. Например, именно благодаря его исследованиям звуковой подсистемы, в S65 и M65 добавили полноценную поддержку MP3, чего не смогла сделать даже сама Siemens. Когда я услышал его историю о том, как он на спор с одногруппником отреверсил и написал ‭‭«змейку‭‭» для своего Siemens A60, я сразу же вдохновился и понял... что нужно обязательно что-нибудь пореверсить и повторить успехи Ильи на какой-нибудь неисследованной платформе, причём желательно достаточно свежей, которую можно встретить в новых бюджетных кнопочниках...

❯ Первые шаги...

Я начал с поиска в своей коллекции телефонов цели для будущего моддинга. Одними из главных критериев были: относительно быстрая флэш-память для того, чтобы не поседеть в процессе заливки софта и поддержка прошивки через обычный USB без необходимости покупки отдельных кабелей и прошивочных боксов. У меня нашлись несколько телефонов на разных процессорах: MediaTek, Spreadtrum, а также Coolsand (похож на MTK и Spreadtrum, но MIPS, а не ARM). Я поочередно вычитывал с них прошивки с помощью специального сервисного софта, а затем ковырял их в дизассемблере и подбирал подходящую модель.

Моё внимание привлёк телефон Explay B240, который за пару дней до начала процесса мне подарил подписчик Павел, за что ему огромное спасибо.

После загрузки прошивки в IDA Pro, я сразу же полез смотреть строки и искать самые первые необходимые функции: printf, аллокатор динамической памяти, функции libc для работы со строками, а также ABI-функции по типу деления (в ARM аппаратного деления нет).

Большинство функций libc найти очень просто, если иметь представление об их оригинальных сигнатурах. Например, у аллокатора первый аргумент — всегда размер выделяемой памяти. Смотрим, что предполагаемой функции поступает на вход, если похоже на константный размер структуры от оператора sizeof — значит это скорее всего то, что нам нужно.

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

Это настоящий дар для реверсера!
Это настоящий дар для реверсера!

Изначально код после загрузки в дизассемблер выглядел странно: и тут и там указатели на несуществующую память, побитые данные и очень малое количество прямых референсов на ROM. И тут Илья взял фулл, поковырял его и сказал ‭‭— «да это ж Big-Endian, я нутром чую!‭‭». И как оказалось — действительно, телефон использовал BE порядок байт.

Что такое BE и LE?

Для тех, кто не в курсе — в мире компьютеров есть два варианта представления одного и того же многобайтового числа (то есть полуслова, слова, длинного слова): Big Endian и Little Endian. В Little Endian байты числа исчисляются от младшего к старшему, а в Big Endian — от старшего к младшему. Таким образом, если программа, например, захочет загрузить BMP-картинку, ей необходимо будет перевернуть порядок байт в каждом машинном слове заголовка, чтобы получить правильные данные о размере изображения.

Существует также сетевой порядок байт — это Big Endian, он нужен для унификации протокола общения между компьютерами разной архитектуры!

ARM умеет работать в обеих режимах, но до ARMv6 BE и LE аппаратно переключался в процессорном ядре на этапе синтеза или, например, внешним пином. Как раз таки из-за этого перед дизассемблирование ARM-прошивки необходимо сначала узнать её Endianness: например вместо LE-инструкции FE B5 в Thumb у нас будет B5 FE.

Для меня это стало неожиданностью, поскольку из примеров BE на телефонах я знал только легендарные Motorola. После этого я выяснил, что телефон работает на чипсете Spreadtrum SC6500L 2010 года выпуска, который представляет из себя:

  • Одно ядро ARM9EJ-S на частоте 208МГц в паре с DSP для обработки GSM-радиоканала.

  • 4МБ интегрированной оперативной памяти типа PSRAM и 4МБ NOR-памяти.

  • Контроллеры LCD-дисплеев и различной периферии, включая SPI, I2C, I2S и GPIO.

  • Встроенный контроллер питания вместе с модулем чарджера.

И это очень достойные для простого телефона характеристики. Такой чипсет может потянуть не только змейку или Java-игры, но даже эмуляторы ретро-консолей! И 4Мб оперативной памяти для этого хватит с головой. Перспективы дальнейшего моддинга уж точно были!

В реверс-инжиниринге полезно всё: промежуточные elf'ы с прошивкой (axf), таблица символов и тем более исходный код. В поисках слитых исходников прошивки, я наткнулся на архив для гораздо более свежего чипсета — SC6531 (который до сих пор используется в 90% кнопочных телефонов, которые сейчас можно купить в условном DNS до 2.000 рублей), и для общего понимания архитектуры принялся его изучать.

Поскольку кодовая база Spreadtrum тянется из нулевых, прошивка написана по ‭‭«эмбеддерски‭‭» олдскульно: весь код на Plain-C, практически везде глобальные переменные (для экономии RAM, т. к. флэшка поддерживает XIP и маппится в адресное пространство процессора напрямую, а также во избежание фрагментации), UI-построен на модели сообщений как в Windows — то есть, огромные свич-кейсы. Вкратце, архитектуру можно описать так:

  • В основе лежит RTOS ThreadX, которая также называется Nucleus. В задачи ОСРВ входит реализация вытесняющей многозадачности, включая примитивы синхронизации — мьютексы, семафоры, системного аллокатора, обработчика аппаратных исключений и некоторых других низкоуровневых подсистем.

    Nucleus также использовался в телефонах на процессорах MediaTek, Coolsand/RDA, Infineon (Siemens, Panasonic), Freescale (Motorola) и многих других.

  • Над RTOS реализованы драйверы для работы с железом. Дисплей, звук, коммуникация с DSP, клавиатура — всё это тоже низкоуровневые подсистемы.

  • Далее идёт UI-подсистема MMI — Man Machine Interface. MMI представляет из себя менеджер окон, служб (например воспроизведение музыки в фоне), GUI-фреймворк для построения интерфейса и апплетов — встроенных в телефон приложений, а также менеджер ресурсов. При этом MMI оперирует жестко-прописанными в прошивке набором окон, где каждая структура содержит строковой идентификатор и указатель на функцию-обработчик событий, что заметно упрощает реверс-инжиниринг этой части прошивки.

‭‭❯ «Угоняем‭‭» окно MMI

Для того, чтобы запустить код с внешнего носителя, необходимо сначала найти функции для работы с файловой системой и пропатчить уже существующую часть прошивки, дабы она могла вызывать наш код в ответ на какое либо действие. С функциями для работы с ФС проблем не возникло. Поскольку трейсов много, я практически сразу нашел необходимый минимум — SFS_OpenFile, SFS_GetFileSize, SFS_SetFilePointer/GetFilePointer, SFS_ReadFile/SFS_WriteFile и SFS_CloseFile.

На вход SFS_OpenFile принимает указатель wchar_t на строку с полным путем к файлу с учетом диска (C:/ — системное хранилище, D:/ — внутренняя память, E:/ — MicroSD), числовой идентификатор с режимом открытия файла и два дополнительных параметра для атрибутов.

Имейте ввиду, что на некоторых мобильных ОС работа с файлами только асинхронная и на коллбэках!

Реализация SFS_OpenFile
Реализация SFS_OpenFile

Как я уже говорил ранее, у каждого окна в системе есть функция для обработки сообщений — концепция такая же, как и WndProc на Windows. Если эту самую функцию пропатчить, можно сразу ‭‭«угнать‭‭» контекст MMI и использовать для того, чтобы писать свои собственные GUI-приложения. В качестве вектора атаки я решил использовать какое-нибудь не сильно нужное в повседневной жизни приложение. Например, встроенную игру ‭‭«Сокобан‭‭».

Улитка должна передвинуть ящики на место какашек
Улитка должна передвинуть ящики на место какашек

Поскольку реализация игры на моей версии прошивки значительно отличалась от той, что есть в исходном коде, то пришлось искать функцию ‭‭«по наитию‭‭». Сначала нашел функции для управления таймером подсветки, затем от неё несколько WndProc и анализировав одну из функций (в частности то, что она вызывает функции для движения персонажа, а вектор задается значениями -1 и 1 для X и Y), понял, что это скорее всего то, что мне нужно.

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

Момент заливки прошивки в телефон — самый рисковый, когда все 280 секунд процесса ты лихорадочно изучаешь листинг ассемблера патча в прошивке... чтобы обнаружить, что ты где-то упустил прибавление единицы к адресу функции, поскольку у тебя Thumb (инструкция BX/BLX изменяет режим процессора с ARM на Thumb, если в первом бите адреса функции единица, а в момент прыжка — устанавливает первый бит на ноль и получает таким образом корректный адрес), и получаешь ребут на ровном месте :)

И вот! Спустя несколько перепрошивок всё запустилось! Моей радости просто не было предела! Далее я немного усложнил патч и вызывал функции для работы с файловой системой, дабы понять, какие буквы ‭‭«диска‭‭» используются. Всё заработало и я получил файл "Privet5.txt"!

Первый патч!
Первый патч!

Поскольку вручную патчить прошивку неудобно, а Vi_Klay не хватает скриптинга, я написал свой редактор патчей с поддержкой С#. Скрипты автоматизируют выполнение многих руинных задач: ищут функции по паттернам, формируют таблицу функций и скрипт линкера, а также патчат фуллфлэш.


using System;
using System.IO;
using MonoPatcher.Scripting;
            
public static class Script
{
    public static int FindWindowHandlerFunction(byte[] firmware)
    {
        int offset = Patcher.PatternSearch(firmware, "B5 FE 1C 04 20 00 4B C2 25 01 33 A0", 0);

        return offset + 2;
    }

    /* Patch description: Replace file association from .txt to .app to make possible hooking EBook with our code */
    public static void PatchFileAssociation(FileStream strm, byte[] firmware)
    {
        int offset = Patcher.PatternSearch(firmware, "01 00 00 00 74 78 74 00");
        byte[] ext = { (byte)'a', (byte)'p', (byte)'p' };

        if(offset == -1)
        {
            Patcher.Log.WriteError("Failed to apply file-extension patch");
            
            return;
        }

        Patcher.Patch(strm, offset + 4, ext);
    }

    /* Patch description: Hook file manager */
    public static int FindFileManagerFunction(byte[] firmware)
    {
        int offset = Patcher.PatternSearch(firmware, "B5 7F 1c 15 AA 08 1C 0C", 0);

        return offset;
    }

    public static void Run()
    {
        string baseDir = "D:/windows-arm-none-eabi-master/bin/fasolim/";

        byte[] firmware = File.ReadAllBytes(baseDir + "firmware.bin");
        Patcher.CopyFile(baseDir + "firmware.bin", baseDir + "patched.bin");

        if(!File.Exists(baseDir + "bin/binloader.bin"))
        {
            Patcher.Log.WriteLine("binloader.bin does not exist");
            
            return;
        }

        byte[] binloader = File.ReadAllBytes(baseDir + "bin/binloader.bin");

        using(FileStream strm = File.OpenWrite(baseDir + "patched.bin"))
        {
            
            Patcher.Log.WriteLine("Patching game window handler function..."); 
            int handlerOffset = FindWindowHandlerFunction(firmware);
            int fmOffset = FindFileManagerFunction(firmware);

            if(handlerOffset == -1)
            {
                Patcher.Log.WriteError("Window handler function not found");
            
                return;
            }

            if(fmOffset == -1)
            {
                Patcher.Log.WriteError("FileManager function not found");
   
                return;
            }

            //Patcher.Log.WriteLine(string.Format("P{0:X}", handlerOffset));

            long firmwareEnd = strm.Length;
            //Patcher.Append(strm, binloader);

            if(firmwareEnd % 4 != 0)
            {
                Patcher.Log.WriteLine("Please align fullflash to border of 4");
            
                return;
            }

            // Apply skip boot animation patch
            //byte[] skipAnim = File.ReadAllBytes(baseDir + "patches/nopoweronanim.bin");
            Patcher.Patch(strm, 0x252FE8, baseDir + "bin/nopoweronanim.bin");
            Patcher.InsertNOP(strm, 0x9DC3C4); // Alignment
            Patcher.Patch(strm, 0x9DC3C4, baseDir + "bin/fmpatch.bin");

            PatchFileAssociation(strm, firmware);
            Patcher.InsertNOP(strm, handlerOffset - 2); // Alignment
            Patcher.Log.WriteLine("Function address: {0:X}", handlerOffset);
            Patcher.Patch(strm, handlerOffset, binloader);

            //Patcher.HookFunction(strm, handlerOffset, (int)firmwareEnd | 1, true); // Remember about THUMB!
        }
    }
}

        

❯ Разбираемся в подсистемах телефона

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

За открытие файлов отвечает функция MMIAPIFMM_OpenFile, которая получает из расширения его внутренний числовой тип. Сначала я думал что у менеджера файлов есть ассоциация расширений с MIME-типами и ассоциативный массив с обработчиками для разных типов файлов, но как оказалось, здесь у нас был большой свич-кейс, что одновременно и плохо с точки зрения красоты и производительности кода, и хорошо для реверс-инжиниринга (есть прямые референсы на функции).

PUBLIC void MMIAPIFMM_OpenFile(wchar *full_path_name_ptr)
{
    uint16              full_path_name_len                        = 0;
    uint16              suffix_len                                = MMIFMM_FILENAME_LEN;
    wchar              *suffix_wstr_ptr                           = PNULL;
    MMIFMM_FILE_TYPE_E  file_type                                 = MMIFMM_FILE_TYPE_NORMAL;
    MMIFILE_FILE_INFO_T file_info                                 = {0};

    full_path_name_len = MMIAPICOM_Wstrlen(full_path_name_ptr);

    //SCI_TRACE_LOW:"MMIAPIFMM_OpenFile Enter"
    SCI_TRACE_ID(TRACE_TOOL_CONVERT,MMIFMM_WINTAB_13453_112_2_18_2_21_3_559,(uint8*)"");

    if (0 == full_path_name_len)
    {
        //SCI_TRACE_LOW:"MMIAPIFMM_OpenFile, file name is null"
        SCI_TRACE_ID(TRACE_TOOL_CONVERT,MMIFMM_WINTAB_13457_112_2_18_2_21_3_560,(uint8*)"");
        return;
    }

    MMIAPICOM_WstrTraceOut(full_path_name_ptr, full_path_name_len * sizeof(wchar));

    if (MMIAPIUDISK_UdiskIsRun()) //U盘使用中
    {
        MMIPUB_OpenAlertWarningWin(TXT_COMMON_UDISK_USING);
        return;
    }

    if (MMIAPIFMM_GetFileInfoFormFullPath(full_path_name_ptr, full_path_name_len, &file_info))
    {
        suffix_wstr_ptr = SCI_ALLOCA((MMIFMM_FILENAME_LEN + 1) * sizeof(wchar));
        if (PNULL == suffix_wstr_ptr)
        {
            //SCI_TRACE_LOW:"MMIAPIFMM_OpenFile Fail, no memory"
            SCI_TRACE_ID(TRACE_TOOL_CONVERT,MMIFMM_WINTAB_13474_112_2_18_2_21_3_561,(uint8*)"");
            return;
        }

         SCI_MEMSET(suffix_wstr_ptr, 0x00, (MMIFMM_FILENAME_LEN + 1) * sizeof(wchar));

        MMIAPIFMM_SplitFileName(file_info.file_name, file_info.file_name_len, PNULL, PNULL, suffix_wstr_ptr, &suffix_len);

        file_type = MMIAPIFMM_ConvertFileType(suffix_wstr_ptr, suffix_len);
        
#if defined(DRM_SUPPORT)
            //  如果是DRM文件,进一步分析是何种媒体文件   
            {
                DRM_PERMISSION_MODE_E drm_permission = DRM_PERMISSION_NONE;
                DRMFILE_PRE_CHECK_STATUS_E pre_check_drmfile_status = DRMFILE_PRE_CHECK_NORMAL;
                
                if (MMIFMM_FILE_TYPE_DRM == file_type)
                {
//                  FmmCombineFullFileName(&s_fmm_list_data,&s_fmm_current_path,index,s_full_file_name,MMIFMM_FULL_FILENAME_LEN);			
                    file_type = MMIAPIDRM_GetMediaFileType(SFS_INVALID_HANDLE, full_path_name_ptr);

                    switch(file_type)
                    {
                    case MMIFMM_FILE_TYPE_PICTURE:
                    case  MMIFMM_FILE_TYPE_EBOOK:
                        drm_permission = DRM_PERMISSION_DISPLAY;
                        break;
                        
                    case MMIFMM_FILE_TYPE_MUSIC:
                    case MMIFMM_FILE_TYPE_MOVIE:
                        drm_permission = DRM_PERMISSION_PLAY;
                        break;                   
                        
                    case MMIFMM_FILE_TYPE_JAVA:
                        drm_permission = DRM_PERMISSION_EXECUTE;
                        break;
                        
                    default:
                        break;
                    }
                    
                    if (DRM_PERMISSION_NONE == drm_permission)
                    {
                        MMIPUB_OpenAlertWarningWin(TXT_COMMON_NO_SUPPORT);
                        return;
                    }
                
                    pre_check_drmfile_status = MMIAPIDRM_PreCheckFileStatus(full_path_name_ptr, drm_permission);
                    if (DRMFILE_PRE_CHECK_NORMAL != pre_check_drmfile_status)
                    {
                        if (DRMFILE_PRE_CHECK_NO_RIGHTS == pre_check_drmfile_status)
                        {
                            //如果是无效的,则需要提示guilist去刷新本行   
//                          MMIPUB_OpenAlertWarningWin(TXT_DRM_COPYRIGHTS_PROTECTION_NOT_OPERATE);
//                          MMIAPIFMM_UpdateListIconData(ctrl_id, index, list_data_ptr->pathname, s_full_file_name);
                        }
                        
                        return;
                    }
                }
            }
#endif

        switch(file_type)
        {
        case MMIFMM_FILE_TYPE_PICTURE:
            {
                MMIAPIFMM_PreviewPicture(full_path_name_ptr);
            }
            break;
#ifdef MMI_AUDIO_PLAYER_SUPPORT
        case MMIFMM_FILE_TYPE_MUSIC:
            {
                MMIAPIMP3_PlayFile(full_path_name_ptr, (const uint32)full_path_name_len);
            }
            break;
#endif

#ifdef VIDEO_PLAYER_SUPPORT
        case MMIFMM_FILE_TYPE_MOVIE:
            {
#ifdef MMI_VIDEOPLAYER_MINI_FUNCTION
                MMIAPIVP_MiniFunction_PlayVideo(full_path_name_ptr,full_path_name_len);
#else
                MMIAPIFMM_PreviewVideo(full_path_name_ptr);
#endif
            }
            break;
#endif

#ifdef EBOOK_SUPPORT
        case MMIFMM_FILE_TYPE_EBOOK:
            {
                MMIFMM_ShowTxtContent(full_path_name_ptr);
            }
            break;
#endif
#if defined MMI_VCARD_SUPPORT
        case MMIFMM_FILE_TYPE_VCARD:
            {
                //MMIPB_ReadVCardFile(full_path_name_ptr);
                MMIFMM_ShowTxtContent(full_path_name_ptr);
            }
            break;
#endif
        case MMIFMM_FILE_TYPE_JAVA:
            {
#ifdef JAVA_SUPPORT_IA
                MMIAPIJAVA_InstallFromFilesystem(full_path_name_ptr, full_path_name_len);
#elif defined (JAVA_SUPPORT_MYRIAD)
                MMIAPIJAVA_Install(full_path_name_ptr, full_path_name_len);                        
#endif
            }
            break;
        default:
            {
                MMIPUB_OpenAlertWarningWin(TXT_COMMON_NO_SUPPORT);
            }
            break;
        }

        SCI_FREE(suffix_wstr_ptr);
    }
    else
    {
        MMIPUB_OpenAlertWarningWin(TXT_COM_FILE_NO_EXIST);
    }
}

В телефоне есть читалка электронных книг, но пользы от неё немного — кодировок поддерживает мало, выглядит невзрачно. Если захотим, то сами напишем эльф для чтения книг в .txt. Разработчики прошивки очень удачно написали функцию MMIFMM_ShowTxtContent, куда передается указатель на полный путь к нашему файлу, а значит, именно её мы и будем с вами хукать... но сначала сменим ассоциацию файлов с txt на app:

/* Patch description: Replace file association from .txt to .app to make possible hooking EBook with our code */
    public static void PatchFileAssociation(FileStream strm, byte[] firmware)
    {
        int offset = Patcher.PatternSearch(firmware, "01 00 00 00 74 78 74 00");
        byte[] ext = { (byte)'a', (byte)'p', (byte)'p' };

        if(offset == -1)
        {
            Patcher.Log.WriteError("Failed to apply file-extension patch");
            
            return;
        }

        Patcher.Patch(strm, offset + 4, ext);
    }

Суть хука простая: мы ‭‭«воруем‭‭» глобальную переменную (массив символов) у какой-то другой, неактивной в данный момент программы и храним в ней строку с путём к нашему эльфу, а затем запускаем окно хукнутой игры. Эльфлоадер стартует, берёт указатель на программу и загружает её, перенаправляя все события ей. Такой вот незамысловатый хук:

#include <api.h>

#define PATH_VARIABLE 0x46F9224 //0x46C37F0

// TODO: Make this patch more portable. Now it require manual porting for new platforms.
#define RUN_BOXMAN_GAME_PTR 0x6EA9E4
#define PATH_MAX 255

#define HEAP_BASE 0x212431C7

#define _Alloc(...) ((void*(*)( unsigned int size, unsigned int heap, char* where, unsigned int lineNumber )) 0x0043E2BC + 1)(__VA_ARGS__)

void MMIAPIEBOOK_ManagerWinMsg_4Fmm(uint8 file_dev, wchar_t* name_ptr, uint32 name_length, uint32 file_size, wchar_t* full_name_ptr, uint32 full_name_length)
{
	wchar_t* filePath = (wchar_t*)PATH_VARIABLE;
	uint32 written;
	
	int len = wstrlen(full_name_ptr) + 1;
	
	for(int i = 0; i < len; i++)
		filePath[i] = full_name_ptr[i];
	
	((void(*)()) RUN_BOXMAN_GAME_PTR + 1)(); // TODO: Pattern search of this function (it's thunk at this moment).  
}

В процессе реверса функций для открытия окон в прошивке я нашел скрытое меню... с дополнительной игрой, которая есть в прошивке, но штатными способами до неё невозможно добраться!

Далее я адаптировал бинлоадер на новый лад и по итогу у меня всё заработало...

...но до получения результата мне пришлось два дня подряд не спать всю ночь и сидеть до 5 утра ;)

/*
*
*	Spreadtrum binloader
*
*	©2025 Bogdan Nikolaev. All rights reserved.
*
*	Special thanks to Ilya_ZX
*/

// Binloader uses reduced, statically linked with binary function table
#include <api.h>

#define DISK_SYSTEM u"D:/"
#define DISK_CARD u"E:/"

// We hijack global variable from web browser.
#define LOAD_ADDRESS_VARIABLE 0x46F9224 // 0x46C37F0
#define STATE_VARIABLE 0x46C37F4

#define STATE_NUMBER 0xCAFEBABE

#define CreateDebugFile(str) FileClose(FileOpen(str, FILE_CREATE, 0, 0));

int HandleBoxmanWinMsgHook(uint32 window, uint32 msgId, uint32 dparam)
{
	uint32 readBytes = 0;
	uint32 handle;
	
	void** loadAddr = (void**)LOAD_ADDRESS_VARIABLE; // Also filemanager put absolute path to binary here
	unsigned int* stateVariable = (unsigned int*)STATE_VARIABLE;
	
	if(msgId == MSG_CLOSE_WINDOW || msgId == MSG_KEYDOWN_CANCEL || msgId == MSG_CTL_CLOSE)
	{
		MMKCloseWin(window);
		*stateVariable = 0;
	}
	
	// FIT IN 294 BYTES!!!
	if(*stateVariable != STATE_NUMBER)
	{
		// Initialization state: Load runtime from E:/rt.so to memory, store it's address into some global variable.
		wchar_t* str = (wchar_t*)loadAddr;
		
		handle = FileOpen(str, 0x31, 0, 0);
		
		if(!handle)
			goto err;
		
		uint32 size = 0;
		FileGetSize(handle, &size);
		*loadAddr = Alloc(size, "m", 1);
		if(!(*loadAddr))
			goto err;
		
		FileRead(handle, *loadAddr, size, &readBytes);
		
		if(readBytes == 0)
			goto err;
		
		*stateVariable = STATE_NUMBER;
	}
	else
	{
		// Program state: MMI keep sending our hooked function events, we pass them directly to loaded program.
		// The program can also pass execution to another program by swapping WindowFunc with pointer to loaded program.
		LoaderContext ctx = {
			__api_table,
			loadAddr
		};
		WindowFunc func = (WindowFunc)(*loadAddr + 1); // Beware of THUMB
		
		func(&ctx, window, msgId, dparam);
	}
	
	return 1;
err:
	CreateDebugFile(u"D:/E");
	return 1;
}

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

И залил экран желтым цветом:

#include <api.h>

void LcdClear()
{
	LcdId lcd = { 0, 0 };
	Rect rct = { 0, 0, 240, 320 };
	
	uint16* fb = ((uint16*(*)(LcdId* id)) 0x321DEA + 1)(&lcd);

	uint16 startEnd[4] = { 0, 0, 240, 320 };

	((void(*)(LcdId* lcdId, uint32 start, uint32 end, uint16 col)) 0x9701C4 + 1)(&lcd, ((uint32*)&startEnd[0])[0], ((uint32*)&startEnd[0])[1], 0xFFFF);
	
	for(int i = 0; i < 240 * 320; i++)
		fb[i] = 0xFF00;
	
	((void(*)()) 0x966378 + 1)(); // Update rect

	
	
	//((void(*)(LcdId* lcdId, Rect* rct, void* res)) 0x9662F2 + 1)(&lcd, &rct, 0); // Store update rect
}

__attribute__((section(".main")))
int WindowProc(LoaderContext* context, int window, int msgId, int dparam)
{
	LcdClear();
	
	// Send MSG
	((void(*)(uint32 window, uint32 msg, uint32 res)) 0x36A3CA + 1)(window, MSG_FULL_PAINT, 0);
	
	return 1;
}

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

public static ImportedFunction[] Functions = new ImportedFunction[]{
        // File IO
        new ImportedFunction("Alloc", "B5 F7 1C 07 25 00 37 19 B0 82", "void*", "unsigned int size, char* where, unsigned int lineNumber"),
        new ImportedFunction("wstrlen", "1C 01 D1 00 47 70 88 0A", "uint32", "wchar_t* str"),
        new ImportedFunction("FileOpen", "B5 FE 1C 05 09 08", "uint32", "wchar_t* fileName, uint32 accessMode, uint32 shareMode, uint32 fileAttributes"),
        new ImportedFunction("FileRead", "B5 FF 1C 06 1C 17 1C 1D B0 85 9C 0E 21 00 A0 86 F7 FF F8 2F 1C 23", "uint32", "uint32 handle, void* buffer, uint32 bytesToRead, uint32* bytesRead"), // FileRead as well as FileWrite are similiar due to identical arguments
        new ImportedFunction("FileWrite", "B5 FF 1C 06 1C 17 1C 1D B0 85 9C 0E 21 00 A0 8D F7 FF F8 09 1C 23", "uint32", "uint32 handle, void* buffer, uint32 bytesToWrite, uint32* bytesWritten"),
        new ImportedFunction("FileClose", "B5 10 1C 04 A0 8A 21", "uint32", "uint32 fileHandle"),
        new ImportedFunction("FileGetSize", "B5 B0 1C 05 1C 0C 21 00", "uint32", "uint32 fileHandle, uint32* fileSize"),
        new ImportedFunction("MMKCloseWin", "B5 70 25 00 F1 A7", "uint32", "uint32 windowHandle"),

        /*new ImportedFunction("TurnOffBacklight", "49 1D B5 10 20 02 60 C8", "void", "uint32 value"),
        new ImportedFunction("AllowTurnOffBacklight", "B5 F1 B0 92 24 00 94 11", "void", "uint32 value"),
        new ImportedFunction("SetKeypadBacklight", "B5 10 1C 04 1C 01 A0 F4", "void", "uint32 value"),
        new ImportedFunction("AllowBacklight", "B5 B0 1C 04 1C 02 48 BF 4D A5", "void", "uint32 value")*/
     };
#ifdef LOADER
__attribute__((section(".text")))
void* __api_table[] = {
(void*)(0x90FEF8 | 1), // Alloc
(void*)(0x92DEAC | 1), // wstrlen
(void*)(0x9D41AE | 1), // FileOpen
(void*)(0x9D4CD2 | 1), // FileRead
(void*)(0x9D4D1E | 1), // FileWrite
(void*)(0x9D4CA4 | 1), // FileClose
(void*)(0x9D509C | 1), // FileGetSize
(void*)(0x981242 | 1), // MMKCloseWin
};
#endif

// _addr defines needed only for patches to make them portable
#define Alloc_addr 0x90FEF8
#define Allocsig unsigned int size, char* where, unsigned int lineNumber
#ifndef PATCH
#define Alloc(...) ((void*(*)( Allocsig )) __api_table[0])(__VA_ARGS__)
#else
#define Alloc(...) ((void*(*)( Allocsig )) 0x90FEF8 + 1)(__VA_ARGS__)
#endif

Саму таблицу функций можно расположить в конце прошивки или в теле какой-нибудь BMP-картинки... Например так делали с телефонами Motorola:

❯ Заключение

Вот такой программный моддинг у нас с вами получился. Надеюсь, вам было интересно! На самом деле ничего сложного в такой модификации нет: у меня были на руках не совсем актуальные, но всё же исходники, а прошивка была собрана в дебаге и в ней было достаточно строк для подробного анализа. Более опытные реверсеры умудряются раскапывать прошивки с куда меньшим количеством документации и без дебаггера, а это значит, что есть куда расти!

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

А если вам интересна тематика ремонта, моддинга и программирования для гаджетов прошлых лет — подписывайтесь на мой Telegram-канал ‭«Клуб фанатов балдежа‭», куда я выкладываю бэкстейджи статей, ссылки на новые статьи и видео, а также иногда выкладываю полезные посты и щитпостю. А ролики (не всегда дублирующие статью) можно найти на моём YouTube канале.

Отдельное спасибо: @ILYA_ZX и @Andy51 за мотивацию, @Azq2и @EXL за советы, а также авторам IDA Pro и Ghidra за крутые инструменты! Без вас этой статьи бы не вышло.

Важно: друзья! Я уверен, что статью будут читать выходцы с форумов моддеров и возможно даже ребята, связанные с прошивочными боксами. Если у вас есть исходный код или объектные файлы для телефонов Siemens (S-Gold или E-Gold — не имеет значения) и вы хотели бы помочь общему моддерскому делу — напишите пожалуйста мне в Telegram. Несмотря на то, что этот код уже давно никому не нужен и E-Gold/S-Gold уже более 15 лет снят с производства, гарантирую полную анонимность и крутой контент :)

Очень важно! Разыскиваются девайсы для будущих статей!

Друзья! Если вам понравилась сегодняшняя статья про разработку эльфов, то спешу объявить: для подготовки будущих материалов с разработкой самопальных игрушек под необычные устройства, объявляется розыск телефонов и консолей! В 2000-х годах, китайцы часто делали дешевые телефоны с игровым уклоном — обычно у них было подобие геймпада (джойстика) или хотя бы две кнопки с верхней части устройства, выполняющие функцию A/B, а также предустановлены эмуляторы NES/Sega. Фишка в том, что на таких телефонах можно выполнять нативный код и портировать на них новые эмуляторы, чем я сейчас занимаюсь, а затем написать об этом подробную статью и записать видео! Если у вас есть телефон подобного формата и вы готовы его задонатить или продать, пожалуйста напишите мне в Telegram (@monobogdan) или в комментарии. Также интересуют смартфоны-консоли на Android (на рынке РФ точно была Func Much-01), там будет контент чуточку другого формата :)

А также я ищу старые (2010-2014) подделки на брендовые смартфоны Samsung, Apple и т. п. Они зачастую работают на весьма интересных чипсетах и поддаются хорошему моддингу, парочку статей уже вышло, но у меня ещё есть идеи по их моддингу! Также может у кого-то остались самые первые смартфоны Xiaomi (серии Mi), Meizu (ещё на Exynos) или телефоны на Linux (например Motorola EM30, RAZR V8, ROKR Z6, ROKR E2, ROKR E6, ZINE ZN5 и т. п., о них я хотел бы подготовить специальную статью и видео т. к. на самом деле они работали на очень мощных для своих лет процессорах, поддавались серьезному моддингу и были способны запустить даже Quake!). Всем большое спасибо за донаты!

А ещё я держу все свои мобилы в одной корзине при себе (в смысле, все проекты у одного облачного провайдера) — Timeweb. Потому нагло рекомендую то, чем пользуюсь сам — вэлкам:

Новости, обзоры продуктов и конкурсы от команды Timeweb.Cloud — в нашем Telegram-канале 

Опробовать ↩

Перед оплатой в разделе «Бонусы и промокоды» в панели управления активируйте промокод и получите кэшбэк на баланс.

Комментарии (68)


  1. bodyawm Автор
    24.05.2025 14:07

    Друзья, наработки по бинлоадеру доступны здесь:
    https://github.com/monobogdan/spreadtrum-binloader

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

    Если кому-то нужна будет база в IDA Pro - пишите в ЛС, поделюсь.


    1. bodyawm Автор
      24.05.2025 14:07

      Также мне читатели и зрители надонатили денюжку, а я решил заказать на них НОВЫЕ бюджетные кнопочники с интересным, по моему мнению, дизайном. Все они работают на базе SC6531DA и конечно мы с @ILYA_ZX будем ковырять. Илья написал распаковщик сжатых LZMA областей в прошивке, а я мечтаю систематизировать паттерны самых необходимых функций и написать УНИВЕРСАЛЬНЫЙ патчер, которому на вход поступает прошивку от любого бюджетного кнопочника из DNS и на выходе будет уже готовая, пропатченная прошивка, способная запускать произвольные эльфы!

      Скрытый текст


      1. bodyawm Автор
        24.05.2025 14:07

        А скоро мы с вами в рамках статьи вскроем коробочку, которая с 2004 года лежит запечатанная.. Кто догадается что в ней? :)


        1. MaFrance351
          24.05.2025 14:07

          Какая-то мобила из двухтысячных, с MP3, двумя симками и телевизором? Или ещё один телефон-консоль?


          1. bodyawm Автор
            24.05.2025 14:07

            Не телефон. Устройство на Linux, сверху коробки есть намек


            1. vesowoma
              24.05.2025 14:07

              Какой-то КПК наверное... Случайно не тот, где экран можно по разному поворачивать?


              1. bodyawm Автор
                24.05.2025 14:07

                Тот


        1. DingoTM
          24.05.2025 14:07

          1. bodyawm Автор
            24.05.2025 14:07

            Верно)


            1. MaFrance351
              24.05.2025 14:07

              О. Крутое пополнение!


          1. noncinque
            24.05.2025 14:07

            Какой симпатичный!


        1. ququnta
          24.05.2025 14:07

          кверти-слайдер а-ля нокла е7 или n950


      1. strvv
        24.05.2025 14:07

        Добрый день, Богдан.
        А если взять более древний арм - типа TI Calipso, ARM4TDMI?
        Осмоком - есть, но может другие есть исходники?
        моторолок было много упрощенных.


        1. bodyawm Автор
          24.05.2025 14:07

          На осмокомах MMI разный же


  1. Moog_Prodigy
    24.05.2025 14:07

    Я все жду статьи, когда можно будет не только на любом кнопочнике запускать эльфы, но и использовать его как одноплатник.


    1. bodyawm Автор
      24.05.2025 14:07

      С разработкой бинлоадера такая возможность уже есть. Найти функции прошивки для отправки данных в UART не не составит труда, а через UART можно общаться с микроконтроллером, который будет выполнять мост между процессором и GPIO :)


    1. bodyawm Автор
      24.05.2025 14:07

      И похожая статья уже выходила, там мы рассматривали готовые рантаймы:

      https://habr.com/ru/companies/timeweb/articles/791072/


    1. lv333
      24.05.2025 14:07

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

      Когда прочитал про то что недавно наконец-то сделали возможность запускать эльфы на с380, с650 - всплакнул даже, но потом вспомнил какой сейчас год на календаре... Как говорится - дорога ложка к обеду! Хотя может и откопаю свою с380, если она заведется и у меня будет подходящее настроение, может и вспомню как это было 20 лет назад...


      1. bodyawm Автор
        24.05.2025 14:07

        В есп32 не будет дисплея и такого количества памяти)


        1. lv333
          24.05.2025 14:07

          На алике есть куча готовых полуфабрикатов с экранами, разъемом для сд карты и даже ОЗУ целых 8мб! :) А ещё с гпс, лорой и так далее. Даже практически готовые устройства есть с е-инк и тачскрином, есть с кнопками. Ну или б.у. смартфон за копейки можно взять, короче вариантов тьма, не то что было 20 лет назад конечно. Так что в общем и целом это ковыряние сейчас имеет очень мало какого то прям практического смысла. Ни разу пытаюсь принизить саму проведенную работу, это реально круто.


          1. Sun-ami
            24.05.2025 14:07

            Недостаток б/у смартфона в том, что их сложно найти даже десяток одинаковых, а тем более больше, а значить мелкосерийное изделие на них не сделать. А полуфабрикаты с экранами и 8мб ОЗУ стоят заметно дороже кнопочных телефонов. И в них как правило нет GSM, а он тоже может быть полезен.


            1. lv333
              24.05.2025 14:07

              Найти десяток смартфонов одного производителя и одной модели для вашего мелкосерийного изделия, вполне посильная задача, но тут даже это не нужно, достаточно брать +/- одного поколения, с относительно схожим железом и с +/- одной версией андроида, причем все это в довольно широких пределах. А наличие унифицированной ос, апи - гарантирует работу одного и того же приложения на всем этом разнообразии устройств. В том то и прелесть унифицированной ос в отличии от написания кода на голом железе, там да шаг в право, шаг в лево и все уже все поплыло или вообще окирпичило железку.


              1. lv333
                24.05.2025 14:07

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


                1. MaFrance351
                  24.05.2025 14:07

                  У этих решений плюс в том, что десяток таких телефонов можно найти дешевле, чем вот такой набор на ESP. Можно, например, сделать какой-нибудь пульт управления с расчётом на то, что если разобьют или потеряют - не особо жалко.


                  1. strvv
                    24.05.2025 14:07

                    И если взять армейское применение, США в 00-е приняли, ибо могли такое соорудить, для своих систем тактического звена C4ISR - ниже роты шли обычные тогда лопатники самсунги, только не с типовой прошивкой. Массовое железо, дешевле некуда.
                    Сломал, пролюбил - выдали новую, ключ ид пользователя зашили, старый - бан в сети.
                    Как на такое решение облизывались разработчики в СНГ.


                1. Nick0las
                  24.05.2025 14:07

                  Айфоны это супермассовая модель, потому что в один год все любители яблока покупают какой-то условный айфон 6/7/8 .. и они расходятся миллионами. А с китайскими девайсами не так. Их меньше было выпущено раз, после старения к ним относятся как к мусору два, и третье, самое главное - несколько устройств с одинаковым названием от производителя могут иметь сильно разные аппаратные ревизии и разные запчасти.


                  1. lv333
                    24.05.2025 14:07

                    Ну поэтому я и вспомнил про айфоны, полностью идентичное железо и софт, а цена на устаревшие модели очень низкая. Даже если использовать чисто по прямому назначению, как звонилку, то лучше уж взять какой нить старенький айфон в хорошем состоянии чем новенький китайский кнопочник. А уж для всяких самоделок и подавно.


                    1. MaFrance351
                      24.05.2025 14:07

                      Да и в принципе какой-то топ или средний сегмент нулевых в хорошем состоянии сейчас будет при схожей цене лучше, чем что-то бюджетное сейчас. Что по качеству изготовления, что по возможностям.


              1. Sun-ami
                24.05.2025 14:07

                Мелкосерийное изделие - это не только электроника, но и корпус. А корпус для разной электронной начинки или разных моделей телефонов, которые в него будут встраиваться, нужен разный. Десяток может и можно найти, а 50, 100? Кнопочные телефоны на Spreadtrum можно купить от $12, хоть сотню, хоть две.


          1. kenomimi
            24.05.2025 14:07

            На готовых поделках с esp32 своих подводных камней как грязи...

            Но в целом да - сейчас есть какой-нибудь luckfox, milk-v duo или hi-link, делающие очень мелкие, но паябельные дома SoM, не надо морочить голову разводкой сложных многослоек. Причем там есть полный sdk c с линуксом. Есть Simcom, у коорого навалом сотовых модулей, 2G по баксу на али лежат, 4G пятнаху стоят. Экранов ваще навалом, и хороших, и плохих, и даже круглых. Корпуса на фотополимернике самого днищевого уровня получаются как заводские. Бери и запиливай свой кнопочный телефон с блекджеком и змейкой... Всё есть в модулях, причем если раньше это были корявые оргомные поделки для ардуино, то сейчас полно и приличных мелких SoM, которые не стыдно в прод ставить.

            Единственное, ради чего стоит ломать старые телефоны - спортивный интерес. Это реально занимательно, пусть и не очень-то полезно в глазах окружающих.


            1. MaFrance351
              24.05.2025 14:07

              Единственное, ради чего стоит ломать старые телефоны - спортивный интерес. Это реально занимательно, пусть и не очень-то полезно в глазах окружающих.

              Иногда в процессе такого ковыряния обнаруживается кое-что интересное...


              1. lv333
                24.05.2025 14:07

                Зато дешёвые телефоны! Которых можно набрать мешок по рублю и внедрить в свои проджекты!:)) Как тут выше @Sun-amiсоветует... А потом доказывай что верблюд не ты...


                1. Sun-ami
                  24.05.2025 14:07

                  Я никому ничего не советую, я говорю, что доступность серийно выпускаемых до сих пор кнопочных телефонов для запуска своих бинарных программ даёт новые возможности. А пользоваться ими или нет - каждый решает сам. Если опасаетесь бэкдоров и троянов - не вставляйте SIM-карту и не используйте сотовую связь. Или найдите и удалите их из системы. Или используйте проверенный кем-то на отсутствие троянов и бэкдоров телефон - есть разные возможности.


          1. slog2
            24.05.2025 14:07

            Подскажите волшебное слово, как найти на алике эти полуфабрикаты.


            1. lv333
              24.05.2025 14:07

              esp32 display, esp32 e-ink, esp32 lora, esp32 sim module и так далее и тому подобное... :)


      1. MaFrance351
        24.05.2025 14:07

        И эти люди в целом будут даже по своему правы, а зачем собственно?

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


        1. bodyawm Автор
          24.05.2025 14:07

          Именно в этом и прикол) А еще есть GSM, так что можно намутить что-нибудь полезное сигнализационное)


          1. MaFrance351
            24.05.2025 14:07

            Сразу вспомнилось вот такое:

            Это такая приблуда, Spy-Tel называется. Туда втыкается Nokia 3310, которая может контролировать несколько шлейфов сигнализации.

            А со своей прошивкой можно сделать что-то подобное, только компактное и дешёвое...


            1. Nick0las
              24.05.2025 14:07

              Например некто Sabodyn сделал для Siemens C45 и C55 патч Simpage который превращает телефон в охранную сигнализацию. Патч был в бесплатном варианте на один шлейф и в платном на два. Архитектурно патч построен на отправке AT команд из кода патча в обработчик команд в телефоне. Подробнее тут: https://web.archive.org/web/20070128001333/http://www.webcenter.ru/~kat/SimPage.html
              Если что у меня сохранился патч и pdf к нему.

              А вот использовать отправку AT на S/ME45i не полкчилось, там обработчик не работал пока кабель не подключишь. Я покопался немного но так обход и не нашел.


      1. ILYA_ZX
        24.05.2025 14:07

        Хобби. Купил телефон, BQ3587, телефон понравился, основной минус - на мои bluetooth наушники заикается. Пришлось расковырять прошивку, поправил. Хотел отпуск провести на связи, без интернета. В итоге из 28 дней отпуска 3 провел на берегу озера, с допиленным телефоном) Телефон на Spreadtrum. Разбираться было интересно, отпуск не прошел даром, это к вопросу зачем. Электроника действительно нас разбаловала в плане выбора, я набрал кучу модулей/микросхем/FPGA, которые лежат и я более чем моргание диодом не сделал. ESP32 там же, руки не доходят проверить возможности и производительность.


        1. Nick0las
          24.05.2025 14:07

          Круто. Фикс BT кажется нетривиальной задачей, даже если иметь исходники. Возможно потому что у меня поверхностное представление о BT и A2DP.

          Электроника действительно нас разбаловала в плане выбора, я набрал кучу модулей/микросхем/FPGA, которые лежат и я более чем моргание диодом не сделал.

          Нужно иметь внятную цель чтобы что-то сделать. Вот есть у тебя плата с МК или FPGA и можешь ты на ней что-то сделать, на одной, на второй, на третьей - на любой. И если надо что-то делать делаешь на привычной. А вот если есть конкретный девайс и в него надо что-то добавить, то тогда прийдется его изучить, возможно что-то отреверсить и добавить то, что тебе нужно.


      1. EXL
        24.05.2025 14:07

        Откопайте обязательно, даже прошивка новая с эльфпаком для Motorola C380, C650, V180, V220 есть. Носталгия на пару вечеров обеспечена (:

        Motorola C380/C650/V180/V220 custom firmware
        Motorola C380/C650/V180/V220 custom firmware


    1. d1mk0
      24.05.2025 14:07

      Или использовать как пульт управления старшим братом-одноплатником без экрана и клавиатуры.


  1. Yuiko64
    24.05.2025 14:07

    Огонь статья, прочитала на 1 дыхании


    1. bodyawm Автор
      24.05.2025 14:07

      Спасибки) На этом еще не все, я просто не успел змейку дописать))

      Я возможно потом возьму интервью у @ILYA_ZX и @Andy51 если они захотят


  1. MaFrance351
    24.05.2025 14:07

    В процессе реверса функций для открытия окон в прошивке я нашел скрытое меню... с дополнительной игрой, которая есть в прошивке, но штатными способами до неё невозможно добраться!

    Прямо напомнило восьмибитные картриджи. Когда-то пару раз перемычками тоже находил "скрытые" игры.


    1. bodyawm Автор
      24.05.2025 14:07

      Интересно, много ли людей встаривали в картриджи переключатели, чтобы получить бесплатно еще пару игр?)


      1. MaFrance351
        24.05.2025 14:07

        Точно помню, как кто-то рассказывал, что проделывал такой трюк с тетрисом (Brick game из девяностых). Там в какой-то из бесчисленных модификаций при замыкании перемычек помимо тетриса появлялись гонки и ещё какая-то игра.


        1. vesowoma
          24.05.2025 14:07

          • Стрелялка наверное. У меня было несколько таких игрушек, но в основном позже, а в той что в студенческие годы купил, уже сразу было 96 или 99 игр. Вскрыл на 3 или 4 день, т.к. при включении оно орало мелодию, лекторов пугало ) пришлось доработать. Там уже без всяких перемычек и намеков на какие-то настройки.


          1. MaFrance351
            24.05.2025 14:07

            Либо арканоид, либо стрелялка.


      1. MaFrance351
        24.05.2025 14:07

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

        Вот этот экран "Address error" я помню хорошо. Тогда, правда, не знал, что это всё такое.


        1. bodyawm Автор
          24.05.2025 14:07

          Я только об этом узнал))


          1. MaFrance351
            24.05.2025 14:07

            Никогда не поздно вкатиться в разработку и под классические консоли...


    1. ILYA_ZX
      24.05.2025 14:07

      Эх, мне не новые игры не попадались. Список изменялся от 100 в одном к 10000 в одном, и появлялись интересные вариации игр)


      1. Nick0las
        24.05.2025 14:07

        И особенно весело было перебирать 10000 игр нажимая кнопку инкрементирующую счетчик и пытаться понять чем игра 2566 отличается от игры 3846.


  1. Eltaron
    24.05.2025 14:07

    Отличный детектив с хэппи-эндом!


    1. bodyawm Автор
      24.05.2025 14:07

      Спасибо


  1. StjarnornasFred
    24.05.2025 14:07

    Отличная статья, настоящая хабрагоднота! Отдельное спасибо за то, что был найден Spreadtrum SC6500L в полноценном (не монохромном) кнопочнике. Я-то думал, этот проц ни на что не годится.


  1. NutsUnderline
    24.05.2025 14:07

    я вот думаю что чуть побольше смысла было бы покопаться в платформах которые умеют 4g в них потенциала досточно чтобы реализовать несколько более актуальную времени годноту. сименсы и моторолы то ломали когда они были в широкой продаже? помню как давным давно мне показали чб simens на котором запустили че то wolfenstein подобное

    и отдельный момент - GSM ядро и протоколы, любопытно как это реализовано с точки зрения многопроцессорности и ОС


    1. lv333
      24.05.2025 14:07

      и отдельный момент - GSM ядро и протоколы, любопытно как это реализовано с точки зрения многопроцессорности и ОС

      Насколько я понял, это почти всегда отдельная вселенная с своим процессором и максимально огражденная от основного процессора и прошивки. Есть некоторые модели от Моторола, где получали доступ непосредственно к ПО модуля GSM, но там их если мне по изменяет память целых две штуки они весьма старые и их ещё надо поискать на вторичке. Зато при помощи этих телефонов и одноплатного компьютера можно реализовать к примеру свою GSM базовую станцию в режиме 2G.


      1. NutsUnderline
        24.05.2025 14:07

        это да поэтому и спрашиваю

        статьи про эти телефоны и свою базовую есть на Хабре


  1. Nick0las
    24.05.2025 14:07

    Статья интересная, ждем продолжение. Одна поправка - thumb включается нулевым битом а не первым.


    1. bodyawm Автор
      24.05.2025 14:07

      Намеренная очепятка для лучшего понимания))


  1. WRP
    24.05.2025 14:07

    Процессорный модуль для IDA взяли готовый или сами написали?


    1. bodyawm Автор
      24.05.2025 14:07

      Готовый, ARM там почти с самого начала


  1. Devastator82
    24.05.2025 14:07

    Спасибо за статью! Это именно то зачем я захожу на Хабр


  1. K_P_A_H
    24.05.2025 14:07

    Интересная статья. Мало что мне понятно, как неспециалисту. Но такая тема может быть актуальна для распространенных mp3 плееров. Прошивка у которых та ещё китайская недоделанная. А вот хорошая функциональность востребована, например, при изучении языков. Я уже думал, что может самому с помощью ИИ прошивку переписать.


    1. Nick0las
      24.05.2025 14:07

      Теме альтернативных прошивок для MP3 плееров примерно столько же лет сколько и теме патчей для телефонов. Гуглите по названию Rockbox. Впрочем я плееры не патчил, это друзья мои патчили.