Содержание статьи
Исполняемые файлы, динамические библиотеки и драйверы — все они «крышуются» одним и тем же форматом, проходящим под кодовым названием 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».
Ну, condom нам в ближайшие несколько часов не понадобится, а вот дизассемблер — очень даже. Никакого риска тут нет, поскольку crackme представляет собой тривиальный вызов MessageBoxA
.
Берем HIEW — простой как топор; грузим файл, привычным движением руки переключаемся в HEX-mode (Enter) и переходим в точку входа — F8 (Header), F5 (Entry). Опс... Не переходится! То есть вообще никуда не переходится. Там, где стояли, — там и остались. Причем точка входа смотрит по вполне легальному адресу 401010h, расположенному в 10h байтах от начала секции .text, что видно из заголовка, вызываемого нажатием F8.
Ладно! Не хочет работать 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’ов в загруженном файле».
Покорно жмем О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 (состоящий всего из двух дюжин ассемблерных инструкций) активно противостоит всем основным хакерским орудиям — отладчикам, дизассемблерам и дамперам, но работает под любой версией Windows.
Продолжение доступно только участникам
Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
Вариант 2. Открой один материал
Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.
Я уже участник «Xakep.ru»