среда, 9 марта 2016 г.

Еще один способ использования BURNMEMORY

Лет 5 назад был пост про BURNMEMORY опцию (http://kitrap08.blogspot.ru/2011/12/burnmemory.html), задаваясь вопросом - а зачем оно вообще нужно. В комментах были даны ответы, но сейчас мне встретился еще один вариант использования BURNMEMORY/removememory, и этот вариант уже имеет непосредственное отношение к практике.

Встретился мне этот вариант в доке: Intel Debug Extensions for WinDbg* for Intel Processor Trace.

Intel Processor Trace это новая фича процессоров Intel 6й серии(Skylake), которая суть есть трассировка выполнения с низким оверхедом. Данные трассировки будут скидываться в память, конфигурировать которую нужно через BIOS / UEFI firmware, но только в том случае, если это самое firmware поддерживает данную фичу. А вот если не поддерживает, то на помочь придет как раз  BURNMEMORY/removememory.

Так как именно эти опции позволят сказать ОС, чтобы она не трогала данную память, в которую будут складываться данные трассировки.

Ну и третий вариант - опция badmemory.

пятница, 4 марта 2016 г.

Verifier

Потребовалось мне, для своих нужд, проинжектировать dll и перехватить в процессе некоторые функции. Да так, чтобы кода было минимум, без всяких там сторонних движков и прочих detours'ов.

Всем этим требованиям удовлетворяет механизм verifier'a. Вот только штука эта отладочная и даже системные приложения не идеальны и полны разного рода косяков и багов. Соответственно verifier начинает проверять, ворчать и сыпать брекпойнтами на любой чих. В отладчике соответственно видно что-то типа такого:

VERIFIER STOP 00000210: pid 0x464: Critical section not initialized.

    759C08C0 : Critical section address.
    008A0BF0 : Critical section debug info address.
    00000000 : Not used.
    00000000 : Not used.
   
Или такого:

VERIFIER STOP 00000006: pid 0x464: corrupted heap pointer or using wrong heap

    00EF1000 : Heap used in the call
    05A507F0 : Heap block
    00000214 : Block size
    80DF1000 : Heap owning the block

При отсутствующем отладчике, соответственно, получим необрабатываемое исключение в том процессе, куда мы заинжектили dll и все благополучно упадет.

В большинстве случаев, брякается все это дело в VerifierStopMessageEx в verifier.dll. А в самом начале функции стоит следующая проверка:

if ( AVrfpProcessBeingTerminated || !AVrfpStopInitialized )
    return 0;
   
То есть бряки перестанут сыпаться, если установить AVrfpProcessBeingTerminated в TRUE. Осталась задача - легко найти эту переменную. VerifierStopMessageEx не экспортируется, а вот VerifierStopMessage экспортируется и имеет в начале нужную переменную:

.text:1124B860 _VerifierStopMessage@40 proc near
.text:1124B860                 mov     edi, edi
.text:1124B862                 push    ebp
.text:1124B863                 mov     ebp, esp
.text:1124B865                 sub     esp, 1Ch
.text:1124B868                 mov     [ebp+var_1C], 0
.text:1124B86F                 mov     [ebp+var_18], 0
.text:1124B876                 mov     [ebp+var_14], 0
.text:1124B87D                 mov     [ebp+var_8], 0
.text:1124B884                 cmp     _AVrfpProcessBeingTerminated, 0
.text:1124B88B                 jnz     short loc_1124B896

Соответственно, найти ее становится элементарным делом. И после нахождения данной переменной и установки ее значения в TRUE, из своей инжектированной dll, все проблемные int 3 более не вызывались.

P.S. К слову, verifier оказался хотя и удобным решением, но тем не менее, не без недостатков. Оказалось, что он перехватывает не все. К примеру, ZwContinue он перехватывать отказался, хотя LdrLoadDll из той же ntdll.dll перехватил.