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

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

Но ведь работать с ними как‑то надо! Как вык­рутить­ся прос­тому хакеру без столь удоб­ного инс­тру­мен­та, кажуще­гося незаме­нимым? Поп­робу­ем разоб­рать все мытарс­тва, ожи­дающие его на этом тер­нистом пути.

Итак, усло­вие задачи: дана некая биб­лиоте­ка, опре­делен­ную фун­кци­ональ­ность которой нам нуж­но пос­тичь и ревер­сировать. Как обыч­но, для начала заг­ружа­ем ее в Detect It Easy.

Сра­зу замеча­ем нелад­ное: тип про­цес­сора — 32-бит­ный CRIS — нам отро­дясь не встре­чал­ся. Про­буем дизас­сем­бли­ровать биб­лиоте­ку в IDA.

IDA вро­де сог­лаша­ется с DIE: тип фай­ла ука­зан как ELF for CRIS, одна­ко пред­лага­емый по умол­чанию тип про­цес­сора (MetaPC) нас­торажи­вает. Тем более никако­го CRIS в спис­ке под­держи­ваемых IDA про­цес­соров и близ­ко нет. Естес­твен­но, сле­дом выс­какива­ет ошиб­ка.

Что такое тип 76, в прин­ципе, понят­но — мгно­вен­но нагуг­лив спе­цифи­кацию хидера ELF, мы находим его рас­шифров­ку:

EM_CRIS 76 Axis Communications 32-bit embedded processor

Се­мей­ство доволь­но извес­тное и широко исполь­зуемое в узких кру­гах: обыч­но под этим типом под­разуме­вают про­цес­соры ETRAX фир­мы Axis Communication. Само сло­во CRIS — это тип архи­тек­туры подоб­ных про­цес­соров, оно явля­ется сок­ращени­ем от Code Reduced Instruction Set, что перево­дит­ся как «набор инс­трук­ций с сок­ращен­ным кодом».

Этот набор инс­трук­ций заяв­лен как под­мно­жес­тво инс­трук­ций RISC, одна­ко при попыт­ке выбора в IDA любого из похожих типов (да и вооб­ще любого под­держи­ваемо­го IDA типа) осмыслен­ного кода получить не уда­ется.

Поп­робу­ем эмпи­ричес­ки про­верить, что все‑таки у нас за про­цес­сор и как рас­кодиро­вать его инс­трук­ции. Google показы­вает нам спе­цифи­кацию похоже­го CRIS-про­цес­сора AXIS ETRAX 100LX. Пос­мотрим, соот­ветс­тву­ют ли инс­трук­ции нашего про­цес­сора ука­зан­ной спе­цифи­кации.

Для это­го поп­робу­ем рас­кодиро­вать пер­вую инс­трук­цию _init_proc со скрин­шота выше, опи­раясь на най­ден­ную спе­цифи­кацию. Сог­ласно ей, поч­ти все инс­трук­ции это­го про­цес­сора име­ют дли­ну 16 бит (Dword). Соот­ветс­твен­но, рас­кодиру­емое зна­чение будет 0xE284. В битовом виде это будет выг­лядеть так:

1110 0010 1000 0100

В раз­деле 3 INSTRUCTIONS IN ALPHABETICAL ORDER нашей спе­цифи­кации при­лага­ются побито­вые рас­шифров­ки каж­дого клас­са инс­трук­ций это­го про­цес­сора. Изрядно пома­явшись, мы находим инс­трук­цию, под­ходящую под нашу битовую мас­ку, subq.

Ес­ли верить спе­цифи­кации, это опе­рация быс­тро­го вычита­ния 6-бит­ной чис­ловой кон­стан­ты из регис­тра. Кон­стан­та опре­деля­ется млад­шими шестью битами и в нашем слу­чае рав­на 00100b=4. Регистр Rd же — стар­шие 4 бита 1110b=14, что соот­ветс­тву­ет ука­зате­лю сте­ка sp. То есть пол­ная мне­мони­ка нашей коман­ды subq 4, sp (перемес­тить ука­затель сте­ка на 4 бай­та вверх) впол­не похожа на исти­ну — обыч­но так начина­ется стан­дар­тный вход в про­цеду­ру с резер­вирова­нием пула локаль­ных перемен­ных. Спе­цифи­кация, похоже, рабочая, но не будем же мы покоман­дно рас­шифро­вывать нес­коль­ко сот килобайт кода? Жизнь слиш­ком корот­ка для подоб­ных чел­лен­джей, надо как‑то авто­мати­зиро­вать про­цесс.

Ес­ли ты по жиз­ни мак­сималист и обла­даешь неог­раничен­ным запасом сво­бод­ного вре­мени при пол­ном отсутс­твии дру­гих инте­рес­ных задач, мож­но сде­лать собс­твен­ный уни­каль­ный дизас­сем­блер‑деком­пилятор, осно­выва­ясь на нагуг­ленной спе­цифи­кации. Я не осуж­даю подоб­ное решение, у него мно­жес­тво плю­сов — мож­но пот­рениро­вать­ся в пар­синге и глуб­же понять прин­цип дей­ствия про­цес­сора. В кон­це кон­цов, это поз­волит соз­дать новый, единс­твен­ный в сво­ем роде гит­хабов­ский про­ект, на который потом мож­но наращи­вать новые фай­ловые фор­маты и про­цес­сорные архи­тек­туры. Его не стыд­но будет положить в пор­тфо­лио и пуб­ликовать о нем статьи на «Хакере» и про­чих умных ресур­сах.

Но цель нашей сегод­няшней статьи сов­сем дру­гая — выб­рать путь, который поз­волит быс­тро и наимень­шими уси­лиями ревер­сировать фраг­мент кода ред­кого (и уже вин­тажно­го) про­цес­сора. А писать под такое собс­твен­ный деком­пилятор — это, изви­няюсь за неп­рилич­ное срав­нение, все рав­но что выкупать гек­тар тай­ги и стро­ить на нем бумаж­ный завод для того, что­бы скас­товать рулон туалет­ной бумаги.

Поп­робу­ем миними­зиро­вать задачу — у нас име­ется IDA, которая уже уме­ет раз­бирать (и успешно разоб­рала) фор­мат ELF со все­ми его стро­ками, фун­кци­ями, импорти­руемы­ми‑экспор­тиру­емы­ми сим­волами и про­чими ниш­тяками. Нам не хва­тает толь­ко одно­го: пар­синга ассем­блер­ных инс­трук­ций.

С дру­гой сто­роны, IDA рас­ширя­ема, к ней впол­не мож­но написать свой про­цес­сорный модуль. Ты, веро­ятно, зна­ешь, что IDA поз­воля­ет писать свои пла­гины. Задача эта, хоть и полег­че раз­работ­ки собс­твен­ного деком­пилято­ра с нуля, тоже весь­ма неп­ростая.

Ес­ли ты собира­ешь­ся ком­пилиро­вать собс­твен­ный натив­ный про­цес­сорный модуль для IDA, слож­ности начина­ются уже на эта­пе получе­ния Hex-Rays SDK под нуж­ную (а надо ска­зать, что вер­сии SDK доволь­но сла­бо сов­мести­мы друг с дру­гом) вер­сию дизас­сем­бле­ра — это весь­ма неп­рият­ный квест. Затем нач­нутся слож­ности с ком­пилято­ром С++, потому что далеко не каж­дый из них спра­вит­ся с этим нелег­ким делом. Поэто­му нуж­но заранее готовить бубен поболь­ше.

Раз­работ­чики IDA явно рас­счи­тыва­ли на прод­винутую хакер­скую ауди­торию, поэто­му, что­бы не разоча­ровы­вать ее, сде­лали этот путь мак­сималь­но хар­дкор­ным, вдо­бавок прак­тичес­ки не при­ложив к нему тол­ковой докумен­тации. Впро­чем, раз­работ­чики сто­рон­них пла­гинов написа­ли мно­жес­тво ста­тей об этом: нап­ример, статью с говоря­щим наз­вани­ем Writing an IDA Processor Module, «До­бав­ление нового семей­ства про­цес­соров в IDA pro» или «Раз­рабаты­ваем про­цес­сорный модуль NIOS II для IDA Pro».

Продолжение доступно только участникам

Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».

Присоединяйся к сообществу «Xakep.ru»!

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    2 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии