Каждый, кто пользовался Windows, хорошо знает, что такое ярлык. Однако этот значок со стрелкой далеко не так прост, как может показаться, и при определенных условиях он открывает широкие возможности для атакующего. Я расскажу, как сделать «ядовитый» ярлык и как с помощью флешки выполнять произвольный код на целевой системе.
 

Исторический экскурс

Все началось еще в 2010 году, когда в паблике всплыл эксплоит для Windows версий 7 и ниже. Эксплоит позволял атакующему выполнить произвольный код в системе, причем пользователю достаточно было всего лишь перейти по ссылке.

Этот эксплоит использовался как один из вариантов распространения небезызвестного червя Stuxnet. Когда кто-то вставлял флешку в компьютер, червь заражал ее, копируя вредоносный DLL, и создавал специальный ярлык. Если на машине, в которую потом вставляли носитель, была включена функция автозапуска, вредоносный код из библиотеки выполнялся.

Импакт при этом не ограничивался одной только флешкой: код также срабатывал, если пользователь посещал вредоносный URL, который указывал на сетевую или локальную папку с эксплоитом.

Взглянув на весь этот ужас, в Microsoft выпустили апдейт MS10-046, который исправляет эту уязвимость. Вот только получилась заплатка не то чтобы удачной.

В начале января 2015 года немецкий исследователь Михель Герклоц (Michael Heerklotz) детально изучил этот патч и нашел способ его обойти. Результатом работы Герклоца стал отчет на конференции Zero Day Initiative (ZDI), проводимой компанией HP. После исправления патча в марте того же 2015 года исследование было опубликовано. Имеется даже видеодемонстрация работы эксплоита.

После этого в Microsoft выкатили следующий патч — с порядковым номером MS15-018, однако и он не смог полностью закрыть уязвимость. Совсем недавно, в июне 2017 года, был обнаружен очередной способ его обхода. Импакт при этом остался тем же — выполнение произвольного кода на целевой системе.

Уязвимость откликается на CVE-2017-8464, а PoC-эксплоит создали Йорик Костер (Yorick Koster) и nixawk. Йорик также написал модуль для Metasploit. MSF я не использую по религиозным соображениям и поэтому в обзоре буду опираться на первоначальный сплоит. Найти его ты сможешь, заглянув в репозиторий к nixawk.

Если же хочешь просто потриггерить уязвимость, то здесь есть готовые LNK-файлы и DLL, которая запускает калькулятор. Тебе остается лишь скинуть их на флешку.

WARNING

Материал адpесован специалистам по безопасности и тем, кто собираeтся ими стать. Вся информация предоставлена исключительно в ознакомительных целях. Ни редакция, ни автор не несут ответственности за любой возможный вред, причиненный материалами данной статьи.

 

Стенд

В качестве подопытного кролика для теста уязвимости я буду использовать виртуалку с Windows 10 х64.

Уязвимая версия Windows 10 x64
Уязвимая версия Windows 10 x64

При работе с бинарщиной нам, конечно же, пригодится дизассемблер. Не будем оригинальничать и возьмем IDA.

Также нам понадобится какой-нибудь дебаггер. Я решил использовать WinDbg в режиме отладчика ядра. Вот один из способов настроить удаленный дебаггинг виртуалки.

  1. Запустить WinDbg. Затем File → Kernel Debug. Там во вкладке NET нужно указать порт. Его будет слушать программа в ожидании подключения от отлаживаемой системы. Еще можно указать ключ для шифрования передаваемых данных во время соединения.

    Настройка отладки ядра по сети в WinDbg
    Настройка отладки ядра по сети в WinDbg
  2. Включить режим отладки на гостевой машине. В этом нам поможет консольная утилита bcdedit.

    bcdedit /debug on
    bcdedit /dbgsettings net hostip:127.0.0.1 port:50000 key:time.to.debug.1337

где hostip — IP хостовой ОС, port и key — порт и ключ, которые ты указал в настройках WinDbg. После перезагрузки виртуалки она подключится к отладчику.

Гостевая ОС готова к отладке
Гостевая ОС готова к отладке
 

Особенности линкования

Чтобы понимать уязвимость и успешно ее проэксплуатировать, нужно сначала разобраться непосредственно с самим форматом LNK-файлов. К счастью, нам не придется продираться через дебри бинарщины вслепую, потому что ребята из Microsoft позаботились и написали подробную техническую спецификацию под названием Shell Link (.LNK) Binary File Format. Будем заглядывать туда периодически.

Еще нам понадобится утилита для просмотра детальной информации по файлам LNK. Так как моя основная ОС — это Windows 10, то я воспользуюсь приложением LNKParser. Если ты ищешь что-то платформонезависимое, то попробуй модуль pylnk (pip install pylnk) для Python.

Shell Link Binary File Format состоит из последовательности структур, которые регулируются правилами ABNF (Augmented Backus-Naur Form). Правила же описаны в спецификации RFC5234.

SHELL_LINK = SHELL_LINK_HEADER [LINKTARGET_IDLIST] [LINKINFO] [STRING_DATA] *EXTRA_DATA

Совокупность этих структур и называется shell link, а в простонародье — «ярлык».

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

Рассмотрим все это на живом примере. Для этого создадим ярлык на любой файл (я создал для explorer.exe) и натравим на него LNKParser.

lnk_parser_cmd "explorer.exe - Shortcut.lnk"
Просмотр содержимого ярлыка с помощью LNKParser
Просмотр содержимого ярлыка с помощью LNKParser

Здесь я рассмотрю только нужные для создания эксплоита структуры, ты же можешь покопаться в тонкостях строения .LNK в свое удовольствие.

За загрузку, анализ и парсинг данных из файла ярлыка отвечает функция CShellLink::_LoadFromStream из библиотеки windows.storage.dll.

Функция парсинга содержимого LNK-файла
Функция парсинга содержимого LNK-файла

Первый обязательный блок, который должен присутствовать в каждом уважающем себя LNK-файле, — это SHELL_LINK_HEADER. По большому счету это единственная обязательная структура в ярлыке. Она содержит идентификационную информацию, временные метки и флаги, которые определяют наличие или отсутствие дополнительных блоков с информацией, включая LinkTargetIDList, LinkInfo и StringData.

Структура блока SHELL_LINK_HEADER
Структура блока SHELL_LINK_HEADER

Пройдемся по остальным структурам.

  • HeaderSize (4 байта) — размер блока Header, он фиксированный — 0x0000004C.
  • LinkCLSID (16 байт) — уникальный идентификатор класса (CLSID). Структура CLSID — это оболочка для идентификатора COM-класса. Также имеет фиксированное значение — 00021401-0000-0000C000-000000000046.
  • LinkFlags (4 байта) — флаги, которые отвечают за опции ярлыка. Некоторые флаги означают наличие дополнительных структур в файле.
  • FileAttributes (4 байта) — атрибуты файла, на который ссылается ярлык.
  • CreationTime (8 байт), AccessTime (8 байт), WriteTime (8 байт) — время создания файла, последнего доступа к нему и его изменения.
  • FileSize (4 байта) — размер файла. Формат — 32-битное беззнаковое целое.
  • IconIndex (4 байта) — индекс иконки файла в указанном хранилище. Формат — 32-битное беззнаковое целое.
  • ShowCommand (4 байта) — вид окна приложения, запущенного через ярлык. Формат — 32-битное беззнаковое целое. Он может быть трех видов: нормальный (SW_SHOWNORMAL, 0x00000001), развернутый на весь экран (SW_SHOWMAXIMIZED, 0x00000003), свернутый (SW_SHOWMINNOACTIVE, 0x00000007).
  • HotKey (2 байта) — структура HotKeyFlags отвечает за назначенные ярлыку горячие клавиши. В настройках линка ты можешь указать требуемое сочетание клавиш, и если сам LNK лежит на рабочем столе или в меню, то при их нажатии он будет срабатывать.
  • Reserved1 (2 байта), Reserved2 (4 байта), Reserved3 (4 байта) — зарезервированные значения. Должны быть нулевыми.

Из всего этого многообразия нас интересует только LinkFlags. Секция состоит из 32 бит, каждый из которых отвечает за разные опции ярлыка.

Битовая маска секции LinkFlags
Битовая маска секции LinkFlags

Нужные нам биты — это 0 (HasLinkTargetIDList) и 7 (IsUnicode).

Важные для эксплуатации флаги
Важные для эксплуатации флаги

С IsUnicode, думаю, все ясно из названия, а вот нулевой бит рассмотрим подробнее.

Флаг HasLinkTargetIDList указывает, что следующим блоком, идущим за хидером, будет структура IDList.

Структура IDList в файле легитимного ярлыка
Структура IDList в файле легитимного ярлыка

Функция CShellLink::_LoadIDList сначала читает первые два байта данных из блока (это размер структуры) и выделяет требуемое количество памяти для его загрузки.

Функция CShellLink::_LoadIDList для парсинга содержимого структуры IDList
Функция CShellLink::_LoadIDList для парсинга содержимого структуры IDList

Затем начинается чтение данных из LINKTARGET_IDLIST. Каждый элемент этой структуры — это часть пути до объекта, на который ссылается ярлык. Система проходит по каждому такому элементу ItemID и читает его данные.

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

Вариант 1. Оформи подписку на «Хакер», чтобы читать все статьи на сайте

Подписка позволит тебе в течение указанного срока читать ВСЕ платные материалы сайта, включая эту статью. Мы принимаем оплату банковскими картами, электронными деньгами и переводами со счетов мобильных операторов. Подробнее о подписке

Вариант 2. Купи одну статью

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


3 комментария

Подпишитесь на ][, чтобы участвовать в обсуждении

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

Check Also

Tips’n’Tricks из арсенала андроидовода. Самые интересные, полезные и нестандартные трюки с Android

Многие годы мы рассказывали про самые разные способы оптимизировать, модифицировать и твик…