Различия

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

Ссылка на это сравнение

articles:msr-hacker [2017/09/05 02:55] (текущий)
Строка 1: Строка 1:
 +====== MSR-hacker ======
 +<​sub>​{{MSR-hacker.odt|Original file}}</​sub>​
 +
 +====== MSR-регистры на службе хакера ======
 +
 +крис касперски ака мыщъх, a.k.a. nezumi, a.k.a. souriz, no-email
 +
 +**популярные дебагеры (****soft-ice,​ syser, olly) ****используют базовые отладочные возможности,​ появившиеся еще в 80386 и совершенно игнорируют тот факт, что процессоры изрядно подросли и обросли целым комплексом отладочных механизмов термоядерного типа, реализованных в виде нестандартных расширений,​ управляемых посредством специальных ****MSR-****регистров с помощью которых мы можем перехватывать системные вызовы,​ трассировать ветвления в реальном времени,​ дампить содержимое регистров общего назначения на каждом такте и делать еще множество других удивительных вещей, существенно упрощающих взлом защищенных программ**
 +
 +//​бывает,​ что человек пытается решить какую-то проблему,​ хотя она решена уже тысячи лет назад. а он просто об этом не знает. или не понимает,​ что это именно его проблема.//​
 +
 +//​Виктор Пелевин,​ "​Желтая Стрела"//​
 +
 +===== введение =====
 +
 +Количество регистров Pentium-процессоров вплотную приближается к тысяче и хотя значительная часть из них носит сугубо служебный характер,​ сути дела это не меняет. Часть регистров стандартизирована и реализована во всех моделях (например,​ EAX, CR3, DR1), часть — специфична для определенной группы процессоров и совместимость с другими процессорами негарантированна,​ хотя все они продаются под торговой маркой Pentium. Вот о таких специфичных регистрах мы и поговорим.
 +
 +В технической документации они скрываются за аббревиатурой **MSR** – //​**M**////​odel ////​**S**////​pecific ////​**R**////​egister(s)//,​ и впервые такие регистры появились (если мне не изменяет память) в P6, более известном как Pentium Pro и его "​бюджетном"​ собрате Pentium-II. Революции не свершилось,​ но команда RDTSC с тех времен прочно вошла в лексикон всех разработчиков защит. Специальный MSR-регистр каждый такт увеличивает свое значение на единицу,​ а команда RDTSC позволяет прикладным программам считывать его содержимое. Как результат — при пошаговом прогоне защищенного кода под отладчиком,​ кол-во "​тиков"​ процессора между двумя соседними замерами резко возрастала и защита палилит хакера только так.
 +
 +Разработчики Xenon-процессоров (используемых главным образом в серверах и высокопроизводительных рабочих станциях) совершили огромный бросок вперед,​ сотворив новые отладочные механизмы,​ глядя на которые обладатели Pentium-II/​III только облизывались. Но с появлением Pentium-4 эти возможности,​ хлынув в бюджетную сферу, стали доступными всем и каждому,​ к чему создатели отладчиков ни морально,​ ни физически,​ ни технически оказались не готовы.
 +
 +К счастью,​ большинство дебагеров поддерживают подключаемые модули,​ позволяя нам дописать весь необходимый функционал самостоятельно,​ однако,​ использование MSR-регистров не ограничивается одной лишь отладкой и, как мы увидим по ходу статьи,​ они интересы и создателям rootkit'​ов,​ а так же разработчикам самих защит.
 +
 +{{msr-hacker_Image_0.jpg}}
 +
 +Рисунок 1 мыщъх (a.k.a.Chuha на Хинди) за работой
 +
 +===== >>>​ врезка что нам понадобится =====
 +
 +Для экспериментов,​ описанных в статье,​ нам понадобятся следующие вещи, программы и инструменты:​
 +
 +  - **Windows Driver Kit (WDK) ****для всех систем по Вислу включительно:​**
 +    - __http://​www.microsoft.com/​whdc/​DevTools/​default.mspx__ (требует регистрации);​
 +  - **Windows Server 2003 SP1 DDK:**
 +    - __http://​www.microsoft.com/​whdc/​devtools/​ddk/​default.mspx__;​
 +  - **IA-32 Architecture Software Developer'​s Manual Vol****. ****3: System Programming Guide****:​**
 +    - __http://​www.intel.com/​products/​processor/​manuals/​____;​__
 +  - DebugView:
 +    - __http://​technet.microsoft.com/​en-us/​sysinternals/​bb896647.aspx__;​
 +  - **KmdManager – ****утилита динамической загрузки/​выгрузки драйверов:​**
 +    - __https://​wasm.ru/​pub/​21/​files/​kmd3.zip;​__
 +  - **Syser 1.95.19000.0894**:​
 +    - __http://​www.sysersoft.com/​download/​download.php__;​
 +  - **Soft-Ice**:​
 +    - __www.google.com__;​-)
 +===== чтение и запись MSR-регистров =====
 +
 +MSR-регистры имеют свои собственные имена (например,​ IA32_TIME_STAMP_COUNTER),​ однако,​ мыщъх'​у не известен ни один ассемблер,​ "​переваривающий"​ их, а потому приходится использовать "​безликие"​ номера,​ перечисленные в приложении "​MODEL-SPECIFIC REGISTERS"​ руководства Intel "IA-32 Architecture Software Developer'​s Manual Volume 3: System Programming Guide",​ откуда,​ в частности,​ можно узнать,​ что MSR-регистр **IA32_TIME_STAMP_COUNTER** имеет номер **10h**.
 +
 +Чтение MSR-регистров осуществляется машинной командой **RDMSR**, с предварительной загрузкой номера нужного нам MSR-регистра в ECX. После выполнения команды регистровая пара EDX:EAX содержит исходный результат. В EDX помещаются старшие 32-бита значения MSR, а в EAX, соответственно,​ идут младшие.
 +
 +За запись отвечает команда **WRMSR**, ожидающая номер MSR-регистра в ECX, а записываемое значение в регистровой паре EDX:EAX. Пример использования обоих команд показан ниже:
 +
 +MOVECX, 10h ; // IA32_TIME_STAMP_COUNTER
 +
 +RDMRD; // MOV (EDX:EAX), IA32_TIME_STAMP_COUNTER
 +
 +INCEAX
 +
 +WMSR; MOV IA32_TIME_STAMP_COUNTER,​ (EDX:EAX)
 +
 +Листинг 1 демонстрация чтения и записи MSR-регистров
 +
 +В защищенном режиме обе команды могут вызываться только из нулевого кольца,​ иначе операционная система сгенерирует исключение. Другими словами,​ для экспериментов с MSR-регистрами нам необходимо написать драйвер,​ "​скелет"​ которого представлен ниже:
 +
 +.686
 +
 +.MMX
 +
 +.model flat, stdcall
 +
 +extern DbgPrint:​PROC
 +
 +.code
 +
 +DriverEntry proc
 +
 +NOP
 +
 +NOP
 +
 +INT 03; // soft-ice: I3HERE DRV
 +
 +
 +
 +MOV ECX, 10h; // IA32_TIME_STAMP_COUNTER
 +
 +RDMSR; // MOV (EDX:EAX), IA32_TIME_STAMP_COUNTER
 +
 +
 +
 +MOVEAX, 666h; LOW 32 bits
 +
 +WRMSR; // MOV (EDX:EAX), IA32_TIME_STAMP_COUNTER
 +
 +
 +
 +RDMSR; // READ AGAIN - just for fun :-)
 +
 +
 +
 +push offset mystring
 +
 +CALL DbgPrint
 +
 +pop eax
 +
 +
 +
 +mov eax, 0C0000182h; STATUS_DEVICE_CONFIGURATION_ERROR
 +
 +;RET; Four-F says
 +
 +RETN 8; <- haron says
 +
 +DriverEntry endp
 +
 +.data
 +
 +mystring DB "*] MSR [*",​0Dh,​0Ah,​0
 +
 +end DriverEntry
 +
 +Листинг 2 исходный текст "​скелета"​ простейшего драйвера MSR-base.asm для экспериментов с MSR-регистрами
 +
 +Для сборки драйвера нам понадобиться NTDDK и командный файл следующего содержания (для настройки которого необходимо прописать путь к библиотекам ядра):
 +
 +@ECHO OFF
 +
 +SET FILE_NAME=MSR-base
 +
 +**REM ****каждый настраивает эту строку под себя!**
 +
 +**SET ntoskrnl=D:​\NTDDK\libchk\i386\ntoskrnl.lib**
 +
 +IF EXIST %FILE_NAME%.obj DEL %FILE_NAME%.obj
 +
 +ml /nologo /c /coff %FILE_NAME%.asm
 +
 +IF NOT EXIST %FILE_NAME%.obj GOTO err
 +
 +link /nologo /driver /​base:​0x10000 /align:32 /​out:​%FILE_NAME%.sys /​subsystem:​native %FILE_NAME%.obj %ntoskrnl% ​
 +
 +GOTO end
 +
 +:err
 +
 +ECHO -ERR!
 +
 +:end
 +
 +Листинг 3 командный файл для сборки драйвера
 +
 +Остается самая малость — загрузить драйвер внутрь системы,​ передав управление процедуре DriverEntry,​ которая,​ выполнив все, что задумано,​ завершится с кодом STATUS_DEVICE_CONFIGURATION_ERROR,​ автоматически выгружая драйвер из системы.
 +
 +Существует множество загрузчиков драйверов (на худой конец можно написать и свой, благо в MSDN входит пример с ZwLoadDriver вместе со строгой рекомендацией не использовать эту функцию в серьезных проектах). Перебрав кучу загрузчиков,​ мыщъх остановился на KmdManager'​е,​ написанным легендарным хакером Four-F, известным своим циклом статей на WASM'​е,​ откуда можно скачать сам загрузчик вместе с исходными текстами:​ https://​wasm.ru/​pub/​21/​files/​kmd3.zip (прилагаемый к статье).
 +
 +Но прежде чем загружать драйвер в систему необходимо установить soft-ice (или syser – это кому что больше нравится) и сказать ему "​I3HERE DRV",​ заставив его отлавливать INT 03h в драйверах. Зачем все это?! А зачем, что наблюдать за командами RDMSR/WRMSR удобнее всего из отладчика,​ а soft-ice —это классика жанра.
 +
 +{{msr-hacker_Image_1.png}}
 +
 +Рисунок 2 загрузка драйвера посредством KmdManager'​a
 +
 +ОК, soft-ice подготовлен к работе,​ запускаем KmdManager.exe,​ указываем путь к драйверу,​ взводим галочку,​ расположенную между [Register] и [Run] и нажимаем на [Reg'​n'​Run] — Soft-ice тут же появляется на экране в точке, где мы заботливо воткнули в драйвер команду INT 03h и теперь можем трассировать драйвер сколько нашей душе угодно,​ а когда надоест — нажать <​CTRL-D>​ или "​x;<​ENTER>"​ для выхода.
 +
 +KmdManager, конечно,​ обругает нас матом, что драйвер загрузить не удалось,​ но все идет по плану. Именно так оно и было задумано. Зачем загружать драйвер если все, что нам нужно — выполнить несколько команд на уровне нулевого кольца?​!
 +
 +{{msr-hacker_Image_2.png}}
 +
 +Рисунок 3 наблюдение за MSR-регистрами в soft-ice
 +
 +===== >>>​ врезка чтение/​запись MSR с прикладного уровня =====
 +
 +Для чтение/​записи MSR с прикладного уровня можно воспользоваться недокументированной native-API функцией **NtSystemDebugControl()**,​ экспортируемой из динамической библиотеки NTDLL.DLL.Готовый к употреблению пример работы с ней лежит на http://​www.openrce.org/​blog/​view/​535/​Branch_Tracing_with_Intel_MSR_Registers,​ однако,​ для этого необходимо:​ а) обладать правами администратора;​ б) в последних пакетах обновления под Server 2003 и XP возможности этой функции были существенно урезаны и, по-видимому,​ политика урезания продолжится и в дальнейшем,​ так что все-таки без драйвера не обойтись.
 +
 +===== перехватываем системные вызовы =====
 +
 +Для перехода с прикладного уровня в режим ядра операционные системы NT 3.х/4.х и W2K использовали прерывание **INT 2Eh**,​ которое в изобилие водится в динамической библиотеке NTDLL.DLL, служащей своеобразными вратами в "​ад",​ тьфу, мостом между прикладными и ядерными уровнями.
 +
 +77F88278 public ZwCreateFile
 +
 +77F88278 ZwCreateFileproc near; CODE XREF:​LdrLoadAlternateResourceModule+29F↓p
 +
 +77F88278
 +
 +77F88278 arg_0= dword ptr  4
 +
 +77F88278
 +
 +77F88278moveax,​ 20h; NtCreateFile
 +
 +77F8827Dleaedx,​ [esp+arg_0]
 +
 +**77F88281int2Eh;​ <--**** врата в ад**
 +
 +77F88283retn2Ch
 +
 +77F88283 ZwCreateFileendp
 +
 +Листинг 4 реализация вызова функции ZwCreateFile на W2K
 +
 +Основной недостаток INT 2Eh в том, что выполняется она очень медленно и потому в P6-процессорах появилась пара более быстрых команд:​ **SYSENTER** (с прикладного уровня в режим ядра) и **SYSEXIT** (из режима ядра назад на прикладной уровень),​ которую Microsoft стала использовать взамен INT 2Eh начиная с XP и Server 2003, в результате чего NTDLL.DLL оказалась чуть ли не полностью переписаной.
 +
 +В частности,​ в ней появилась пара процедур быстрого вызова ядерных функций и выхода из них обратно на прикладной уровень:​
 +
 +ntdll!KiFastSystemCall:​
 +
 +7C82ED50 8BD4MOVEDX,​ESP
 +
 +7C82ED52 0F34SYSENTER
 +
 +ntdll!KiFastSystemCallRet:​
 +
 +7C82ED54 C3RET
 +
 +Листинг 5 процедуры NTDLL.DLL быстрого вызова ядерных функций с прикладного уровня
 +
 +Прерывание INT 2Eh вопреки распространенному заблуждению не было предано анафеме и вместо морга перекочевало в процедуру KiIntSystemCall:​
 +
 +ntdll!KiIntSystemCall:​
 +
 +7C82ED60 8D542408LEAEDX,​[ESP+0X8]
 +
 +7C82ED64 CD2EINT2Eh
 +
 +7C82ED66 C3RET
 +
 +Листинг 6 процедура вызова ядерных функций через INT 2Eh, оставленная в XP/​Server 2003 для совместимости
 +
 +Однако,​ дизассемблирование показывает,​ что ни та, и другая процедуры реально не используется и NTDLL.DLL исповедует совершенно другой механизм диспетчеризации системных вызовов. В частности,​ код той же функции **ZwCreateFile**в Server 2003 выглядит так (сравните его с листингом 4):​
 +
 +77F42467 public ZwCreateFile
 +
 +77F42467 ZwCreateFile proc near; CODE XREF: LdrLoadAlternateResourceModule-10C↓p
 +
 +77F42467moveax,​ 27h; NtCreateFile
 +
 +77F4246Cmovedx,​ 7FFE0300h; offset SharedUserData!SystemCallStub
 +
 +77F42471calledx
 +
 +77F42473retn2Ch
 +
 +77F42473 ZwtCreateFile endp
 +
 +Листинг 7 реализация вызова функции ZwCreateFile на Server 2003
 +
 +Что находится по адресу 7FFE0300h? Призвав на помощь soft-ice ("​U 7FFE0300h"​) мы видим (см. рис. 4),​ что здесь расположена машинная инструкция SYSENTER, что, собственно говоря,​ и требовалось доказать.
 +
 +{{msr-hacker_Image_3.png}}
 +
 +Рисунок 4 SYENTER в SharedUserData!SystemCallStub
 +
 +Теперь немного о сути самой диспетчеризации. В таблице дескрипторов прерываний (IDT) для прерывания INT 2Eh имеется своя запись,​ указывающая по какому адресу и селектору процессор должен передавать управление при ее выполнении. Естественно,​ на уровне ядра IDT легко модифицировать,​ установив свой перехватчик системных вызовов (многие rootkit'​ы именно так и поступают),​ однако,​ это слишком заметно. Целостность IDT проверяют многочисленные антивирусы и прочие защитные механизмы.
 +
 +Операционные системы семейства XP/​Вислаи Server 2003/2008 предоставляют в этом плане намного больше возможностей. Во-первых,​ мы можем изменить содержимое SharedUserData,​ заменив SYSENTER переходником на свой собственный обработчик. И хотя этот регион формально недоступен для записи с прикладного уровня,​ он находится в пользовательской области памяти,​ которая в отличии от ядра все-таки может быть модифицирована с прикладного уровня,​ пускай и не без извращений,​ но… эта тема совсем другого разговора.
 +
 +Задумаемся — а куда SYSENTER передает управление?​ Ведь целевой адрес нигде явным образом не указан. Курим мануал от Intel и выясняем,​ что SYSENTER принимает три скрытых аргумента,​ передаваемые через MSR-регистры.
 +
 +  - **SYSENTER_CS_MSR ****(****174h):​**
 +    - CS регистр для перехода на уровень нулевого кольца;​
 +  - **SYSENTER_ESP_MSR**** (****175h):​**
 +    - ESP регистр для перехода на уровень нулевого кольца;​
 +  - **SYSENTER_EIP_MSR**** (****176h****):​**
 +    - EIP регистр для перехода на уровень нулевого кольца;​
 +Селектор стека (регистр SS) получается путем сложения константы 08h со значением MSR-регистра SYSENTER_CS_MSR,​ так что SYENTER позволяет задавать не только CS:EIP, но и SS:​ESP.Таким образом,​ мы имеем в своем распоряжении все четыре необходимых ингредиента для перехвата,​ хотя на практике достаточно подменить целевой EIP перенаправив его на код нашего хакерского обработчика (ес-но, расположенного внутри ядра, т. е. представляющего из себя драйвер,​ хотя чисто теоретически можно заставить SYSENTER вызывать обработчик,​ находящийся на прикладном уровне,​ но на этом пути слишком много подводных камней,​ чтобы принимать его всерьез). Весь фокус в том, что за MSR-регистрами еще мало кто следит и подобный rootkit имеет хорошие шансы остаться незамеченным долгое время (или даже не быть замеченным вообще).
 +
 +Ниже приведен фрагмент кода, считывающего MSR-регистры,​ связанные с командой SYSENTER. На NT 3.х/4.х и W2K мы получим нули, а XP/​Висла/​Server 2003/​2008 покажут нам адрес диспетчера системных вызовов который можно хакнуть через WRMSR:
 +
 +INT 03; // for soft-ice
 +
 +MOV ECX, 174H; // SYSENTER_CS_MSR
 +
 +RDMSR; // MOV (EDX:EAX), SYSENTER_CS_MSR
 +
 +MOV ECX, 175H; // SYSENTER_ESP_MSR
 +
 +RDMSR; // MOV (EDX:EAX), SYSENTER_ESP_MSR
 +
 +MOV ECX, 176H; // SYSENTER_EIP_MSR
 +
 +RDMSR; // MOV (EDX:EAX), SYSENTER_EIP_MSR
 +
 +Листинг 8 фрагмент исходного текста драйвера MSR-SYSENTER.asm,​ определяющего адрес диспетчера системных вызовов под XP/​Висла/​Server 200x
 +
 +Загружаем драйвер привычным способом (soft-ice должен быть предварительно запущен) и начинаем трассировать программу,​ наблюдая за значениями,​ возвращаемыми в регистровых парах EDX:EAX.
 +
 +{{msr-hacker_Image_4.png}}
 +
 +Рисунок 5 читаем MSR-регистр номер 174h (SYSENTER_CS_MSR) под W2K и видим в EDX:EAX значение 00000000h, т.к. W2K не использует SYSENTER
 +
 +{{msr-hacker_Image_5.png}}
 +
 +Рисунок 6 читаем MSR-регистр номер 174h (SYSENTER_CS_MSR) под Server 2003 и видим в EAX значение 08h, совпадающее с ядерным селектором CS, что и требовалось доказать
 +
 +===== халтурный хронометр или хронометраж наоборот =====
 +
 +Начиная с P6 в Pentium-процессорах появился специальный счетчик производительности,​ увеличивающий значение MRS-регистра **IA32_TIME_STAMP_COUNTER** (**10****h**) на единицу каждый такт (на самом деле, это очень большое допущение,​ документация от Intel гарантирует просто увеличение,​ оставляя за собой простор для маневров,​ но это уже дебри технических деталей,​ в которые лучше не вдаваться).
 +
 +По умолчанию,​ прикладным программам даровано право читать его содержимое командой **RDTSC**, возвращающей текущее значение в регистровой паре EDX:EAX, причем,​ отладчики типа soft-ice _не_ "​замораживают"​ этот счетчик на время своей работы,​ что позволяет защитным механизмам легко обнаруживать факт трассировки или срабатывания точек останова (обработка которых требует значительного количества процессорного времени). Во времена IBM XT/AT совместимых компьютеров для той же цели использовался системный таймер (ну, грубо говоря,​ часы) и вот его-то soft-ice как раз и "​замораживал",​ не позволяя защитам обнаружить себя. А сейчас что?!
 +
 +{{msr-hacker_Image_6.png}}
 +
 +Рисунок 7 флаг TSD в управляющем регистре CR4
 +
 +Начнем с того, что команду RDTSC очень легко сделать привилегированной. Для этого достаточно взвести TSD флаг (2й бит) в регистре CR4 (доступном только с нулевого кольца),​ после чего всякая попытка вызова RDTSC с прикладного уровня заставит процессор генерировать общее исключение защиты,​ перехватываемое отладчиком и мы (перед возвращением управления программе) можем записать в регистровую пару EDX:EAX все, что нам захочется,​ а конкретно — создать видимость,​ что выполнение данного участка кода заняло ничуть не больше времени,​ чем обычно.
 +
 +Фрагмент кода, который взводит TSD бит приведен ниже:
 +
 +MOVEAX, CR4; // читаем управляющий регистр CR4
 +
 +OREAX, 4; // взводим TSD флаг
 +
 +MOVCR4, EAX; // обновляем CR4
 +
 +Листинг 9 делаем команду RDTSC привилегированной инструкцией
 +
 +А как быть, если защита реализована на уровне драйвера и наш запрет на чтение IA32_TIME_STAMP_COUNTERей не помеха?​! Тогда можно прибегнуть к прямой записи MSR-регистра IA32_TIME_STAMP_COUNTER командой WRMSR, пример использования которой приведен в листинге 1. Правда,​ здесь есть одно "​но"​. Процессор (вот сцука) записывает только младшие 32-бита MSR-регистра IA32_TIME_STAMP_COUNTER,​ а остальные сбрасывает в ноль и защита может разоблачить наши махинации,​ правда,​ все известные мыщъх'​у защиту с этим не заморачиваются,​ а просто сравнивают результаты двух замеров и если в обоих старшие 32-бита обнулены,​ то все ОК.
 +
 +Или не ОК? Прикинем насколько нам хватит младших 32-бит. Возьмем процессор с тактовой частотой в 1 ГГц, увеличивающий IA32_TIME_STAMP_COUNTER на единицу каждый такт, тогда младшие 32-бита переполнятся за 4,​294967296 сек. Срок в общем-то не такой уж и большой. Впрочем,​ учитывая многозадачную природу Windows, защиты осуществляют замеры только на коротких "​трассах",​ выполняющихся сотые или даже тысячные доли секунды,​ т. е. меньше одного кванта (времени,​ отпущенного процессу системным планировщиком,​ после которого происходит переключение на другой поток). В XP длительность кванта составляет ~100 мс, поэтому,​ результаты замера в ~50 мс уже нельзя считать достоверными — поток мог быть прерван планировщиком. Короче говоря,​ для борьбы с защитами младших 32-бит вполне хватит.
 +
 +Кстати,​ интересный факт. При записи IA32_TIME_STAMP_COUNTER под VM Ware, старшие 32-бита MSR-регистра _не_ обнуляются,​ а в младшие записывается немного большая величина,​ чем замышлялось (издержки эмуляции),​ следовательно,​ анти-анти-отладочный механизм должен работать так:
 +
 +  - записать что-то в IA32_TIME_STAMP_COUNTER;​
 +  - прочитать IA32_TIME_STAMP_COUNTER;​
 +  - если старшие 32-бита равны нулю, мы на живом процессоре и:
 +    - записываем в младшие 32-бита фиктивное значение;​
 +  - если старшие 32-бита не равны нулю, мы под VM Ware и:
 +    - записываем в младшие 32-бита значение с поправкой на эмуляцию
 +Таким образом,​ ломая программы под VM Ware и корректируя значение IA32_TIME_STAMP_COUNTER должным образом,​ мы надежно скроем присутствие отладчика от всех защит, основанных на замере временных интервалов.
 +
 +===== трассируем ветвления =====
 +
 +Взведите бит TF регистра флагов (E)FLAGS (от там 8й по счету, начиная от нуля) и процессор начнет генерировать отладочное прерывание INT 01h после выполнения каждой инструкции (за исключением инструкций,​ записывающих сегментный регистр SS) — это еще со времен IBM XT (не путать с XP) всем хакерам хорошо известно.
 +
 +Недостаток такого подхода прежде всего в его чрезвычайной медлительности. Даже с учетом быстродействия современных процессоров,​ обработка исключений обходится _очень_ дорого и "​серьезную"​ программу мы будет трассировать до конца сезона. А смысл?​! К трассировке обычно прибегают для реконструкции логики работы машинного кода, мысленно разбивая его на структурные блоки как-то:​ ветвления,​ циклы, etc.
 +
 +В частности,​ при написании универсальных распаковщиков,​ автоматически определяющих оригинальную точку входа в программу,​ нам совершенно незачем исполнять _все_ команды,​ вполне достаточно после каждого прыжка сравнить целевой код с набором сигнатур стартового кода, внедряемых компиляторами в начало программы.
 +
 +Вот если бы мы могли заставить процессор генерировать отладочные прерывания только после ветвлений — скорость распаковки возросла бы в сотни раз. Или вот еще. Сравнивания два прогона защищенной программы до и после завершения испытательного срока, мы легко найдем тот самый условный переход,​ после которого все пошло по пути "trial expired"​. Естественно,​ полный лог трассировки нам ни к чему. Нас интересуют только ветвления. Вот только так их получить?​!
 +
 +{{msr-hacker_Image_7.png}}
 +
 +Рисунок 8 бит BTF в MSR-регистре MSR_DEBUGCTLA (1D9h)
 +
 +Оказывается,​ процессор позволяет сделать это! Если бит BTF (1й, считая от нуля) MSR-регистра **MSR_DEBUGCTLA** (**1D****9****h**) взведен,​ то процессор будет интерпретировать стандартный TF флаг как указание генерировать отладочное прерывание _только_ после встречи с ветвлением или исключением,​ при этом оба флага (BTF и TF) автоматически очищаются.
 +
 +Проведем следующий эксперимент. Уберем из "​скелета"​ нашего драйвера INT 03h, и поместим туда следующий код, взводящий флаг BTF.
 +
 +MOV ECX, 1D9H; // MSR_DEBUGCTLA
 +
 +RDMSR; // MOV (EDX:EAX), MSR_DEBUGCTLA
 +
 +OR EAX, 2; // SET BTF (single-step on branches) flag (bit 1)
 +
 +WRMSR; // MOV (EDX:EAX), MSR_DEBUGCTLA
 +
 +Листинг 10 фрагмент драйвера MSR-branch-trace.asm,​ взводящего BTF флаг
 +
 +Загрузим драйвер в систему и запустив любой отладчик,​ например,​ OllyDbg, нажмем <F7> для трассировки одной инструкции. Опс! Отладчик заносит нас черт знает куда, останавливаясь на первом ветвлении (которым в большинстве случав будет инструкция CALL, вызывающая некоторую API-функцию из стартового кода). Флаг BTF при этом сбрасывается и дальше трассировка проходит нормально (то есть, шаг-за-шагом) во всяком случае пока мы вновь не загрузим наш драйвер,​ устанавливающий BTF-флагили не напишем plug-in для OllyDbg.
 +
 +К статье прилагается исходный код и откомпилированный модуль MSR-branch-trace.sys,​ устанавливающий BTF-флаг и тут же проверяющий его значение,​ выводя результат проверки в отладочный поток, содержимое которого можно просмотреть как с помощью soft-ice, так и утилитой DbgView от Марка Руссиновича.
 +
 +Если взвести BTF-флаг не удается,​ это означает,​ что на данной платформе он не поддерживается (на P-III Coppermine поддерживается,​ на P-4 тоже, а вот под VM Ware 4.5 и 5.2 – увы и ах!).
 +
 +Проверить значение BTF-бита поможет другой драйвер (MSR-branch-trace-x.sys),​ так же прилагаемый к статье (см. рис. 9).
 +
 +{{msr-hacker_Image_8.png}}
 +
 +Рисунок 9 проверка состояния BTF-флага драйвером MSR-branch-trace-x.sys
 +
 +===== заключение =====
 +
 +На этом наше краткое знакомство с MSR-регистрами не заканчивается и заложенный в них потенциал только начинает раскрываться. Как поется в некогда популярной песне "то ли еще будет ой-ой-ой"​. Мыщъх сейчас работает над созданием трассера реального времени,​ который на самом деле никаким трассером не является,​ а представляет собой своеобразный "​дампер"​ истории выполнения команд,​ сохраняемой процессоров как в MSR-регистрах,​ так и в специально отведенной для этих целей области памяти.
 +
 +Мы не только получаем колоссальный выигрыш в производительности,​ но и полностью скрываем свое присутствие от защитных механизмов и все существующие на данный момент антиотладочные механизмы перестают работать. Но это будет не сейчас. Такая обширная тема требует отдельной статьи,​ в которой MSR-регистры лишь малая часть огромного отладочного механизма,​ спрятанного в недрах процессора.
 +
 +Короче,​ ждите прихода и он будет!!!
 +
 +{{msr-hacker_Image_9.jpg}}
 +
 +Рисунок X учиться,​ учиться и учиться!
 +
 +