Как стать автором
Обновить

Комментарии 96

Это не просто реверс инженеринг, это уже следующий уровень, даже не могу адекватно название придумать.
Аплодирую стоя.


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


Полагаю вы занимаетесь именно этим только взаправду.


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

Спасибо! Работа была действительно интересная. Мы были обязаны про нее долгое время молчать, но вот сейчас срок «молчания» истек. Продолжение следует…
Пока шел срок молчания появились еще сотня другая архитектур. Интересно как будет дело обстоять с ними. Молчать придется еще дольше видимо.
А также «Пляшущие человечки» А. Конан-Дойля
Спасибо за статью, интересно, только неожиданно прервалась, можно сказать, в самом начале( Тоже решал подобную задачу, и тоже начинал с определения размера инструкции «на глаз», потом CALL/RET, правда у меня был работающий девайс и дальше я восстанавливал инструкции в основном методом тыка.
И кстати, хорошо бы в посте опубликовать саму анализируемую прошивку.
Спасибо. Продолжение следует… Возможно по мотивам данной работы будут сделаны задачи для «Кубка реверса».
Ждём-ждём!
Частотный анализ и додуматься до CALL/RET, прям как детектив про Шерлока Холмса.

По длине бинарника можно прикинуть, что за зверь. Прошивка для 8битки вряд ли будет больше 64Кб. Ну и исключить известные архитектуры, типа 8080, Z80, dsPIC.

А еще, позвонить заказчику и попросить сфоткать начинку подробнее.
Заказчику мы звонили, только Заказчик все, что знал, сказал в самом начале работы.
Очень интересно, жду продолжения!
Спасибо. Оно будет достаточно скоро.
Не прбовали поглядеть, по каким адресам грузится файл прошивки, и, исходя из этого, определить что за микроконтроллер используется? Насколько я знаю, у каждого семейства МК свои адреса маппинга памяти для различных нужд.
Прошивка отображалась с нулевого адреса вместе с векторами прерывания. Это типичная ситуация.
После «ни один процессор из поддерживаемых IDA Pro не подошел» я бы предположил, что там используется к примеру форт или что-то подобное, и большая часть прошивки не является машинным кодом.
Разумное предположение, но все оно не подтвердилось.
Скорей всего, японский МК или проц. Всякие NEC любили вдарять по экзотике.
Да и автомобильные МК тоже не похожи ни на что.

Есть ещё большое количество ASIC без (открытой) документации, скажем, TI и Atmel тоже в этом замечены. А уж про процессора для сотовых и говорить нечего.

Прошивка авторами расколота, значит что-то доступное, а не кастом. Возможно, хорошо забытое старое. Ардуино на КПДВ тоже наверное с намёком.
Если есть читаемые ASCII строки, то часто их адрес присутствует в коде команды загрузки указателя в регистр, а дальше идет CALL подпрограммы вывода или сравнения.
Здесь надо учитывать, что мы имеем дело не просто с приложением, а с прошивкой. Поэтому данное высказывание требует проверки.
пробовали скормить прошивку IDA Pro или unidasm-у из комплекта MAME и прогнать все поддерживаемые архитектуры?
или в даташитах на известные MCU поискать наиболее часто встречающиеся в бинарнике опкоды?

в авторах вроде указаны люди с к.ф.-м.н. итп учеными степенями, но с системным подходом похоже проблемы…
Мы писали, что IDA Pro мы пробовали и такой архитектуры он не поддерживает, unidasm-у тоже пробовали, тоже не поддерживает.
Оффтопик
Скажите, пожалуйста, а упомянутый к.ф.-м.н. Чернов А.В. случаем не преподавал практикум по ЭВМ на факультете ВМиК МГУ примерно 15-20 лет назад?
Сева, привет! Упомянутый к.ф.-м.н. Чернов А.В. до сих пор преподает там практикум. И у тебя преподавал. А выше упомянутая к.ф.-м.н. Трошина К.Н. в девичестве Катя Долгова училась с тобой в одной группе на 3-5 курсе :)
Мир тесен…
Катя, привет! Тебя, конечно, не признал, но нечто подобное подозревал:)

