eXTracted INternals

eXTracted INternals
 
ФорумФорум  ЧаВоЧаВо  ПоискПоиск  РегистрацияРегистрация  ПользователиПользователи  ГруппыГруппы  Вход  

Поделиться | 
 

 Кто не RISC'ует, тот не пьет шампанского...

Предыдущая тема Следующая тема Перейти вниз 
АвторСообщение
Hex

avatar

Количество сообщений : 397
Возраст : 35
Дата регистрации : 2006-07-12

СообщениеТема: Кто не RISC'ует, тот не пьет шампанского...   Сб 15 Дек - 10:24

Все больше и больше людей устремляется в реверсинг мобильных и embedded устройсв после реверсинга Win32 приложений. И не удивительно, что происходит это с огромными трудностями - уж очень люди застряют в архитектуре Windows и формате PE. В свое время я тоже прошел через такую "ломку", когда меня потянуло исследовать прошивки мобильных телефонов. Попытаюсь описать как стоит подходить к реверсингу RISC-платформ, чтобы потом не закричать "А это все херня! Как тут ваще можно что-то понять без дебагера?!"

Пример будет вполне реальный. Давно хотел посмотреть, что собой преставляет мой спутниковый ресивер Skyon DSR-2800.
Перед тем как лезть в Иду, надо узнать что за железо в нем стоит. Раскручивать я его не стал, потому что он на гарантии еще. В инете всегда есть куча народу которые сделали это уже до нас Smile Да и есть тематические форумы сервисников. Пошарив по инету я выяснил, что в ресивере используется процессор STi5518. Дальше я начал искать информацию о ядре этого процессора.


Процессоры мобильных устройств, это не просто процы. Это all-in-1 чипы, в которые интегрировано все подряд: mp3 кодек, контроллер памяти, COM порты и прочая переферия. То есть то, что в x86 стоит материнке, здесь встроено в процессор. И поэтому такой процессор часто именуют словами "ASIC", "IC", "Baseband". Именно поэтому надо узнать какое тут "ядро".
Сайты очень любят писать "Процессор такой-то, частота такая-то, ядро - RISC". RISC (Reduced Instruction Set computer) - это название всех архитектур с "урезаным набором команд". Поэтому такая "писюлька" про то, что проц - RISC ничего реально и не говорит. Надо узнать какая именно RISC архитектура используется в ядре процессора: ARM, StrongARM, MIPS, AVR, ST20 C2/C4, PowerPC, SPARC, Coldfire и еще много других.


Наиболее достоверная информация обычно есть на сайте производителя процессора в Datasheet'e на проц. Бывает что datasheet'ы на сайтах не выкладывают. Т.е. покупай проц, подписывай договор о не разглашении - тогда дадим. Но инет богат ресурсами Smile Поэтому и в этот раз гугл помог мне найти. Для поиска datasheet'ов я уже привычно использую вот такой запрос в гугле:
Код:

STi5518 inurl:pdf
Т.е. ищем все pdf-ки содержащие "STi5518".

В datasheet'e ищем строку "instruction set" и находим.
Цитата :

This chapter provides information on the ST20-C2+ instruction set.
...
For further information on the instruction set refer to the ST20C2/C4 Instruction Set Manual.
Вот! Архитектура ядра ST20-C2, а полное описалово команд в "ST20C2/C4 Instruction Set Manual".

В Datasheet'e можно получить информацию об адресах регистров различной переферии, а главное! В нем указана карта памяти. Если есть datasheet на проц - считай 90% информации ты уже нашел.


В embedded устройствах не нужно разграничивать адресные пространства процессов и не нужно думать о виртуальной памяти - здесь просто ее так мало, что не разгуляешься, да и никакого юзерского кода нет в принципе. А если все делаешь сам и для себя - нет смысла париться про безопастность.
Таким образом в 32-битных системах на RISC-процессорах используется единое адрессное пространство размером 4Гб т.е. адреса 00000000 - FFFFFFFF. И все всё видят, почти как ring-0 в винде, где существует только Non-paged память. Или как это в x86 называется plane-адресация.
Команд работы с портами типа in и out здесь тоже нет. Здесь регистры оборудования мапятся на определенные адреса общего адресного пространства. Хочешь читать/писать в какую-то переферию - просто пиши байтики по определенному под эту железку адресу.
Карта памяти (Memory MAP) описывает какие адреса из этого 4-Гб пространства принадлежат какому оборудованию.


Смотрим по карте памяти, где лежит external memory:
Цитата :

* Locations 0x40000000 to 0x5FFFFFFF (banks 0 and 1) are generally used for SDRAM/DRAM, but may be used for
any external memory or peripherals.
* The locations 0x60000000 to 0x6FFFFFFF (bank 2) may be used for any external memory or peripherals except
SDRAM/DRAM.
* The locations 0x70000000 to 0x7FFFFFFF (bank 3) may be used for any external memory or peripherals except
SDRAM/DRAM, but are generally used for boot ROM. When booting from ROM, the system boots from the
predefined location BootEntry (0x7FFFFFFE) at the top of memory space.
Какой-то из этих регионов будет flash, а какой-то - RAM.


В мобильных устройствах для хранения кода чаще всего используется NOR flash память (перезаписываемая, энергонезависимая). NOR память является Random-access при чтении/выполнении кода, и блочной если делается запись. Т.е. читать можно побайтно, а запись только целым блоком. Flash память является для процессора "внешней памятью". У процессора есть своя внутренняя память(IRAM, On-chip RAM), в которой лежит boot-код (аналогично BIOS в x86), и есть маленькая, внутренняя RAM, благодаря которой выпоняется boot-код. Соотвественно, кроме внешней flash памяти, используют еще и внешнюю RAM.


Пока что информации достаточно, теперь нужно добыть код прошивки который мы будем рассматривать. Идеальный случай - сдампить самому флэш память на своем девайсе. Но обычно не знаешь, ни чем дампить, ни как это сделать, да и кабелей для поключения к девайсу нет. Поэтому стоит начать с поиска дампов. Чаще всего их придется выискивать на форумах, выпрашивать в аськах, но иногда встречаются сайты любителей "патчить прошивки не зная об ассемблере абсолютно ничего". Эти люди патчат картинки, руссифицируют ресурсы, в коде прошивки не разбираются, но выкладывают дампы за, что им человеческое спасибо. Дампят они обычно какой-то хитрой сервисной тулзой, которая была когда-то кем-то уперта из официального сервисного центра. Ественно не задумываются о том с какого адреса они дампили: "как сдампил так и заливаю
назад в девайс". Адреса, с которых был получен дамп прошивки, придется узнавать самому.
Вернуться к началу Перейти вниз
Посмотреть профиль
Hex

avatar

Количество сообщений : 397
Возраст : 35
Дата регистрации : 2006-07-12

СообщениеТема: Re: Кто не RISC'ует, тот не пьет шампанского...   Сб 15 Дек - 10:24

Вот примерно также мне удалось добыть "Скайон2300 новый дамп 5.04 - M29W160ET - Full.bin". Бинарь не от моего 2800, но для начального ознакомления покатит.


Иногда везет и натыкаешься на сервисников, которые знают чуть больше чем патчеры, и юзают JTAG для дампа. Зачастую они и не подозревают, что можно творить с девайсом Smile
JTAG - это апаратная система отладки, т.е. это единственный надежный способ продебажить код на девайсе.
JTAG состоит из:
* JTAG интерфейса процессора(в самом процессоре апаратный модуль который реализует отладку)
* JTAG-разъема на плате девайса (иногда не вывыеден как разъем, а контаты разбросаны по всей плате, так называемые "Test Points")
* JTAG - адаптера к компу и специального софта на компе, который через JTAG адаптер управляет отладкой кода на девайсе.
Если у вас все это есть, вы - бог девайса. Вы можете делать с ним все тоже, что могли делать разработчики софта: лить любой код, обращаться к любым адресам и регистрам.


Итак дамп есть. Теперь можно попробовать загрузить дамп в IDA. IDA естественно тип файла не распознает и скажет, что тип "binary", и поумолчанию предложит тип процессора "Intel 80x86 processors: meta pc". Мы то знаем, что это не так. Ставим правильный тип процессора:


И вот первая неожиданость. Новое окно, которого не было на x86:



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

IDA предлагает следующий подход для работы с прошивками. Предполагается что у девайса есть код которые лежит в ROM, и есть RAM для хранения изменяемых данных. В реале это просто предлагается создать в Иде 2 сегмента с именами "ROM" и "RAM" и загрузить указаный кусок прошивки в нужное место. Т.е. можно вначале создать просто ROM, а потом если надо руками создать сегмент, который будет "символизировать" адресное пространство RAM.
Как мы видели в Memory Map'e, внешеняя память может лежать по адресам:
0x40000000 - 0x5FFFFFFF
0x60000000 - 0x6FFFFFFF
0x70000000 - 0x7FFFFFFF
Попробуем наудачу загрузить на адрес 0x40000000. Для этого указываем ROM Start Address и Loading Address = 0x40000000.

Загрузили код и что? Cплошные db:


А где же код? Да тут же! Где ж ему еще быть!


В отличие от PE файлов из которых, состоит Windows, здесь все линейно, здесь нет никаких заголовков, тут все лежит так это захотел программер. Ну почти Smile В реальности в boot-коде, в проце, прописан адрес старта кода из прошивки. Обычно, адрес старта - это самое начало флэш памяти. Т.е. примерно также как в ntldr, здесь нет секций, сразу же начинается код. И данные не вынесены отдельно они идут вперемешку с кодом. Здесь нет релокаций, потому что они не нужны, здесь все строго захардкожено.


Последний раз редактировалось: (Сб 15 Дек - 10:32), всего редактировалось 1 раз(а)
Вернуться к началу Перейти вниз
Посмотреть профиль
Hex

avatar

Количество сообщений : 397
Возраст : 35
Дата регистрации : 2006-07-12

СообщениеТема: Re: Кто не RISC'ует, тот не пьет шампанского...   Сб 15 Дек - 10:25

Жмем C на самом начале. И видим:


Мама, роди меня обратно... А никто и не говорил, что оно будет похоже на x86. Тут свой ассемблер и к нему придется привыкнуть. Как быстро выучить ассемблер? По мануалу об ассемблере? - Неправильно! По компилятору. Ищем компилер для ST20. На официальном сайте нет, значит снова в гугл. И через время на одном из форумов находим упоминание "ST20 Toolset". Ищем
"ST20 Toolkit" и вот на еще на одном из форумов находим ссылку вот сюда:
http://212.90.96.3/~aj/sti5518.htm "STI5518 based universal FTA software project" где есть ST20 Toolset.

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


Качаем ставим, читаем в мануале статью "Getting started", создаем приложение "Hello world", билдим и запускаем на дебаг на эмуляторе. Смотрим в символьную информацию дебагера:


Значит таки правильно был выбран адрес загрузки прошивки - 0x40000000, функция main() как раз в начале образа.

Пробуем загрузить бинарь примера "Hello world" в Иду. Он тоже идой не распознается и грузится как какой-то мусор. Грузим его все равно на адрес 0x40000000, процессор ставим "SGS Thompson st20c4". Ищем строку "Hello World" и пробуем создать код вокруг этой надписи. Рано или поздно получим нечто симметричное:


Что можно сказать по этому коду, функции начинаются и заканчиваются инструкцией ajw, видимо это аналог стекового фрейма. Вызывы функций делаются через call. Загрузка адреса константы делается через ldl. Байт 0x20 используется для выравнивания данных по 4 байта. Теперь можно и почитать мануал по инструкциям вместе с мануалом на проц.

Удивительная архитектура у этого ST20, апаратная поддержка процессов! Т.е. есть ассемблерная комманда startp, которая запускает процесс, и endp - которая завершает. У каждого процесса есть workspace, на него указывает регистр WPtr
Цитата :

Wptr workspace pointer - contains the address of the workspace of the currently executing process

Т.е. типа PEB в винде.

Цитата :

ajw - Move the workspace pointer by the number of words specified in the operand, in order to allocate or de-allocate the workspace stack.
Это инструкция выделение/освобождения стека в текущем процессе.

Цитата :

stl n - Store the contents of Areg into the local variable at the specified word offset in workspace.
Это типа mov в стек.

Цитата :

ldc n - Load constant into Areg.
Это загрузка констант.

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


Регистр Areg используется для передачи параметра в функцию.

попробуем разобрать маленький кусочек кода:
Код:

ROM:400000E4                ajw    -3              ; выделили стек
ROM:400000E6                stl    4              ; сохраняем старое значение Areg в стек
ROM:400000E7                ldc    0Ah            ; загружаем указатель на 400000E8+2+0A=400000F4
ROM:400000E8                xword                  ;
ROM:400000EA                ldl    4              ; загружаем старое значение Areg в стек
ROM:400000EB                call    debugmessage    ; call
ROM:400000ED                ldc    0              ; загружаем указатель на 400000EE+2+0=400000F0
ROM:400000EE                ldl    3              ; Похоже на загрузку результата функции debugmessage
ROM:400000EF                ajw    3              ; освободили стек
ROM:400000F0                startp                  ; запустили процесс
ROM:400000F1                db  20h
ROM:400000F2                db  20h
ROM:400000F3                db  20h
ROM:400000F4 aHelloWorld:    db "Hello World",0Ah,0
Теперь, обладая хоть и дилетантскими, но все-таки уже не нулевыми знаниями о дизассемблировании кода ST20, можно браться за реверсинг прошивки.

Данная информация об ST20 C2/C4 была собрана за 3 часа. Т.е. если посидеть месяц и довести до ума процессорный модуль IDA ST20C4, чтобы он отображал стековые операции и обращения к константам. А потом посидеть-поделать разные примеры кода в компилере и порассматривать их в IDA, можно хорошенько натренироваться в понимании абсолютно новой архитектуры.


Последний раз редактировалось: (Чт 20 Дек - 2:39), всего редактировалось 4 раз(а)
Вернуться к началу Перейти вниз
Посмотреть профиль
twit



Количество сообщений : 57
Дата регистрации : 2007-07-24

СообщениеТема: Re: Кто не RISC'ует, тот не пьет шампанского...   Вс 16 Дек - 5:31

Хорошо когда есть прошивка. А когда ее нет, производитель положил на пользователей, а само устройство является HID, то тут даже не порискуешь.
Вернуться к началу Перейти вниз
Посмотреть профиль
Hex

avatar

Количество сообщений : 397
Возраст : 35
Дата регистрации : 2006-07-12

СообщениеТема: Re: Кто не RISC'ует, тот не пьет шампанского...   Вс 16 Дек - 7:08

twit пишет:
Хорошо когда есть прошивка. А когда ее нет, производитель положил на пользователей, а само устройство является HID, то тут даже не порискуешь.
Не надо впадать в крайности Smile

Статья написана, для тех кто решил таки оторваться от винды и познать что-то новое. Все мы знаем, что есть очень много сложных случаев.
Вернуться к началу Перейти вниз
Посмотреть профиль
twit



Количество сообщений : 57
Дата регистрации : 2007-07-24

СообщениеТема: Re: Кто не RISC'ует, тот не пьет шампанского...   Вс 16 Дек - 11:47

Hex пишет:
Статья написана, для тех кто решил таки оторваться от винды и познать что-то новое.
Я, прочтя её, скачал прошивку для своего Arion AF-1700E и тоже решил покопать. Проц такой же - ST20C2/4
Только есть некоторые далеко неясные штуки Smile
Например, гружу прошивку по адресу 0x40000000, т.е. как и у тебя в статье, одно но, имеется 64-байтный заголовок, вроде всё правильно и в начале имеется бесконечный цикл, как это обычно бывает у микроконтроллеров(AVR точно)
Код:
loc_40000036:                          ; CODE XREF: ROM:4000003Bj
ROM:40000036                ldc    0Ah
ROM:40000037                ldl    1
ROM:40000038                call    sub_40000A50
ROM:4000003B                j      loc_40000036
Но далее есть несколько вызовов, типа
Код:
call    805B3F18h
которые идут за доступное адресное пространство рома, причём есть загрузить ром не по 0x40000000, а по 0x60000000,то тот call приобретает вид
Код:
call    0C05B3F18h
Вернуться к началу Перейти вниз
Посмотреть профиль
Hex

avatar

Количество сообщений : 397
Возраст : 35
Дата регистрации : 2006-07-12

СообщениеТема: Re: Кто не RISC'ует, тот не пьет шампанского...   Вс 16 Дек - 14:35

Это относительный вызов. Т.е. +405B3F18 как не грузи - не попадешь так чтобы совпали адреса.
Я подозреваю что есть ремапинг, или еще какая-то хитрость с прыжками в эти адреса. Вполне возможно что это глюки процессорного модуля, ильфак ведь не занимается особой проверкой валидности дизассемблерного листинга. Он просто в версии 4.5 добавил процессорный модуль, потому что ему видать денег дали. А раз он его выложил с сорцами - значит он его уже давно не сапортит. И оно как было, так и осталось в зародышевом состоянии и с кучей багов. Я не собираюсь ща докапываться до истины, просто хотел показать, что можно влезть в любую новую архитектуру, было бы желание и время.

Не думал, что после статьи будут такие последствия... scratch
Вернуться к началу Перейти вниз
Посмотреть профиль
wl



Количество сообщений : 127
Дата регистрации : 2007-02-15

СообщениеТема: Re: Кто не RISC'ует, тот не пьет шампанского...   Вт 18 Дек - 15:43

а что за дебильный лодер ELF в составе sdk ida? его по моему нереально скомпилировать. А так хотелось сделать нормальный загрузчик PSP Executable (модифицированный ELF, где импорт - это часть SHA1 или MD5, не помню уже точно от, названия функции + процессор MIPS).

ps. формат jpeg - для природных объектов с нечеткой структурой, для скриншотов больше подходит png или gif (если цветов на мониторе немного)
Вернуться к началу Перейти вниз
Посмотреть профиль
Hex

avatar

Количество сообщений : 397
Возраст : 35
Дата регистрации : 2006-07-12

СообщениеТема: Re: Кто не RISC'ует, тот не пьет шампанского...   Ср 19 Дек - 4:34

Надо будет посмотреть на новогодних праздниках, он реально кучу инфы скипает и глючит безбожно на всяких ELF от девайсов.
Вернуться к началу Перейти вниз
Посмотреть профиль
ssx



Количество сообщений : 4
Возраст : 99
Дата регистрации : 2006-07-18

СообщениеТема: Re: Кто не RISC'ует, тот не пьет шампанского...   Ср 19 Дек - 5:10

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



Количество сообщений : 25
Дата регистрации : 2006-09-18

СообщениеТема: Re: Кто не RISC'ует, тот не пьет шампанского...   Пт 28 Дек - 16:15

Hex пишет:
Это относительный вызов. Т.е. +405B3F18 как не грузи - не попадешь так чтобы совпали адреса.
Я подозреваю что есть ремапинг, или еще какая-то хитрость с прыжками в эти адреса.
Одна из хитростей с прыжками может заключаться в разрядности шины адреса. Сейчас - догадка, а в прошлом - встречалось где то такое.
Т.е. реально побоку если напишешь
Код:

call    805B3F18h
или
Код:

call    005B3F18h
Хорошо конечно когда есть sheet по архитектуре проца. Но даже в этом случае интересно каким критерием компилер, а скорее всего девелопер руководствуется чтоб так делать.
twit, если ты не ошибся на 0ч20000000, то код действительно странный - адрес call'a второго варианта нелогичен, кроме как предположить(!) баг модуля IDA
Вернуться к началу Перейти вниз
Посмотреть профиль
Hex

avatar

Количество сообщений : 397
Возраст : 35
Дата регистрации : 2006-07-12

СообщениеТема: Re: Кто не RISC'ует, тот не пьет шампанского...   Ср 2 Янв - 7:58

ssx пишет:
да и на обычных эльфах глючит-падает-виснет. задрало уже, хоть пиши свой лоадер.
Посмотрел что нам ильфак выдал в каталоге \ldr\elf. Это не лоадер.
Это просто 2 хедера, в которых записаны стандартные константы и структуры, которые юзаются в формате elf. И один cpp с набросками функций. "сорцы" не менялись с sdk от 4.7.
Тут действительно проще будет написать свой лоадер с нуля.

p.s. Я посмотрел на бинарь загрузчика ELF. Он огромный.
Вернуться к началу Перейти вниз
Посмотреть профиль
algent



Количество сообщений : 10
Дата регистрации : 2008-03-24

СообщениеТема: Re: Кто не RISC'ует, тот не пьет шампанского...   Пт 28 Мар - 20:05

Классная статья, как впрочем и весь сайт. Но особенно мне понравилась техника поиска даташитов Smile Чуствую себя теперь как на танке, со списком адресов буржуйских хайтек компаний. Завтра испытаю Smile.

Цитата :
Но даже в этом случае интересно каким критерием компилер, а скорее всего девелопер руководствуется чтоб так делать.
Со старшими адресными линиями примерно таже ситуация что и со младшими. Младшие адресуют байты/ворды в пределах выбранного чипа. Старшие выбирают чип, и/или например на шинах ISA, PCI могут выбирать плату. В простом случае, ко старшим линиям подключена микросхема дешифратора, т.н. селектор адреса, он дешифрирует адреса и выдаёт сигналы chip select, которые идут на соответствующие чипы.
Вернуться к началу Перейти вниз
Посмотреть профиль
Спонсируемый контент




СообщениеТема: Re: Кто не RISC'ует, тот не пьет шампанского...   

Вернуться к началу Перейти вниз
 
Кто не RISC'ует, тот не пьет шампанского...
Предыдущая тема Следующая тема Вернуться к началу 
Страница 1 из 1

Права доступа к этому форуму:Вы не можете отвечать на сообщения
eXTracted INternals :: Cтатьи :: Mobile and Embedded-
Перейти: