Старые антиотладочные приемы на новый лад

проецирование физической памяти на виртуальное адресное пространство


Единственная проблема — это трансляция адресов (перевод физических адресов в виртуальные и наоборот). NT предоставляет доступ только к физической памяти до трансляции, а, поскольку, физическая память используется как кэш, то одни и те же физические страницы в разное время могут отображаться на различные виртуальные адреса многих адресных пространств. "Официально" трансляцией занимается функция MmGetPhysicalAddress, доступная только на уровне ядра, что нас, — прикладников, — естественно, не устраивает. Тем не менее, ситуация вовсе не так безнадежна, как это кажется на первый взгляд.

Для большинства задач искать соответствие между физическими и виртуальными адресами вообще не нужно! Ведь существуют же сигнатуры! Достаточно создать банк сигнатур всех популярных отладчиков после чего их обнаружение не станет проблемой, а большинство служебных структур типа таблицы дескрипторов прерываний (IDT) вообще работают с физическими адресами. Найти их путем сканирования PhysicalMemory — не проблема. После чего останется только поиздеваться над прерываниями int 01h и int 03h (или над их обработчиками). Прием, конечно, грубый и убивающий любые отладчики независимо от того отлаживают ли они нашу программу или нет. Правильные программисты так не поступают! Защитные механизмы не должны, просто не имеют морального (и отчасти даже юридического) права мешать отладке посторонних программ, но... Зачастую, они все-таки мешают. Так что сказанное надо воспринимать не как руководство к действию, а как пособие по ремонту чужих защит. О взломе в данном случае никто и не говорит. Почему я, — легальный пользователь защищенной программы, заплативший за нее деньги — не могу держать ко компьютере soft-ice?! Почему я должен каждый раз перезагружать компьютер для работы с программой?!

Впрочем, все это лирика. В некоторых случаях (например, для борьбы с отладчиками прикладного уровня) выполнять трансляцию все-таки необходимо. Это не так-то просто сделать! Статья "Playing with Windows /dev/(k)mem" из PHRACK'а (http://www.phrack.org/phrack/59/p59-0x10.txt ) дает некоторые зацепки, частично решающие проблемы, но до полной победы еще далеко.

Проще всего транслируются адреса из диапазона 80000000h:A0000000h. Перевод виртуального адреса в физический осуществляется путем наложения маски 1FFFF000h, однако, начиная с адреса 877EF000h это правило срабатывает не всегда. Адреса < 80000000h и >
 A0000000h уже не могут быть транслированы таким путем, хотя с некоторой вероятностью маска FFFF000h все-таки срабатывает и простейший вариант реализации функции __GetPhysicalAddress выглядит так:

PHYSICAL_MEMORY MyGetPhysicalAddress(void *BaseAddress)

{

       if (BaseAddress < 0x80000000 || BaseAddress >
= 0xA0000000)

       {

              return(BaseAddress & 0xFFFF000);

       }

      

       return(BaseAddress & 0x1FFFF000);

}



Содержание раздела