Да, действительно очень и очень тесен.:) Тем более логично, что встречи итшников происходят на сайте хабра:)

PS До сих пор рассказываю всем историю как я чуть не сдал Чернову А.В программу на нобелевскую премию на практикуме:) Но не сдал все же.
Да забавно :) Мир очень маленький…

Я встречал (дорабатывал) такой изврат, как виртуальная ассемблерная машина на ассемблерной же прошивке для PIC16.
Для реально существующих процессоров намного проще проверять по карте памяти (порты ввода/вывода, регистры периферии и т.п.)

Да, все так, если есть карты памяти, то их, конечно, надо использовать. Решая такие задачи, собираешь из того что, дали. И просить то, что надо, не приходится.

Но от вас же просили компилируемый исходник, т.е. где-то существует тулчейн под вполне конкретный проц? А для этого тулчейна существуют вполне конкретные заголовочные файлы, ибо писать (uint16_t)0x4000080A=01 вместо GPIOA->ODR=1<<CS в конечном исходнике было бы несколько странно…
Плюс, например, комбинация режимов периферии (таймеров) и DMA, обвязанных ещё и схемотехнически, без знания периферии камня, схемы и осциллограмм в готовом устройстве — превращается просто в набор бессмысленных присвоений и адресов. Которые, на самом деле, являются обработчиками прерываний от DMA, скажем.
Ну то есть, видно, что труд вами проделан большой, но за абстракциями и недоговорённостями смысл потерялся.

Пардон, (uint16_t)a=b вместо
GPIOA->ODR=1<<CS;

У нас не было такой информации в доступе. Но Вы правы, такой tool chain, непременно существует.
Ему требовался алгоритм управления в виде компилируемой С-программы...

И как вы собирались без тулчейна выдать ему компилируемую C-программу? =))
То, как мы в итоге разбирались с физикой, в рамках данного цикла статей мы опустим...

Если с физикой разбирались, то скорее всего у вас доступ устройству был, поэтому сделать оценку контроллера можно было.
Так они не для старого проца программу должны были восстановить, а перенести на новую железяку.
Компилируемую С-программу мы сделали руками. Продолжение будет далее…
Доступа к устройству никогда не было.
И у заказчика тоже никогда не было?
И у заказчика тоже никогда не было.
Есть системы где шины и адреса и данных рандомно перепутаны. Для них Последовательное исполнение инструкций. Процессор исполняет инструкции, расположенные последовательно в памяти. естественно не выполняется.
Когда в руках живая плата — это прозванивается за 10 минут. Но в случае если есть только бинарник — было бы интересно как тут быть?
Нам тоже было бы интересно такую задачу порешать.
У меня например на этот счет нет идей… если у вас тоже — получается, что этот метод будет защитой от реверса вашим методом…
Здесь мы рассказали, как решали конкретную задачу.
В которой вам просто повезло, что было не так! А могло бы и не быть — т.е. ваше решение базируется на везении и том, что линейное пространство в hex-ах встречается с более высокой вероятностью.
Это не везение, это знания. Здесь рассказано решение конкретной задачи, тем методом, которым ее удалось решить.
Вы сделали очень много последовательных допущений, каждое из которых волшебным образом сработало. (линейность пространства, напрямую хранятся адреса вызовов подпрограмм). Я вам привел пример, когда одно из них не срабатывает — этот пример поставил вас в тупик. В чем тогда ценность решения вашей конкретной задачи, если весь класс задач так не решается? В конечном счете вы могли просто собрать 10-низкоуровневых специалистов каждый по своей архитектуре и дать каждому посмотреть код глазами — и без всякого частотного анализа специалист по этой архитектуре ткнет пальцем «о — это мой». Т.е. равноценно обычному угадыванию… Например куча народу только глянув на первую страницу сможет подтвердить или опровергнуть гипотезу принадлежности к MCS51 по векторам 0-3-0b-13-1b и коду LJMP 02h. Или к Z80 по коду JP 0c3h и команде DI (0f3h) с которой все начинается в большинстве % случаев. (в АОН-о строении это веками наработанная практика, ибо как раз файл с одним и тем же названием легко мог принадлежать к одной из этих двух архитектур)…

Уверен, они сделали гораздо больше количество параллельных допущений, большинство из которых не сработало. О том, которое сработало написали пост.
Как понимаете, это не про везение.


ps: ваш пример вообще не понял — ну перемешаны на плате линии данных для удобства разводки, что с того ?

А то, что частотный анализ перестает работать. Точнее он работать будет но смысла не имеет, ведь за RET-ом не будет начала процедуры…

Я просто не вижу чем в данном конкретном случае частотный анализ, чем то лучше банального «угадывания» по набору априорных сведений об архитектурах — кроме того что он подразумевает писанину кода.
А еще там мог оказаться байткод для брейнфакВМ(тм) (что, кстати, более вероятно, чем raw-образ прошивки для параллельной ПЗУ). Был бы другой вариант решения, что с того?

Я, кстати, практически уверен что в рассматриваемом случае собака зарыта в конвертации hex2bin.
Ждем продолжения истории.
Спасибо за комментарий, Вы абсолютно правы, все было именно так. Мы делали значительно большие допущений, экспериментов и всего остального, а написали только про то, что отработало.
Статья супер. Вопрос не совсем по теме, но близко: не пробовали ли реверсить прошивки ПЛИС?
Спасибо. Нет, не пробовали, но с удовольствием попробуем.
С ПЛИСами есть одна засада — дойти до уровня RTL вполне себе может и получится, а вот далее полный швах.

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

Да и switch/case тоже часто так компилится, особенно кстати в прошивках, когда, например, есть какой-то входящий последовательный протокол.
это если case'ы подряд идут и компилятор достаточно умный. а вот для
case 1:…
case 2:…
case 100500:…
ничего кроме связки условных переходов и не придумаешь…
Продолжение следует…
Нет, адреса методов невиртуальных С++ классов линкеру известны, и он, скорее всего, сделает вызов по константному адресу (исключений я не знаю. Впрочем, все архитектуры я тоже не знаю ;-) ).
Другой вопрос, что команд перехода может быть сильно больше одной (когда размер адресуемой памяти превышает размер регистра, фантазия проектировщика системы команд начинает бить ключом — может появиться пяток разных способов адресации в одном чипе).
Насколько часто компилятор проявляет энтузиазм, создавая подпрограммы там, где их не было в высокоуровневом коде? Зависит ли это от флагов оптимизации? А то бывают же случаи, когда на тыщу строк кода меньше десятка функции, да и то почти все — обработчики прерываний, тут бы поиск RET/CALL по статистике дал бы дубу. Я бы искал операции вроде ADD и MOV как самые часто встречаемые в вообще любой программе, а там уже по их кодам перебирал всевозможные контроллеры по каталогу
Насколько часто компилятор проявляет энтузиазм, создавая подпрограммы там, где их не было в высокоуровневом коде?

AFAIK, никогда. Зато часто делает наоборот — инлайнит подпрограммы, так что в бинарнике уже нету RET/CALL.

Я бы искал операции вроде ADD и MOV как самые часто встречаемые в вообще любой программе

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

На так давно помогал с прототипом защиты от подобного анализа для "мягких" процессоров.


Идейно защита достаточно проста — вставляется несколько скремблеров, в частности в шину данных и в декодер инструкций, конечно с зависимостью от адреса и ключа прошивки. Технически же сложности из-за необходимости экономить cells и latency, ну и возня с toolchain. Но получается очень неплохо, можно даже специально оставлять статистические bias/skew, которые при попытке их использовать уводят в совершенно неверном направлении ;)

Очень интересный опыт. Было бы интересно получить подробности работы.
НЛО прилетело и опубликовало эту надпись здесь

Возможно, эта прошивка была не украдена, а сбита ПВО.

НЛО прилетело и опубликовало эту надпись здесь

так или иначе, правообладатели либо не в курсе, либо в суд подавать не станут :-)


К тому же, не стоит забывать про секретность — все подробности вроде конкретных кодов команд, а может и источник получения прошивки, наверняка изменены.

НЛО прилетело и опубликовало эту надпись здесь
Мы ничью прошивку не крали. У нам пришел Заказчик и попросил разобраться с тем, что она нам передал. Передавал прошивку по документам. Мы выполнили задачу.

1280 ГК РФ:
Лицо, правомерно владеющее экземпляром программы для ЭВМ, вправе без согласия правообладателя и без выплаты дополнительного вознаграждения воспроизвести и преобразовать объектный код в исходный текст (декомпилировать программу для ЭВМ) или поручить иным лицам осуществить эти действия, если они необходимы для достижения способности к взаимодействию независимо разработанной этим лицом программы для ЭВМ с другими программами, которые могут взаимодействовать с декомпилируемой программой

НЛО прилетело и опубликовало эту надпись здесь

А вы по каким критериям решили что имело место ущемление чьих-то законных интересов?

НЛО прилетело и опубликовало эту надпись здесь
Мы делали работу для обеспечения совместимости оборудования. Выступали как подрядчик.
В 200х году фирма к примеру заказала бифуркаторный бульбулятор с интерфейсом RS232 у другой компании, по договору у заказчика были допустим все права на код и прочее. Но благодаря раздолбайству(не передали исходники, схематику/передали, но они лежали на единственном диске, который навернулся со стола, потом запилил всю поверхность и перешел в разряд «восстановление данных — 10$ за мегабайт без гарантии») исходники были потеряны.
В 200х+y году фирма, которая это делала прекратила своё существование, ну и для вишенки на торте со всех складов и из продажи исчез применённый заказной микроконтроллер…
В 200x+y+z году надо было выпустить новую партию…
По любому законодательству в этом случае можно обреверситься что прошивкой, что схемой устройства, чтобы выпустить новую партию.
Обычно задача стоит иначе: есть работающая железка, надо вытащить из нее прошивку. При этом известна модель процессора, потому что он в руках. Но обычно считывание прошивки запрещено битами защиты, что и является основным препятствием.
У вас же редкая ситуация — прошивка на руках в легко читаемом формате, но неизвестно от какого процессора. :-).
Мне кажется, или тут только что признались в неком деянии совершенном группой лиц по предварительному сговору и в крупных размерах?

Все история выдумана, совпадения с реальностью случайны.

Не обязательно. У меня был случай, когда заказчик протерял исходники модуля, и модуль остался только в виде .jar файла, который мне потом передали с задачей восстановить исходники. Но там была Java, и было все элементарно.
И такое раздолбайство весьма часто встречается.

Аналогичная ситуация — есть apk, исходники утеряны, кто писал неизвестно, так как за это время много людей в компании поменялось. Такие ситуации сплошь и рядом

Подтверждаю, что такие случае бывают. Мы сталкивались на практике.
Почему не выбрали «Реверс-инжиниринг»? Это ведь прямо оно самое.
Наверное, пропустили… Спасибо за комментарий.
Оказывается, у вас все статьи пропустили этот тэг. Лучше добавьте, такой материал не должен затеряться.
Да, мы в итоге написали свой декомпилятор. Он долго был в отрытом доступе и с него было сделано множество клонов. В ближайшем будущем мы его реанимируем и выложим в открытый доступ обратно.
Там наверное в начале идёт таблица прерываний, полностью состоящая из инструкций JMP или типа того? Например в AVR там будут инструкции относительного перехода RJMP, по которым можно сразу найти начало основной программы. Ещё они будут почти одинаковые и выравнены по 4 байта, т.к. в AVR все команды 16/32 бит. Но, судя по найденным кодам, у вас там что-то другое. Интересно было бы попробовать поиграть в такую игру.
Игра секретная, нам про неё не расскажут. Вон, даже hex-файл в начале статьи исправленный, у него контрольные суммы не сходятся. Впрочем, даже если их поправить, там ничего сверхсекретного не видно: pastebin.com/1gzN7mnQ
Уважаемая Катерина, уже прошёл почти год, а продолжения я так и не нашёл…
Видимо, в марте.
Да если бы

Посмотрим 25го.

Важно, что у подпрограммы одна точка входа, то есть все подпрограммы, вызывающие данную, переходят на один и тот же адрес точки входа.

Не всегда, бывает и немного кода до подпрограммы, на которую тоже прыгают. Эдакая подпрограмма с двумя входами. Не удивлюсь, если бывает и больше.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий