Неизвестный крыс. Обучаем IDA работать с редкими процессорами на примере CRIS

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

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *