Вов­лечен­ный в про­ект по соз­данию инте­рак­тивно­го рас­паков­щика PE-фай­лов, я иссле­дую осо­бен­ности реали­зации сис­темно­го заг­рузчи­ка Win32 на пред­мет сле­дова­ния сво­им же спе­цифи­каци­ям. Оби­лие багов, часть которых носит доволь­но ковар­ный харак­тер, прос­то поража­ет. Итак, сегод­ня мы про­демонс­три­руем при­ем, поз­воля­ющий пря­тать код/дан­ные от популяр­ных дизас­сем­бле­ров типа IDA Pro.

Ис­полня­емые фай­лы, динами­чес­кие биб­лиоте­ки и драй­веры — все они «кры­шуют­ся» одним и тем же фор­матом, про­ходя­щим под кодовым наз­вани­ем Portable Executable (или сок­ращен­но PE). Спе­цифи­кации на него дос­тупны всем жела­ющим. Для раз­работ­чиков лин­керов, отладчи­ков, дизас­сем­бле­ров и про­чего «фир­менно­го» инс­тру­мен­тария спе­цифи­кации — это Коран (Биб­лия, Тора — нуж­ное под­чер­кнуть). Вот толь­ко живая опе­раци­онная сис­тема спе­цифи­каций не при­дер­жива­ется и мес­тами ведет себя сов­сем не так, как это сле­дует из докумен­тации.

Соз­датели вирусов ведут мас­штаб­ные рас­копки ntoskrnl.exe, отыс­кивая раз­личия реали­заций сис­темно­го заг­рузчи­ка и дизас­сем­бле­ров/отладчи­ков/анти­виру­сов. Конеч­но, никаких гаран­тий, что най­ден­ная багофи­ча сох­ранит­ся в пос­леду­ющих вер­сиях Windows (не говоря уже об эму­лято­рах типа Wine), у нас нет, но если дей­ство­вать с умом, то мож­но писать не толь­ко надеж­ные вирусы и ком­мерчес­кие при­ложе­ния.

А сей­час на мгно­вение (гро­зящее рас­тянуть­ся в минуты или даже часы) отор­вемся от статьи и поп­робу­ем взло­мать отно­ситель­но нес­ложный crackme, исполь­зуя любой инс­тру­мент по вку­су (IDA Pro, OllyDbg, HIEW…). Пос­ле чего мож­но про­дол­жить чте­ние, ведь ког­да решение извес­тно — ломать ста­новит­ся неин­терес­но.

Требуется помощь читателей!

Файл с крэк­ми KedaH3.exe был опуб­ликован на DVD «Хакера» #121 (январь 2009 года), одна­ко этот диск отсутс­тву­ет в наших архи­вах. Если у тебя он есть, пожалуй­ста, приш­ли нам матери­алы к этой статье на адрес content@glc.ru.

 

Ликбез

PE-фай­лы гру­зят­ся доволь­но хит­рым обра­зом, про­еци­руя «сырые» (raw) дис­ковые дан­ные в вир­туаль­ную память. В резуль­тате каж­дая сек­ция име­ет два набора атри­бутов: один опи­сыва­ет образ сек­ции на дис­ке, дру­гой — ее про­екцию в памяти. Физичес­кий (physical) раз­мер сек­ции на дис­ке может отли­чать­ся от вир­туаль­ного (virtual). Если вир­туаль­ный раз­мер боль­ше физичес­кого, сис­тема авто­мати­чес­ки ини­циали­зиру­ет «хвост» сек­ции нулями, о чем осве­дом­лены лин­керы и ком­пилято­ры, генери­рующие более ком­пак­тные PE-фай­лы, — что явля­ется общепри­нятой нор­мой и хорошим тоном. Обратная ситу­ация (ког­да вир­туаль­ный раз­мер мень­ше физичес­кого) встре­чает­ся нам­ного реже, но все‑таки встре­чает­ся, ког­да при­ложе­ние хочет при­цепить овер­лей или дру­гие дан­ные, с которы­ми пред­полага­ется работать пос­редс­твом пря­мого дис­кового вво­да/вывода без заг­рузки в память.

На самом деле спе­цифи­кация не гаран­тиру­ет, что оста­ток (Virtual Size – Physical Size) оста­нет­ся на дис­ке. Ник­то ведь не зап­реща­ет гру­зить «хвост» сек­ции в память, осо­бен­но если он укла­дыва­ется в гра­нуляр­ность вырав­нивания, опре­делен­ную в PE-заголов­ке. Допус­тим, физичес­кий раз­мер сек­ции сос­тавля­ет 10h байт, вир­туаль­ный — 100h, а вырав­нивание на дис­ке / в памяти — 1000h. Сис­тема, оче­вид­но, не может про­читать 10h байт с дис­ка. Вмес­то это­го она чита­ет всю стра­ницу целиком (имен­но стра­ницу, а не сек­тор, пос­коль­ку про­еци­рова­ние PE-фай­лов осу­щест­вля­ется на уров­не стра­ниц). Теоре­тичес­ки сис­тема мог­ла бы очис­тить хвост сек­ции, забив его нулями и сох­ранив толь­ко пер­вые 10h байт физичес­кого раз­мера, но... к чему все эти телод­вижения? Спе­цифи­кация ведь не обя­зыва­ет, а потому хвост сек­ции исправ­но гру­зит­ся в память.

А вот дизас­сем­бле­ры ведут себя ина­че. Сле­по сле­дуя спе­цифи­кации, они гру­зят толь­ко 10h байт. Осталь­ные бай­ты либо вооб­ще не заг­ружа­ются, либо прев­раща­ются в нули. Это откры­вает огромные пер­спек­тивы для сок­рытия кода, который не пред­полага­ется видеть ревер­серам и анти­виру­сам. Во вся­ком слу­чае, на этот трюк ловит­ся IDA Pro (вплоть до вер­сии 5.3 — пос­ледней на момент написа­ния этих строк), HIEW, DUMPBIN и куча дру­гих.

 

В поисках лома

«Про­тив лома нет при­ема», говорят одни, а дру­гие ехид­но добав­ляют: «если нет дру­гого лома». Но в нашем слу­чае все еще более позитив­но. У нас есть при­ем (про­тив дизас­сем­бле­ров), но нет под­ходяще­го лома. Какой инс­тру­мент ни возь­ми — сплош­ной облом. Во вся­ком слу­чае, в авто­мати­чес­ком режиме, с которо­го, собс­твен­но говоря, мы и нач­нем.

А нач­нем мы с про­вер­ки работос­пособ­ности прог­раммы, запущен­ной в живой сис­теме безо вся­ких левых отладчи­ков. Как и сле­дова­ло ожи­дать, файл запус­кает­ся нор­маль­но (тес­тировал­ся под W2K, S2K3 и XP), выводя на экран мес­седж‑бокс с заголов­ком «.no pain -- no gain.» и лозун­гом «condom-principle: it’d rather have one and not need it that need it and not have one».

Результат работы программы KedaH3.exe, запущенной без отладчиков, под «живой» операционной системой
Ре­зуль­тат работы прог­раммы KedaH3.exe, запущен­ной без отладчи­ков, под «живой» опе­раци­онной сис­темой

Ну, condom нам в бли­жай­шие нес­коль­ко часов не понадо­бит­ся, а вот дизас­сем­блер — очень даже. Никако­го рис­ка тут нет, пос­коль­ку crackme пред­став­ляет собой три­виаль­ный вызов MessageBoxA.

Бе­рем HIEW — прос­той как топор; гру­зим файл, при­выч­ным дви­жени­ем руки перек­люча­емся в HEX-mode (Enter) и перехо­дим в точ­ку вхо­да — F8 (Header), F5 (Entry). Опс... Не перехо­дит­ся! То есть вооб­ще никуда не перехо­дит­ся. Там, где сто­яли, — там и оста­лись. При­чем точ­ка вхо­да смот­рит по впол­не легаль­ному адре­су 401010h, рас­положен­ному в 10h бай­тах от начала сек­ции .text, что вид­но из заголов­ка, вызыва­емо­го нажати­ем F8.

По непонятным причинам HIEW отказывается переходить в точку входа, и нам приходится определять целевой адрес самостоятельно
По непонят­ным при­чинам HIEW отка­зыва­ется перехо­дить в точ­ку вхо­да, и нам при­ходит­ся опре­делять целевой адрес самос­тоятель­но

Лад­но! Не хочет работать HIEW, и не надо. Вызыва­ем «тяжелую артилле­рию» — «Иду». И со все­го маху фей­сом об тей­бл: «The input file contains non-empty TLS (Thread Local Storage) callback table. However, IDA Pro couldn’t find the TLS callback procedures in the loaded code» — «Ана­лизи­руемый файл содер­жит не пус­тую таб­лицу TLS-callback’ов, одна­ко IDA Pro обло­малась с поис­ком TLS-callback’ов в заг­ружен­ном фай­ле».

Ругательство, выдаваемое IDA Pro в процессе загрузки KedaH3.exe
Ру­гатель­ство, выдава­емое IDA Pro в про­цес­се заг­рузки KedaH3.exe

По­кор­но жмем ОK, что­бы зак­рыть про­тив­ное диало­говое окно, и получа­ем пус­той дизас­сем­блер­ный лис­тинг.

Так выг­лядит KedaH3.exe пос­ле заг­рузки в IDA Pro — из всех инс­трук­ций одна RETN, тек­сто­вых строк нет
.text:00401000 _text segment para public 'CODE' use32
.text:00401000 assume cs:_text
.text:00401000 ;org 401000h
.text:00401000 assume es:nothing, ss:nothing, ds:_data, fs:nothing, gs:nothing
.text:00401000 retn
.text:00401000
.text:00401001 dd 3 dup(?)
.text:0040100D db 3 dup(?)
.text:00401010 public start
.text:00401010 start dd 8 dup(?)
.text:00401010 _text ends

Лис­тинг не то что­бы сов­сем пус­той, но оди­нокий RET, к тому же рас­положен­ный перед точ­кой вхо­да, нас как‑то не воз­бужда­ет. Где MessageBoxA? Где наша тек­сто­вая стро­ка? Нету! Даже TLS Callback’ов и тех не хва­тает, о чем, впро­чем, нас уже пре­дуп­режда­ли.

Об­речен­но заг­ружа­ем KedaH3.exe в «Оль­гу», и... отладчик тупо вис­нет. Опра­вив­шись пос­ле шока, замеча­ем, что вис­нет не сам отладчик, а отла­жива­емый про­цесс, вызывая 100%-ю заг­рузку ЦП. В перево­де на рус­ский — один хрен раз­ница. Прак­тичес­ки все пун­кты меню выделе­ны серым (то есть недос­тупны), окно дизас­сем­бле­ра и дам­па выг­лядит абсо­лют­но некошер­но, и вооб­ще непонят­но, как с этим жить и что теперь делать.

Загрузка KedaH3.exe в «Ольгу» приводит к зацикливанию отлаживаемого процесса и 100%-й загрузке ЦП
Заг­рузка KedaH3.exe в «Оль­гу» при­водит к зацик­ливанию отла­жива­емо­го про­цес­са и 100%-й заг­рузке ЦП

Вы­ходит, что KedaH3.exe (сос­тоящий все­го из двух дюжин ассем­блер­ных инс­трук­ций) активно про­тивос­тоит всем основным хакер­ским ору­диям — отладчи­кам, дизас­сем­бле­рам и дам­перам, но работа­ет под любой вер­сией Windows.

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

Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

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

Вариант 2. Открой один материал

Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.


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

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

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии