Файл вызвал срабатывание точки останова

Обновлено: 06.07.2024

Точки останова

Точку останова (breakpoint) в Visual Studio можно помещать на любую строку кода, которая в действительности выполняется. Самый простой способ — щелчок на необходимой строке в окне редактора кода внутри затененной области вдоль левого края окна документа (или выделение нужной строки и нажатие клавиши <F9>). Это приводит к размещению в данной строке точки останова, которая вызывает прерывание процесса выполнения и передачу управления отладчику. Как и в предыдущих версиях Visual Studio, точка останова обозначается большим кружком слева от соответствующей строки в окне редактора кода. Кроме того, Visual Studio выделяет саму строку, отображая ее текст и фон разными цветами. Щелчок на кружке приводит к удалению точки останова.

Если останов на определенной строке каждый раз не подходит для решения имеющейся проблемы, можно создать так называемую условную точку останова. Для этого выберите в меню Debug (Отладка) пункт Windows --- Breakpoints (Окнo --- Точки останова). Откроется диалоговое окно, позволяющее указать желаемые детали для точки останова. В этом окне можно выполнять следующие действия:

Указать, что выполнение должно прерываться лишь после прохождения точки останова определенное количество раз.

Указать, что точка останова должна вступать в действие при каждом n-ном достижении строки, например, при каждом 20-м ее выполнении (это удобно при отладке больших циклов).

Задать точки останова относительно переменных, а не команд. В таком случае наблюдение будет вестись за значением указанной переменной, и точки останова будут активизироваться при каждом изменении значения этой переменной. Однако этот вариант может сильно замедлить выполнение кода, поскольку на проверку, не изменилось ли значение отслеживаемой переменной после выполнения каждой очередной инструкции, будет тратиться дополнительное время процессора.

Слежения

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

Для просмотра значений переменных можно также использовать окно Autos (Автоматические). Окно Autos представляет собой окно с вкладками, которое появляется лишь тогда, когда программа выполняется в режиме отладки. Если вы его не видите, попробуйте выбрать в меню Debug (Отладка) пункт Windows --- Autos (Окна --- Автоматические).

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

Три предлагаемых в этом окне вкладки предназначены для наблюдения за переменными трех разных категорий:

Вкладка Autos (Автоматические) позволяет просматривать значения нескольких последних переменных, к которым осуществлялся доступ в процессе выполнения программы.

Вкладка Locals (Локальные) позволяет просматривать значения переменных, к которым получается доступ в методе, выполняемом в текущий момент

Вкладка Watch (Слежение) позволяет просматривать значения любых интересующих переменных за счет явного указания их имен непосредственно в окне Watch.

Исключения

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

Конечно, можно устанавливать точки останова в блоках catch, но это часто особо не помогает, поскольку при достижении блока catch поток управления по определению покинет соответствующий блок try. Это означает, что переменные, значения которых, скорее всего, следовало изучить для выяснения того, что пошло не так, покинут область видимости. Не будет даже возможности просматривать трассировочные данные стека для выяснения, какой метод выполнялся во время срабатывания оператора throw, поскольку управление уже покинет этот метод. Разумеется, помещение точки останова в оператор throw позволит решить эту проблему, но надо учитывать, что при написании кода защищенным образом операторов throw будет в коде очень много. Как тогда угадать, какой из них срабатывает и приводит к генерации исключения?

На самом деле в Visual Studio предлагается очень действенное решение. Если заглянуть в меню Debug (Отладка), то можно будет обнаружить там пункт Exceptions (Исключения). В случае выбора этого пункта открывается диалоговое окно Exceptions (Исключения). Это окно позволяет указывать, что должно происходить при выдаче исключения. Здесь можно указать, что выполнение должно продолжаться или же останавливаться с переходом в режим отладки, в случае чего произойдет останов, а отладчик окажется прямо на самом операторе throw:

Окно Exceptions

Дополнительные команды отладки исходного кода

Компиляция практически всего коммерческого программного обеспечения на стадии отладки и на стадии подготовки окончательной версии продукта должна проводиться немного по-разному. Среда Visual Studio способна понимать это, поскольку сохраняет информацию обо всех параметрах, которые ей надлежит передавать компилятору. Для поддержки разных вариантов компоновки проекта Visual Studio потребуется сохранять подобную информацию в более чем одном экземпляре. Разные экземпляры такой информации называются конфигурациями. При создании проекта Visual Studio автоматически предлагает на выбор две таких конфигурации, которые называются, соответственно, Debug (Отладка) и Release (Выпуск):

Конфигурация Release указывает, что компилятор должен проводить в отношении компилируемого кода оптимизацию, в исполняемом коде не должно присутствовать никакой дополнительной информации, а компилятор не должен предполагать наличие препроцессорного символа Debug.

Можно также определять собственные конфигурации. Это необходимо, например, для компоновки приложения с несколькими отличающимися версиями. Раньше из-за проблем, связанных с поддержкой кодировки Unicode в Windows NT, но не в Windows 95, для многих проектов на С++ было принято создавать две конфигурации — одну для Unicode, а вторую для (multibyte character set — набор многобайтных символов).

При отладке точка останова может иметь два визуальных состояния: закрашенный красный кружок или незакрашенный кружок (белая заливка). Если отладчик может успешно установить точку останова в целевом процессе, она будет отображаться как закрашенный красный кружок. Если точка останова отображается как незакрашенный кружок, либо точка останова отключена, либо при попытке установить ее возникло предупреждение. Чтобы определить причину, наведите указатель мыши на точку останова и проверьте, есть ли предупреждение.

В следующих двух разделах описаны наиболее часто возникающие предупреждения и способы их устранения.

"Нет загруженных символов для этого документа"

Перейдите в окно Модули (Отладка > Окна > Модули) и проверьте, загружен ли модуль.

Если модуль загружен, проверьте, загружены ли символы, в столбце Состояние символов.

  • Если символы не загружены, проверьте состояние символов для диагностики проблемы. В контекстном меню модуля в окне Модули щелкните Сведения о загрузке символов. , чтобы узнать, откуда отладчик пытался загрузить символы. Дополнительные сведения о загрузке символов см. в статье Указание файлов символов (.pdb) и исходных файлов.
  • Если символы загружены, PDB-файл не содержит сведений об исходных файлах. Возможно несколько причин.
    • Если исходные файлы были добавлены недавно, убедитесь в том, что загружается последняя версия модуля.
    • Можно создать очищенные PDB-файлы с помощью параметра компоновщика /PDBSTRIPPED. Очищенные PDB-файлы не содержат сведений об исходных файлах. Убедитесь в том, что вы работаете с полным, а не очищенным PDB-файлом.
    • PDB-файл частично поврежден. Удалите файл и выполните чистую сборку модуля, чтобы попытаться устранить проблему.

    Если модуль не загружен, проверьте следующее, чтобы найти причину:

    "… текущий исходный код отличается от версии, построенной в. "

    Если исходный файл изменился и исходный код больше не соответствует отлаживаемому коду, отладчик по умолчанию не будет устанавливать точки останова в коде. Как правило, эта проблема возникает, если исходный файл изменился, но исходный код не был перестроен. Чтобы устранить эту проблему, перестройте проект. Если система сборки считает, что проект уже обновлен, несмотря на то, что это не так, можно заставить ее перестроить проект, сохранив исходный файл еще раз или очистив выходные данные сборки проекта перед сборкой.

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

    Чтобы отключить проверки безопасности, выполните одно из указанных ниже действий.

    • Чтобы изменить отдельную точку останова, наведите указатель мыши на значок точки останова в редакторе и щелкните значок параметров (в виде шестеренки). В редактор добавится окно просмотра. В верхней части окна просмотра есть гиперссылка, указывающая на расположение точки останова. Щелкните гиперссылку, чтобы разрешить изменение расположения точки останова, и установите флажок Разрешить наличие отличий в исходном коде от первоначальной версии.
    • Чтобы изменить этот параметр для всех точек останова, выберите Отладка > Параметры и настройки. На странице Отладка / Общие снимите флажок Требовать точного соответствия исходной версии файлов . Не забудьте снова включить этот параметр после завершения отладки.

    Точка останова была установлена успешно (без предупреждения), но не сработала

    В этом разделе содержатся сведения об устранении неполадок в ситуации, когда отладчик не выводит предупреждений — точка останова представлена закрашенным красным кружком во время отладки, но не срабатывает.

    Вот несколько моментов, которые следует проверить.

    После удаления точки останова она по-прежнему применяется при запуске отладки

    Если удалить точку останова во время отладки, она может снова сработать при очередном запуске отладки. Чтобы прекратить применение этой точки останова, убедитесь, что все ее экземпляры удалены из окна Точки останова .

    1. Сканировать ваш компьютер на наличие вредоносных программ
    2. Удалить сторонние заставки
    3. Удалить настройки разгона
    4. Отключить проблемные приложения
    5. Удалите все недавно установленные приложения
    6. Убедитесь, что приложение, которое вы пытаетесь запустить, обновлено
    7. Создать новую учетную запись пользователя
    8. Убедитесь, что ваша система обновлена ​​
    9. Выполните восстановление системы


    По словам пользователей, иногда эта проблема может возникнуть, если ваша система заражена вредоносным ПО. Для решения проблемы рекомендуется выполнить полное сканирование системы и проверить, решает ли это вашу проблему. Имейте в виду, что полное сканирование системы может занять около часа, поэтому вам придется набраться терпения.

    Чтобы избежать заражения вредоносным ПО в будущем, рекомендуется использовать хороший и надежный антивирус. Если вы хотите добиться максимальной защиты, рекомендуем вам попробовать Bitdefender .

    • Bitdefender Total Security 2019: лучшее мультиплатформенное антивирусное программное обеспечение

    Чтобы решить эту проблему, рекомендуется найти и удалить сторонние заставки со своего ПК. Несколько пользователей сообщили, что причиной этой проблемы были заставки, но после их удаления проблема была решена.

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

    Иногда сторонние приложения могут вызвать ошибку Достигнута точка останова , и для ее исправления рекомендуется найти и удалить проблемное приложение. Частой причиной может быть ваша антивирусная программа, поэтому попробуйте отключить ее и проверить, помогает ли это. В некоторых случаях вам может даже понадобиться удалить антивирус, чтобы решить эту проблему.

    В случае, если это не сработает, следующим шагом будет чистая загрузка. Как вы, возможно, знаете, многие приложения запускаются автоматически с Windows 10, и иногда эти приложения могут вызывать проблемы при запуске.

    Чтобы точно определить причину проблемы, необходимо отключить все запускаемые приложения, выполнив следующие действия:

    1. Нажмите W Indows Key + R и введите msconfig .Нажмите ОК или нажмите Enter .
    2. Откроется окно Конфигурация системы . Перейдите на вкладку Службы и установите флажок Скрыть все службы Microsoft . Теперь нажмите кнопку Отключить все , чтобы отключить все службы запуска.
    3. Перейдите на вкладку Автозагрузка и нажмите Открыть диспетчер задач .
    4. Появится список запускаемых приложений. Нажмите правой кнопкой мыши первую запись в списке и выберите Отключить . Сделайте это для всех приложений в списке.
    5. После отключения всех приложений вернитесь в окно Конфигурация системы и нажмите Применить и ОК .
    6. Перезагрузите компьютер.

    После перезагрузки компьютера проверьте, не устранена ли проблема. Если проблема не появляется, это означает, что проблема была вызвана одним из запускаемых приложений или служб. Чтобы найти причину, вам нужно включить службы и приложения в группах, пока вам не удастся воссоздать проблему.

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

    • ЧИТАЙТЕ ТАКЖЕ: исправьте ошибку сертификата Wi-Fi в Windows 10 за 4 простых шага

    Решение 5. Удалите все недавно установленные приложения.

    Чтобы решить эту проблему, рекомендуется удалить все недавно установленные приложения или любые подозрительные приложения, которые вы не помните, устанавливали. Существует несколько методов, которые вы можете использовать для удаления приложения, но наиболее эффективным из них является использование программного обеспечения для удаления, такого как Revo Uninstaller .

    • ОТНОСИТЕЛЬНО: 10 лучших программ удаления для пользователей ПК

    Решение 6. Убедитесь, что приложение, которое вы пытаетесь запустить, обновлено

    Иногда Достигнута точка останова может появиться ошибка из-за поврежденной учетной записи пользователя. Ваша учетная запись может быть повреждена по разным причинам, и если это произойдет, вы можете столкнуться с различными проблемами. Чтобы решить эту проблему, рекомендуется создать новую учетную запись пользователя и проверить, появляется ли проблема и там. Чтобы создать новую учетную запись пользователя, выполните следующие действия:

    1. Откройте приложение Настройки и перейдите в раздел Аккаунты . Чтобы быстро открыть Приложение настроек , вы можете использовать ярлык Ключ Windows + I .
    2. Выберите Семья и другие люди в меню слева. Выберите Добавить кого-то еще на этот компьютер .
    3. Перейдите к У меня нет информации для входа этого человека> Добавить пользователя без учетной записи Microsoft .
    4. Введите имя пользователя для новой учетной записи и нажмите Далее .

    Решение 8. Убедитесь, что ваша система обновлена

    Windows 10 обычно устанавливает отсутствующие обновления автоматически, но вы всегда можете проверить наличие обновлений самостоятельно, выполнив следующие действия:


    1. Откройте приложение Настройки и перейдите в раздел Обновление и безопасность .
    2. Теперь нажмите кнопку Проверить обновления на правой панели.

    Теперь Windows проверит наличие доступных обновлений и установит их автоматически. После установки обновлений проверьте, не устранена ли проблема.

    Чтобы выполнить восстановление системы, вам просто нужно сделать следующее:

    После того, как вы восстановите свою систему, проверьте, сохраняется ли проблема.

    В первой части мы получили базовое представление об отладчике WinDBG. Во второй части мы углубим свои знания, чтобы вы уже смогли начать отладку программ.

    image

    Автор: Брэд Антониевич (Brad Antoniewicz)

    В первой части мы получили базовое представление об отладчике WinDBG. Во второй части мы углубим свои знания, чтобы вы уже смогли начать отладку программ.

    Перечень всех статей, входящих в этот цикл:

      – установка, интерфейс, символы, удаленная/локальная отладка, система помощи, модули, регистры.
    • Часть 2 – точки останова.
    • Часть 3 – инспектирование памяти, пошаговая отладка программ, советы и трюки.

    Точки останова

    Точки останова – это такие маркеры, связанные с определенным адресом памяти, при достижении которых процессор останавливает выполнение программы. Приложение может состоять из миллионов ассемблерных инструкций, и проходить через каждую из них, чтобы добраться до определенного места в программе, - непозволительная трата временных ресурсов. Точки останова значительно сокращают время отладки, когда вы устанавливает маркер на определенную функцию, а процессор, автоматически выполняя весь предыдущий код, останавливается в нужном вам месте. Как только достигнута точка останова, программа останавливается, и вы можете начать отладку.

    Точки останова можно выставить как внутри приложения, так и внутри процессора (аппаратно). Рассмотрим оба этих способа:

    Программные точки останова

    Перед выполнением программа сначала загружается в память, что позволяет нам временно модифицировать участок памяти, связанный с программой, без влияния на процесс ее выполнения. Именно так и работают программные точки останова. Отладчик запоминает ассемблерную инструкцию, где должна быть вставлена точка останова, затем заменяет ее на ассемблерную инструкцию INT 3 (0xcc), которая заставляет процессор остановить выполнение программы. Как только точка останова достигнута, отладчик считывает текущий адрес памяти, достает ранее записанную инструкцию и показывает ее пользователю. Пользователю кажется, что программа остановился на этой инструкции, однако процессор не имеет ни малейшего представления о ее существовании.

    В WinDBG программные точки останова устанавливаются при помощи команд bp, bm, или bu. Команда bp (Break Point), вероятно, наиболее часто используемая команда, при помощи которой устанавливаются точки останова. В самом простейшем случае достаточно указать один адрес, по которому должна быть установлена точка останова:

    0:001> bp 00e61018

    Адрес, передаваемый команде bp, должен быть участком памяти с исполняемым кодом. Поскольку команда bp работает с памятью, где хранятся данные, то в некоторых случаях могут возникнуть проблемы, так как отладчик перезаписывает информацию, которая находится в участке памяти. Во избежание проблем компания Microsoft рекомендует использовать команду ba (о ней мы поговорим дальше) в случае, если вы работаете с памятью, где хранятся данные.

    Давайте рассмотрим, как устанавливать программные точки останова на примере приложения notepad.exe, которое мы будем запускать через WinDBG. По умолчанию, при запуске программы через WinDBG, отладчик устанавливает точку останова в самом начале программы. Для начала найдем адрес памяти, куда загрузился notepad.exe:


    Рисунок 1: Нахождение адреса загрузки notepad.exe

    Далее, используя адрес загрузки и команду !dh, находим точку входа программы:


    Рисунок 2: Нахождение точки входа программы

    Теперь устанавливаем точку останова в точку входа (адрес загрузки + 0x3689):


    Рисунок 3: Установление точки останова


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

    Аппаратные точки останова

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

    В WinDBG аппаратные точки останова устанавливаются при помощи команды ba (Break on Access). Обычно в эту команду передается три аргумента:

    0:001> ba e 1 00453689

    При помощи этой команды, вероятно, можно было добиться того же самого, что и в примере с командой bp, но только не в случае с аппаратными точками останова (вскоре мы узнаем почему). Первый аргумент e – тип доступа к памяти (на выполнение), второй аргумент – размер (всегда 1 для этого типа доступа). Последний аргумент – адрес. Давайте рассмотрим установку аппаратной точки останова, учитывая то, что наши адреса загрузки различаются из-за ASLR.

    Из-за способа, при помощи которого Windows сбрасывает контексты потока, и места, где появляется WinDBG после порождения процесса, мы не сможем установить точку останова тем же самым способом, как делали это в предыдущем примере. Ранее мы устанавливали точку останова во входной точке приложения, но если сделать так же и здесь, то возникнет ошибка:

    0:000> lmf m notepad
    start end module name
    00e60000 00e90000 notepad notepad.exe
    0:000> ba e 1 00e63689
    ^ Unable to set breakpoint error
    The system resets thread contexts after the process
    breakpoint so hardware breakpoints cannot be set.
    Go to the executable's entry point and set it then.
    'ba e 1 00e63689'

    Для решения этой проблемы нам нужно использовать команду g, чтобы программа добралась до определенного адреса памяти. Когда мы устанавливали программную точку останова, то делали примерно то же самое, но не совсем. Таким образом, мы заставляем WinDBG дойти до начального контекста потока, что впоследствии позволит нам устанавливать аппаратные точки останова.

    0:000> g 00e63689
    ModLoad: 76be0000 76bff000 C:\Windows\system32\IMM32.DLL
    ModLoad: 76c00000 76ccc000 C:\Windows\system32\MSCTF.dll
    eax=77081162 ebx=7ffd7000 ecx=00000000 edx=00e63689 esi=00000000 edi=00000000
    eip=00e63689 esp=0022fbb4 ebp=0022fbbc iopl=0 nv up ei pl zr na pe nc
    cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
    notepad!WinMainCRTStartup:
    00e63689 e8c5f9ffff call notepad!__security_init_cookie (00e63053)

    Теперь мы можем установить аппаратную точку останова:


    Рисунок 5: Установка корректной аппаратной точки останова

    Чтобы убедиться в том, что точка останова хранится в регистре процессора, можно использовать команду r (подробнее о ней мы поговорим позже). Атрибут M нужен для использования маски регистра 0x20:


    Рисунок 6: Просмотр отладочных регистров

    Из Рисунка 6 видно, что что-то мы сделали не так, и во всех регистрах находятся нули! Такое произошло потому, что WinDBG еще ничего не занес ни в один из этих регистров. После того, как вы продвинетесь на один шаг вперед, используя команду p (подробнее об этом поговорим чуть позже), то в регистр dr0 установится адрес нашей точки останова:


    Рисунок 7: При продвижении вперед на один шаг, в отладочный регистр устанавливается адрес аппаратной точки останова

    Команды для работы с точками останова

    Теперь, когда вы познакомились с базовой информацией о точках останова, мы рассмотрим некоторые команды для работы с ними, которые могут быть полезны во время отладки.

    Просмотр точек останова

    Для просмотра всех точек установленных точек останова используется команда bl (Breakpoint List).

    0:000> bl
    0 e 00523689 e 1 0001 (0001) 0:**** notepad!WinMainCRTStartup

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

    • 0 – Идентификатор точки останова
    • e – Статус точки останова - активирована (enabled) или деактивирована (disabled).
    • 00523689 – Адрес памяти
    • e 1 – Флаг доступа к адресу памяти (execute) и размер – только для аппаратных точек останова
    • 0001 (0001) – сколько раз должна сработать точка останова перед тем, как она станет активной. В скобках указано общее количество проходов (для особого варианта использования)
    • 0:**** - Информация о потоке и процессе. Данное обозначение показывает, что точка останова не специфична для потока
    • notepad!WinMainCRTStartup – соответствующий модуль и смещение функции, связанное с адресом памяти.

    Удаление точек останова

    Чтобы удалить точку останова, используйте команду bc:

    В команду передается только один параметр – идентификатор точки останова (можно узнать, выполнив команду bl). По желанию можно указать символ *, чтобы удалить все точки останова.

    Некоторые трюки при работе с точками останова

    Существует несколько трюков, которыми я обычно пользуюсь при работе с точками останова. Ниже приводятся некоторые из них. Если вы также пользуетесь какими-либо трюками, расскажите о них в комментариях!

    Вычисление адресов

    Самый простейший трюк при работе с точками останова – вычисление адреса памяти. Вместо того чтобы производить эти вычисления в голове, вы можете сделать это прямо в WinDBG. К примеру, в вышеупомянутых примерах мы знаем адрес загрузки notepad.exe и смещение входной точки программы (0x3689). Теперь мы можем вычислить адрес для установки точки останова:

    0:000> lmf m notepad
    start end module name
    00770000 007a0000 notepad notepad.exe
    0:000> bp 00770000 + 3689
    0:000> bl
    0 e 00773689 0001 (0001) 0:**** notepad!WinMainCRTStartup

    Использование имен и смещений в качестве адресов

    Символы (о которых мы говорили в первой части) особенно хороши тем, что дают нам информацию о местонахождении известных функций. Таким образом, мы можем использовать смещения к этим функциям в качестве адресов в точках останова. Для того чтобы выяснить смещение, используйте команду u. Команда u возьмет информацию по указанному адресу и отобразит ее в виде ассемблерных инструкций. Кроме того, команда u выводит смещение до ближайшего символа:

    0:000> u 00770000 + 3689
    notepad!WinMainCRTStartup:
    00773689 e8c5f9ffff call notepad!__security_init_cookie (00773053)
    0077368e 6a58 push 58h

    Теперь мы знаем, что имя notepad!WinMainCRTStartup более красивый аналог адресу 00770000 + 3689. Поскольку в конце этого имени не стоит числового смещения, мы можем сделать вывод, что для этой функции существуют символы. Давайте проверим инструкцию, которая следует сразу за первой функцией:

    0:000> u 0077368e
    notepad!_initterm_e+0x61:
    0077368e 6a58 push 58h

    В этот раз мы получили имя функции notepad!_initterm_e плюс смещение (+0x61). Я точно не знаю, почему WinDBG добавляет смещение к notepad!_initterm_e вместо notepad!WinMainCRTStartup. Вероятно, влияет порядок сортировки во время поиска символов. Тем не менее, мы можем добавить смещение к notepad!WinMainCRTStartup, чтобы сослаться на ту же самую область памяти:

    0:000> u notepad!WinMainCRTStartup+0x5
    notepad!_initterm_e+0x61:
    0077368e 6a58 push 58h

    Вся фишка в том, что мы можем использовать это смещение во время установки точки останова, и эти смещения всегда корректны, даже когда работает ASLR. То есть нам не нужно высчитывать адреса при каждом запуске.

    0:000> bp notepad!WinMainCRTStartup+0x5
    0:000> bl
    0 e 0077368e 0001 (0001) 0:**** notepad!_initterm_e+0x61

    Прерывание загрузки модуля

    На практике может возникнуть необходимость в установке точки останова во время загрузки модуля. К сожалению, не существует очевидного решения этой задачи в рамках использования стандартных команд (если вам знаком такой способ, поделитесь им в комментариях). Зато есть немного замысловатый путь, когда мы добавляем подобную точку останова, путем установки исключения при помощи команды sxe, возникающего во время загрузки модуля:

    0:000> sxe ld IMM32.DLL

    Выполняя эту команду, мы установили first chance исключение (sxe) во время загрузки модуля (ld) и определили конкретный модуль (IMM32.DLL), в котором возникает это исключение.

    Мы можем увидеть все установленные исключения, используя команду sx (Set Exceptions). Если посмотреть на список под именем Load Module, то можно увидеть прерывание на модуле IMM32.DLL.


    Рисунок 8: Прерывание на модуле IMM32.DLL

    Убрать исключение можно при помощи команды sxi (Set Exception Ignore):

    0:000> sxi ld IMM32.DLL

    Выполнение команд при срабатывании точки останова

    Может возникнуть такая ситуация, что при срабатывании точки останова будет необходимо выполнить определенные команды. К примеру, нужно узнать, что находится в стеке. В WinDBG весь процесс можно автоматизировать при помощи выполнения цепочки команд, привязанных к точке останова. В нашем примере мы будем выводить на экран информацию из стека при помощи команды dd (более подробно поговорим о ней позже). Также обратите внимание, как отображается наша команда при просмотре перечня точек останова:

    0:000> bp notepad!WinMainCRTStartup ".echo \"Here are the values on the stack:\n\"; dd esp;"
    0:000> bl
    0 e 00ae3689 0001 (0001) 0:**** notepad!WinMainCRTStartup ".echo \"Here are the values on the stack:\n\"; dd esp;"

    Теперь давайте посмотрим, что произойдет при срабатывании точки останова:


    Рисунок 9: При срабатывании точки останова отображается информация из стека

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

    Оставайтесь на связи

    В следующей статье мы рассмотрим инспектирование памяти и пошаговую отладку программы! Не переключайтесь!

    Читайте также: