Абсолютный ноль Николай «GorluM» Андреев Хакер, номер #072, стр. 072-068-4 Дело в том, что в винде есть один очень интересный объект - \\Device\\PhysicalMemory. Это устройство позволяет получить полный доступ к физической памяти – нужно только дать себе необходимые права и открыть этот объект с помощью функции NtOpenSection (Native API). Очень неплохо, ведь где-то в физической памяти есть и наши таблицы, жалко только, что у нас их виртуальные адреса, а тут нужны физические, что далеко не одно и то же. Поэтому придется реализовывать свою функцию для перевода одних адресов в другие. В 59-ом номере журнала Phrack, к примеру, такая функция выглядит вот так: Перевод виртуальных адресов в физические PHYSICAL_ADDRESS GetPhysicalAddress(ULONG vAddress) { PHYSICAL_ADDRESS add; if (vAddress < 0x80000000L || vAddress > = 0xA0000000L) { add.QuadPart = (ULONGLONG) vAddress & 0xFFFF000; } else { add.QuadPart = (ULONGLONG) vAddress & 0x1FFFF000; } return(add); } Итак, похоже, наша мозаика, наконец, решила сложиться. Мы знаем, как модифицировать таблицу, знаем ее адрес, умеем получать к ней доступ – что еще нужно? А ничего, осталось все это дело реализовать и прыгать от счастья на нулевом уровне привилегий. API в ring0 Оказавшись в долгожданном привилегированном режиме процессора, понимаешь – здесь можно все, но как это «все можно» – не понимаешь. В user mode было АПИ, с помощью которого осуществлялось взаимодействие с системой, а что делать в kernel mode? Благо хоть над этой задачей долго биться не придется – на уровне ядра тоже есть свое АПИ. Функций, правда, в нем на порядок больше, чем в старом добром kernel32.dll, – тут и функции для работы со структурой процессов, и хитрые процедуры для обеспечения работы драйверов. Практически все они располагаются в ntoskrnl.exe, даже по такому коротенькому названию файла понятно – это ядро. Есть, конечно, функции и в ntdll.dll, но в основном они все импортируются из ядра. Если ты переходишь в нулевое кольцо с помощью драйвера, то проблем с поиском адресов этих функций у тебя не должно возникнуть. Все функции описаны в lib’ах в комплекте DDK и будут добавлены в таблицу импорта драйвера. А как же быть нам, хакерам? Мы же драйверов писать не хотим. А раз не хотим, придется нам все адреса функций искать вручную. Ntoskrnl.exe всегда загружен в системе, но находится выше двух гигабайт памяти, поэтому обычной функцией GetProcAddress тут не обойтись. Все чуточку хитрее. Нужно подгрузить ntoskrnl к нашему приложению с помощью LoadLibrary и найти смещение функции в нем, а затем прибавить полученное значение к оригинальному адресу образа ядра, который можно узнать с помощью функции, экспортируемой ntdll и доступной из ring3, – NtQuerySystemInformation (подробное описание читай в книге Гари Нэббета). Ну а получив адрес функции, с ней можно что-нибудь сотворить – к примеру, запустить… или перехватить. Когда я писал свою программу, у меня было отличное настроение и я не был настроен на дестрой, поэтому для пробы я решил с помощью АПИ сменить имя своему процессу. Чтобы это сделать, мне понадобилось найти адрес ядерной функции PsGetCurrentProcess (префикс Ps означает, что функция предназначена для работы со структурой процессов), которая возвращает объект ядра типа EPROCESS. Этот объект содержит все данные о моем процессе, и при желании их можно поменять на что угодно. Меня интересовало имя процесса, иначе – image name. Но вот незадача – описание структуры EPROCESS менялось в зависимости от версии винды, поэтому нельзя было точно сказать, где именно находится в этой структуре необходимое мне имя процесса в моем новеньком ХП. Поэтому мне пришлось вычислять смещение имени в структуре с помощью обыкновенного поиска подстроки. Таким образом я нашел в этом объекте старое имя и сменил его на торжественное «Hacked by gorl». Кстати, на нашем диске есть программа, написанная небезызвестным кодером 90210 и опубликованная ранее в вирусном е-зине 29А, которая грамотно переключается в ринг0 и меняет либо вообще убирает имя заданного процесса. |