Вызывает ли чтение регистра отладки исключение, если установлен флаг GD?

#debugging #assembly #x86 #reverse-engineering #malware

# #отладка #сборка #x86 #обратная разработка #вредоносное ПО

Вопрос:

В последнее время я провел некоторое исследование регистров отладки и того, как некоторые вредоносные программы могут манипулировать ими в качестве тактики предотвращения отладки. Одна из вещей, которые я прочитал несколько раз, заключается в том, что это можно предотвратить, используя флаг общего обнаружения в DR7, который вызывает исключение отладки, если для доступа к любому из DR0-DR7 используется команда MOV.

Однако мне не ясно, что именно означает access — если, например, инструкция mov используется только для размещения адреса DR0-DR3 в регистре общего назначения, чтобы его можно было прочитать, приведет ли это к возникновению исключения отладки при установке флага GD? Или это происходит только в том случае, если для фактического изменения содержимого регистра используется команда MOV? То, что я прочитал до сих пор, было немного неоднозначным по этому поводу.

Я столкнулся со сборкой ниже в тексте, который показывает манипуляции с регистрами отладки, но в этом случае mov используется только для получения адреса регистров отладки, а фактическое изменение выполняется инструкцией or, поэтому я не уверен, что этот код вызовет исключение, если был установлен GD.

     xor eax, eax
    push offset except_callback
    push d fs:[eax]
    mov fs:[eax], esp
    int 3 ;force an exception to occur
    ...        

    except_callback:
     mov eax, [esp 0ch] ;get ContextRecord
     mov ecx, [eax 4] ;Dr0
     or ecx, [eax 8] ;Dr1
     or ecx, [eax 0ch] ;Dr2
     or ecx, [eax 10h] ;Dr3
     jne <Debugger_detected>
 

Комментарии:

1. Действительно, в руководствах Intel иногда говорится «доступ», а иногда «изменить», например, в таблице 17-2, Условия исключения отладки.

2. Ваш пример вообще не обращается к регистрам отладки. «ContextRecord» не присущ процессору и не подвергается какой-либо специальной обработке (помимо обычной сегментации памяти и подкачки).

3. @ecm Я добавил немного недостающего кода для большего контекста (без каламбура) на случай, если теперь это имеет больше смысла. Исходные инструкции являются частью обработчика исключений, который передается в стек и позже вызывается, оттуда смещение используется для доступа к записи контекста.

4. @Rahl2500: добавленный код также не обращается напрямую ни к одному из регистров отладки. Только инструкции вида mov XXX, drX (xxx = регистр, x = число) обращаются к ним напрямую.

Ответ №1:

Intel довольно ясно об этом:

Попытка чтения или записи регистров отладки с любого другого уровня привилегий генерирует исключение общей защиты (#GP).

Таким образом, чтение или запись регистра отладки, когда он не выполняется с CPL 0, вызовет исключение, независимо от GD флага.

На самом деле, я проанализировал довольно много вредоносных программ, и ни одна из них не обращается напрямую к регистрам отладки. Они получают текущий контекст потока (GetThreadContext или NtGetContextThread или аналогичные варианты WOW64) и проверяют значения регистров отладки оттуда, обратите внимание, что именно ядро Windows в этом случае считывает регистр отладки. Этот трюк с защитой от ошибок можно обойти вручную (с помощью точки останова в API, извлекающем контекст) или с помощью плагина отладчика. Вредоносные программы, работающие с CPL 0, могут использовать флаг GD, но я пока его не нашел.

Отвечая на ваш вопрос заголовка, любой доступ на чтение или запись (с CPL 0) к регистру отладки вызовет #GP, если GD он установлен. Я не тестировал его, но, учитывая его предполагаемое использование (для поддержки эмулятора аппаратного отладчика), идея состоит в том, чтобы «виртуализировать» регистры отладки. Аппаратный отладчик, эмулируемый программным обеспечением, может затем использовать регистр отладки, даже если отлаживаемая ОС уже использует их. Это делается путем сбоя при каждом доступе и правильной замены значений ОС и эмулятора.

Если бы ошибка была только при записи, эмулятор не смог бы предотвратить чтение отлаживаемой ОС неправильного значения (помещенного туда эмулятором) из регистра отладки.

Включает (при установке) защиту регистра отладки, которая вызывает создание исключения отладки до любой команды MOV, которая обращается к регистру отладки.
Когда такое условие обнаружено, флаг BD в регистре состояния отладки DR6 устанавливается до генерации исключения. Это условие предусмотрено для поддержки встроенных эмуляторов. Когда эмулятору требуется доступ к регистрам отладки, программное обеспечение эмулятора может установить флаг GD, чтобы предотвратить вмешательство со стороны программы, выполняющейся в данный момент на процессоре.
Процессор удаляет флаг GD при входе в обработчик исключений отладки, чтобы разрешить обработчику доступ к регистрам отладки.

Комментарии:

1. > «Вредоносные программы, работающие с CPL 0, могут использовать флаг GD, но я пока его не нашел». Интересно. Разве попытка изменить сам флаг GD не вызовет #GP, поскольку DR7 является регистром отладки?

2. @Rahl2500: Руководство разработчика программного обеспечения 17.2.4: «Процессор удаляет флаг GD при входе в обработчик исключений отладки, чтобы разрешить обработчику доступ к регистрам отладки». Поэтому, если он не установлен, вы можете установить его (из CPL 0). Он остается установленным до тех пор, пока не возникнет исключение отладки. В этот момент он очищается, и если вы все еще хотите, чтобы он был включен, обработчик должен установить его снова.