
Обнаруживайте, анализируйте и однозначно идентифицируйте сбои в Windows-приложениях.
=====
Обнаружение, анализ и уникальная идентификация ошибок приложений.
Хотите ли вы...
...тогда BugId может быть для вас!
Чтобы использовать BugId, пожалуйста, загрузите и установите следующее программное обеспечение:
Если вы установите Python и Debugging Tools for Windows с настройками по умолчанию, BugId должен работать без изменения каких-либо настроек. Вы можете распаковать BugId в любое место в вашей локальной файловой системе.
Перед запуском BugId вам следует включить full page heap в целевом приложении.
Это можно сделать для каждого бинарного файла путём установки определённых Global Flags. Самый простой способ сделать это — использовать
скрипт pageheap.cmd, который поставляется с BugId. Например, чтобы включить full page heap
для notepad, выполните следующую команду:
C:\BugId>pageheap notepad.exe ON
(Обратите внимание, что эту команду необходимо запускать из командной строки с повышенными привилегиями и административным доступом к машине).
Чтобы сделать всё ещё проще, pageheap.cmd содержит список известных приложений. Вы
можете включить или отключить full page heap для любого из них, указав его имя, например,
pageheap msie ON включает full page heap для Microsoft Internet Explorer. Используйте
pageheap /?, чтобы получить дополнительную информацию об аргументах командной строки.
На этом этапе вы, возможно, захотите проверить, правильно ли работает BugId. Мы можем сделать это,
запустив приложение в BugId и вызвав его крах, чтобы увидеть, правильно ли BugId сообщает об ошибке.
Хорошим приложением для этого теста является rundll32.exe, которое есть во всех
установках Windows в подпапке system32 папки Windows
(%WinDir%). Его можно использовать для загрузки любой dll, находящейся в локальной файловой системе, и вызова
экспортируемой функции в этой dll с определённым форматом вызова. В папке
system32 много dll, которые экспортируют функции. Большинство этих экспортируемых функций ожидают
аргументы в совершенно другом формате, чем тот, который предоставит rundll32, что приводит к краху приложения.
Сначала мы должны включить full page heap в rundll32 следующей командой:
C:\BugId>pageheap rundll32.exe ON
Затем мы запустим BugId и укажем ему запустить rundll32 с аргументами, которые предписывают
загрузить advapi32.dll и вызвать CloseThreadWaitChainSession. На момент написания
это вызывает так называемое нарушение прав доступа при обращении к NULL-указателю, которое BugId должен
обнаружить и о котором сообщить.
C:\BugId>BugId.cmd %WinDir%\system32\rundll32.exe -- advapi32 CloseThreadWaitChainSession
Обратите внимание, что между rundll32.exe и передаваемыми ему аргументами стоит --.
Это потому, что вы можете передавать аргументы как самому BugId, так и
приложению, которое хотите протестировать. Эти два набора аргументов должны быть разделены
-- в командной строке. Всё, что находится до --, обрабатывается
BugId, а всё, что после, игнорируется BugId, но передаётся приложению.
Если всё в порядке, вывод BugId будет выглядеть так:
* Command line: C:\WINDOWS\system32\rundll32.exe advapi32 CloseThreadWaitChainSession
+ Main process 8024/0x1F58 (rundll32.exe): Attached; command line = C:\WINDOWS\system32\rundll32.exe advapi32 CloseThreadWaitChainSession.
,-- A bug was detect in the application ----------------------------------------
| Id @ Location: AVR@NULL a1f.904 @ rundll32.exe!advapi32.dll!WctRemoveEntry
| Description: Access violation while reading memory at 0x0 using a NULL pointer.
| Security impact: Denial of Service
| Version: rundll32.exe 10.0.16299.15 (x64)
| advapi32.DLL 10.0.16299.15 (x64)
| Bug report: AVR@NULL a1f.904 @ rundll32.exe!advapi32.dll!WctRemoveEntry.html (60703 bytes)
'-------------------------------------------------------------------------------
Первая строка сообщает вам командную строку, которую BugId собирается запустить. Вторая
строка сообщает, что это привело к созданию нового процесса с идентификатором процесса
8024, запущенным rundll32.exe, и командной строкой для этого процесса (которая,
конечно же, такая же, как в первой строке). Вскоре после запуска приложения
была обнаружена ошибка. BugId сгенерировал уникальный идентификатор (AVR@NULL a1f.904)
для этой ошибки и сообщил, что её местонахождение находится в функции WctRemoveEntry
dll advapi32.dll, загруженной rundll32.exe. Поскольку крахи из-за NULL-указателя
обычно не эксплуатируемы ни для чего, кроме краха приложения, воздействие ошибки
на безопасность — Denial of Service. По умолчанию BugId создаёт HTML-отчёт
для каждой найденной ошибки и сообщает вам, где этот отчёт был сохранён.
Как вы можете видеть, имя файла отчёта основано на идентификаторе ошибки и её местонахождении.
Каждый идентификатор ошибки, создаваемый BugId, состоит из двух частей, разделённых пробелом.
Первая часть описывает тип ошибки. В приведённом выше примере AVR@NULL
это означает Access Violation Reading memory at address NULL.
Вторая часть описывает местонахождение ошибки; она состоит из двух коротких хэшей,
разделённых точкой. Эти хэши вычисляются из верхних функций в стеке,
которые считаются релевантными данной ошибке. В примере a1f.904
состоит из a1f (вычисленного из advapi32.dll!WctRemoveEntry) и 904
(вычисленного из advapi32.dll!CloseThreadWaitChainSession).
Если вы снова запустите ту же команду, BugId сообщит точно такой же BugId, поскольку это должно вызывать точно такую же ошибку в точно таком же коде.
Поздравляем! Теперь вы готовы тестировать собственные крахи с помощью BugId, но,
возможно, вам стоит в какой-то момент запустить BugId.cmd --help, чтобы получить
информацию о многочисленных параметрах командной строки, которые поддерживает BugId.
BugId был разработан и протестирован на большом количестве приложений во время фаззинга для анализа сотен тысяч крахов, вызванных сотнями различных ошибок. В этой роли он показал себя чрезвычайно точным при анализе ошибок с очень низким уровнем ложноположительных и ложноотрицательных результатов; оба показателя составляют менее 1%.
Конечно, не все типы ошибок легко обнаружить и проанализировать. Некоторые ошибки в настоящее время невозможно надёжно обнаружить в момент их возникновения, но они вызывают крах гораздо позже в совершенно несвязанном коде, что приводит к совершенно неверному анализу. В таких случаях многократное воспроизведение одной и той же ошибки приведёт к нескольким различным идентификаторам ошибок, поскольку приложение падает по-разному в разное время. Чтобы убедиться, что это не так, вам рекомендуется запустить ваш тестовый пример в BugId несколько раз и посмотреть, остаётся ли идентификатор ошибки неизменным.
Другие ошибки вызывают крахи, которые выглядят так, будто они вызваны другим типом ошибки. Это может привести к неверному анализу и неверным идентификаторам ошибок. Наиболее примечательно, что ошибки, являющиеся результатом некорректных приведений типов в коде C/C++, в настоящее время невозможно обнаружить и сообщить о них с помощью BugId. Они могут приводить к различным типам крахов; наиболее часто — к нарушениям прав доступа, когда значения, хранящиеся в свойствах объекта, ошибочно используются как указатели. Если вы подозреваете, что причиной краха могут быть некорректные приведения типов, вам следует перепроверить анализ, выполненный BugId, чтобы убедиться в его правильности.
BugId сильно зависит от использования full page heap приложением для возможности обнаружения и анализа большого количества ошибок, связанных с кучей. Это означает, что он будет гораздо менее эффективен при обнаружении и анализе ошибок в приложениях, которые используют свой собственный внутренний менеджер кучи, не полагающийся на стандартную кучу Windows.
BugId имеет бесплатный 30-дневный пробный период для коммерческого и некоммерческого использования.
В течение этого пробного периода данная работа лицензируется в соответствии с
[Creative Commons Attribution-NonCommercial 4.0 International License](http://creativecommons.org/licenses/by-nc/4.0/).
После окончания пробного периода необходимо приобрести платную лицензию на license.skylined.nl, если вы хотите продолжать использовать BugId.
Некоммерческие лицензии доступны за очень небольшую плату; ровно столько, чтобы покрыть мои расходы. Коммерческие лицензии для отдельных исследователей безопасности также доступны с огромной скидкой.
Если у вас есть вопросы по лицензированию или вы хотите обсудить оптовую скидку, пожалуйста, свяжитесь с [email protected].
BugId имеет пробный период, чтобы вы могли оценить его полезность. Если вы хотите продолжать использовать BugId после окончания пробного периода, я прошу вас внести небольшой взнос для оплаты моей работы над BugId и обработки запроса на лицензию. Если вы используете BugId в коммерческих целях, я прошу вас выплачивать регулярный лицензионный сбор, чтобы поделиться частью прибыли, которую вы получаете от использования BugId.