Вопрос по x86, assembly, windows – Почему этот код позволяет мне обнаруживать отладчик?

16

Почему следующий ассемблерный код является средством отладки?

l1:
call l3
l2:
;some code
l3:
mov al, 0c3h
mov edi, offset l3
or ecx, -1
rep stosb

я знаю этоC3h являетсяRETN и я знаю чтоstobs записывает значение вal в качестве кода операции в соответствии со смещением вedi и это сделано дляecx раз из-заrep.

Я также осознаю тот факт, чтоstobs а такжеstosw будет работать, если они были предварительно загружены на архитектуру Intel в качестве исходного формата.

Если мы запустим программу в режиме отладки, предварительная выборка не имеет значения, и метка l2 будет запущена (потому что она одношаговая), в противном случае, если нет отладчика, это будет пинг-понг между l1 и l3, я прав?

Не будет ли это все еще зависеть от того, установлен ли он как одношаговый? Потому что я, честно говоря, не понимаю, почему отладчик мог бы споткнуться об этом. Правила несколько отличаются в одношаговом режиме. 0xC0000022L

Ваш Ответ

2   ответа
14

Когда программа отлажена (то есть один шаг), очередь предварительной выборки сбрасывается на каждом шаге (когда происходит прерывание). Однако при нормальном выполнении этого не произойдетrep stosb, Старые процессоры не сбрасывали его даже при записи памяти в кешированную область, чтобы поддержать изменяющийся код, кромеrep movs а такжеrep stosb, (IIRC был в конечном итоге исправлен в процессорах i7.)

Вот почему, если есть код отладчика (одношаговый), будет выполняться правильно и когдаrep stosb заменяетсяret l2 будет выполнен. Когда нет отладчикаrep stosb будет продолжаться, так какecx является максимально возможным, он в конечном итоге напишет куда-то, что не должен писать, и произойдет исключение.

Этот метод устранения неполадок описан вЭта бумага.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
2

что здесь делает отладчик - это добавляет задержку. Это может быть ключом к тому, как это работает. В руководстве Intel (и я полагаю, что AMD) прямо говорится, что самоизменяющийся код не гарантирован, чтобы "работать" если только программа не сообщит ЦПУ, что строка кэша, содержащая измененную инструкцию, изменилась. Это должно сделать логику предварительной выборки дешевой; разработчики микросхем не хотят иметь аппаратное обеспечение, которое постоянно проверяет, что каждый байт строки кэша команд все еще действителен.

Итак, я предполагаю, что происходитwith отладчики - это вызовы l1, вызовы l3, в которых хранится возврат после rep stosb, и возврат выполняется из-за длительных задержек, вызванных отладчиком в одном шаге, что заставляет кешклин, содержащий l3, быть повторно загруженным после изменения.

Без отладчика, я полагаю, команда (не показана) после выполнения stosb. Если бы это был переход к «нет отладчика» тогда успех прыжка продемонстрирует, что ни один пошаговый отладчик не использовался.

Если бы я нашел этот код в приложении, я бы отказался его запускать.

Похожие вопросы