Ковыряем Windows по примеру известных руткит-мейкеровАлександр Эккерт, stannic.man@gmail.com В основе функционирования современных операционных систем лежит виртуальная память. Именно она позволяет адресовать в 32-битных системах 4 гигабайта виртуального адресного пространства. А 64-битная адресация, в свою очередь, позволяет использовать практически неограниченное количество виртуальной памяти. Сегодня мы поговорим об основном способе организации виртуальной памяти — страничном, при котором единицей отображения виртуальных адресов на физические является регион постоянного размера (так называемая страница). Поддержка такого режима присутствует в большинстве современных процессоров, и он является классическим для почти всех современных ОС, в том числе Windows. В статье мы попытаемся рассмотреть, как этот «классический» аргумент можно использовать в своих грязных целях. Введение, или о чем это мы?В большинстве современных операционных систем, в том числе, в семействе ОС Windows виртуальная память организуется с помощью страничной адресации. Если говорить коротко и понятно, то данные в памяти в Windows существуют: 1) в виртуальном виде размером в 4 гигабайта и 2) в проекции этих самых данных в памяти физической и, наконец, в виде так называемых страниц. Что такое страницы? Это области памяти фиксированной длины (как правило, или 4 Кб, или 4 Мб), которые являются минимальной единицей выделяемой памяти (то есть, даже запрос на 1 байт от приложения приведет к выделению ему страницы памяти). Процесс обращается к памяти с помощью адреса виртуальной памяти, который содержит в себе номер страницы и смещение внутри страницы. Операционная система преобразует виртуальный адрес в физический, при необходимости подгружая страницу с жесткого диска в оперативную память. При запросе на выделение памяти операционная система может сбросить на жесткий диск страницы, к которым давно не было обращений. Соответствующие единицы в физической памяти образуют страничные кадры (page frames), а система поддержки страничной виртуальной памяти называется пейджингом (paging). Передача информации между памятью и диском всегда осуществляется целыми страницами. Главное, что надо уяснить - данные, представленные в виртуальной памяти, на самом деле находятся в памяти физической (оперативной или сброшены на жесткий диск) и для доступа к ним процессор использует механизм страничной трансляции. Таким образом, операция записи в память какого-либо процесса в конечном итоге сведется к записи страниц, принадлежащих этому процессу и находящихся в где-то в физической памяти. Если вдуматься, то получается, что данные находятся как бы в дублированном состоянии (хотя это не так): непосредственно сами данные лежат в памяти физической, и они же представлены в памяти виртуальной. А раз основная организация виртуальной памяти есть страничная память, что нам помешает, не трогая виртуальных адресов, найти сами физические страницы, содержащие нужные нам данные и использовать (читай – «перезаписать или подменить») их по своему усмотрению? Да ничего! Ни антивирусы, ни проактивки, ни файрволы нам не помеха! В итоге мы получим стелс-технологию, которая может беспалевно подменять нужные нам данные в адресном пространстве процесса. Разбираем устройство виртуальной памятиЧтобы применять эту технику на практике, конечно же, нужно понять основы — правила организации и механизм работы виртуальной и страничной адресации. Не вдаваясь в подробности механизма страничной адресации (он довольно сложен для понимания), отмечу только, что в его основе используется двухуровневая табличная трансляция линейного адреса в физический. Этот механизм имеет три части: каталог страниц (Page Directory, PDE), таблицы страниц (Page Table, PTE) и собственно страницы (Page Frame). Тем, кто хочет досконально разобраться в механизме страничной трансляции, могу порекомендовать мануалы INTEL'а по системному программированию; их ты можешь найти на сайте www.intel.com или на нашем диске. Как же можно заполучить доступ к этим каталогам - PDE и PTE? Очень легко! Любителям лаконичности можно посоветовать вот такой способ обретения указателя на таблицы страниц PTE: Стоит, наверное, пояснить. Допустим, у нас есть линейный 32-байтный адрес: В ядре существует целый набор системных функций, предназначенных для работы с памятью, как физической, так и виртуальной. Все они имеют префикс Mm*. В юзермоде тебе должны быть знакомы функции WriteProcessMemory и ReadProcessMemory, хотя на самом деле они являются «заглушками» для вызова сервисов ядра. Например, функция MmGetPhysicalAddress вернет физический адрес, соответствующий виртуальному адресу, находящемуся в неподкачиваемой памяти. Системная функция ядра - MmIsAddressValid() - всего-навсего проверяет, представлена ли страница в физической памяти, т.е. не сработает ли исключение «Page Fault» при обращении по указанному виртуальному адресу. Если страницы нет, то функция вернет FALSE. Также интересна функция MmIsNonPagedSystemAddressValid, которая в отличие от MmIsAddressValid проверяет то, что переданный ей адрес принадлежит подкачиваемой или неподкачиваемой областям памяти ядра. Так, затрагивая тему работы с виртуальной/физической памятью, хотелось бы заметить, что у страниц в памяти может быть несколько состояний. Перечислим их! Способ раз, или «Поймай меня, если сможешь!»В момент обращения страница может присутствовать в физической оперативной памяти, а может быть выгруженной на внешнюю (дисковую) память. При обращении к выгруженной странице памяти процессор генерирует исключение #PF — «Page Fault» или отказ страницы, а программный обработчик исключения (часть ОС) получит необходимую информацию для свопинга — «подкачки» отсутствующей страницы с диска. И самое главное - страницы не имеют прямой связи с логической структурой данных или программ. Абсолютно стандартное поведение менеджера виртуальной памяти! И ведь кто бы мог подумать - эта «особенность» виртуальной памяти ОС Windows используется в руткитостроении. Каким образом? Если ты знаешь, список системных модулей (читай - драйверов) ядра можно получить, вызвав системную функцию NtQuerySystemInformation c параметром SystemModuleInformation или открыв директорию «\Driver» вызовом ZwQueryDirectoryObject. Также можно пробежаться по системному списку PsLoadedModuleList (расписывать эти способы не буду, тема статьи другая, если интересно - за подробностями в Гугл). Все известные способы сокрытия драйвером заключались в патче указанных функций или исключении имени модуля из PsLoadedModuleList. Но вот на свет появился Shadow Walker - руткит уровня ядра. Главной его особенностью является способ сокрытия в ядре нужных хакеру данных - как правило, Shadow Walker скрывает другой драйвер руткита FU. Это, с позволения сказать, революционное решение заключается в следующем. Загруженный драйвер руткита ставит перехват на прерывание INT0E и помечает нужные физические страницы как «не представленные в памяти» - и в случае обращения менеджера виртуальной памяти к этим самым страницам, где лежит драйвер, будет сгенерировано то самое исключение - #PF или «PageFault». Здорово, правда? Когда произойдет ошибка страницы (при ее чтении) в связи с тем, что PTE помечен как недействительный, Shadow Walker определяет, является ли страница той, которую необходимо скрыть; если да, то подменяются данные на странице. Если происходит выполнение на странице кода руткита, Shadow Walker просто помечает PTE как действительные и дает процессору доступ к странице. Правда, проблема здесь в сложности определения, что именно понадобилось процессору: прочесть данные или выполнить код. Разработчиками Shadow Walker было решено и это; для ознакомления сорцы руткита лежат на диске, думаю, ты сможешь разобраться сам. Убираем бит представления страницы в памятиЧто ж, поехали!
Эффективность руткита такова, что до сих пор вычислить его присутствие в оперативной памяти может лишь сигнатурный поиск по всей физической памяти или использование гипервизора. Много ли современных антивирусов способны на подобное? Если учесть, что зачастую данные в силу фрагментированности разбросаны по всему жесткому диску, а гипервизор - неподъемная задача, то руткит оказывается не под силу обычным антивирусам. Вычислить присутствие этого руткита в оперативной памяти до сих пор может лишь сигнатурный поиск по всей физической памяти или использование гипервизора. Много ли антивирусов способны на подобное? Существует и программный поиск сокрытых Shadow Walker страниц в памяти; более подробно об этом можно почитать здесь http://www.ht-group.net/32, однако он ненадежен. Способ два, или «Не верь глазам своим»Теперь перейдем ко второму, крайне интересному, но практически неизвестному в широких кругах способу манипуляций с содержимым виртуальной памяти. Находясь в ядре, мы всегда сможем попасть в адресное пространство любого процесса, вызвав функцию KeAttachProcess. Что она делает, я думаю, ты понимаешь. Также уверен, что тебе знакома такая фича, когда, находясь в адресном пространстве, ты можешь относительно безопасно писать данные вызовом функции ZwWriteProcessMemory, - ][ уже писал об этом. Но, увы и ах! Всякий мало-мальски нормальный антивирус обычно хукает такую опасную функцию, ибо ее использование стоит на первом месте у злых кодеров. Но теперь (и я хочу, чтобы ты прочувствовал всю значимость момента!), используя форму организации страничной памяти, можно изменять данные в адресном пространстве без записи данных; ведь надо просто подменить PTE нужного нам виртуального адреса! Здесь виртуальная память процесса останется нетронутой, но при обращении к адресу подмены менеджер памяти вернет запрашивающему те данные, которые нам нужно подсунуть! Смотрим код: Подмена страниц PTE по нужному адресу
Вот в принципе и все. Если немного постараться, то можно немного сократить и усовершенствовать этот код. Столь простая, но крайне эффективная техника может легко использоваться для подмены данных в адресном пространстве процесса (сколько простора для геймчитеров!) или вызывать напрямую похуканые проактивными защитами важные системные функции. Путешествие в ЗазеркальеНа примере этой статьи можно видеть, что мир процессов - а это игры, антивирусные программы, да все что угодно, что крутится в таскменеджере Windows - довольно зыбок и нельзя однозначно полагаться на то, что ты видишь собственными глазами. В общем, «The matrix has you, Neo!». Мир виртуальной памяти Windows поистине захватывает, и путешествие в его глубины сродни путешествию в Зазеркалье. Приложишь немного усилий - и тебе станет подвластна вся операционная система. Удачного компилирования и да пребудет с тобой Сила! DVDНа диске ты сможешь найти литературу, которая поможет в отладке и дебаге твоего кода. Обещанные сорцы руткита Shadow Walker ждут тебя там же. WWWХочешь знать все-все о памяти в Windows? Бегом на http://gr8.cih.ms/index.php?entry=entry008 - лучше этой статьи админа форума wasm.ru под ником Great не найти. Также замечательная статья по управлению памятью в ОС Windows, правда, на английском - http://www.informit.com/articles/article.aspx?p=167857. INFOБудь осторожен при опытах с виртуальной памятью! |