Внезапно обнаружил, что уже половина июня прошла незаметно..
У кого-то каникулы-отпуска, а я тут рутиной всякой занимаюсь, и почему-то ее никак не становится меньше.
Приходится заниматься и тем и этим, и всем понемножку. К сожалению, некоторые начатые проекты для плат Марсоход подвисли из-за навалившихся работ.
Сейчас опять занимаюсь отладной / reverse-engineering очередного драйвера. Я уже как-то писал про отладку драйверов. В принципе эта информация не является какой-то уникальной, документации по отладчику WinDbg у самого Microsoft много.
Заметил, что если каким-то инструментом не пользуешься регулярно, то постепенно он забывается. Так и у меня с WinDbg.
В принципе, я знаю как им пользоваться, но приходит время и через пол года опять тратишь 1-2 дня, чтоб какую-то мелочь вспомнить.
Вот решил для самого себя написать памятку.
Простой вопрос: "Как поставить точку останова WinDbg в контексте пользовательского процесса?"
Тут история такая: Windows является многозадачной операционной системой.
В ОС одновременно выполняются множество процессов и потоков.
Причем в некоторый момент времени может оказаться, что интересующий нас процесс вообще не доступен или выгружен из памяти.
То есть, нажмем Ctrl+Break в отладчике WinDbg, Windows остановится, но где мы оказались в настоящий момент времени, во время останова?
С драйверами ядра не так. С драйверами все в некотором смысле проще. Тут выполняешь команду kd> bp mydrv!DriverEntry и точка останова готова. А вот как быть с пользовательским процессом?
- Первое. Нужно найти среди исполняемых процессов именно тот, который интересует.
Например, меня в настоящий момент интересует, что читает из файла некоторый пользовательский процесс (пусть это будет winlogon.exe). Значит делаю в отладчике Ctrl+Break, что бы прервать Windows и войти в режим команд отладчика.
Команда kd> !process 0 0 выводит список всех работающих процессов. Если знаем имя образа процесса, то можно проще:
kd> !process 0 0 winlogon.exe
PROCESS ffffe00070ec4900
SessionId: 2 Cid: 0a28 Peb: 7ff71fbc4000 ParentCid: 09cc
DirBase: 2fbfc000 ObjectTable: ffffc0003373b240 HandleCount: <Data Not Accessible>
Image: winlogon.exe
Здесь PROCESS ffffe00070ec4900 - это адрес структуры EPROCESS. Она описывает текущее состояние процесса операционной системы Windows.
- Второе. Мы знаем, что интересующий нас процесс существует, но он где-то там далеко. Отладчик скорее всего не в контексте нашего процесса. Нужно сменить контекст:
kd> .process /i ffffe00070ec4900
You need to continue execution (press 'g' <enter>) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
И это еще не все. Нужно однократно "отпустить Windows", и когда scheduler Windows переключая процессы дойдет до нашего, отладчик сам остановится уже в контексте нужного процесса. Поэтому, отпускаю Windows:
kd> g
И через секунду получаю в отладчике
Break instruction exception - code 80000003 (first chance)
nt!DbgBreakPointWithStatus:
fffff801`609dcb90 cc int 3
Это то, что нужно. Теперь я нахожусь в контексте моего процесса.
- Третье. Теперь можно поставить точку останова уже непосредственно на любую из известных нам функций API Windows прямо в нужном процессе Windows.
kd> bp /p ffffe0007095a900 kernel32!ReadFile
Параметр /p ffffe0007095a900 как раз указывает на EPROCESS нужного процесса. Ну и меня интересует Windows API связанное с чтением из файла, поэтому ReadFile.
Теперь точка останова стоит. Отпускаю Windows из отладчика:
kd> g
Теперь, каждый раз, когда именно этот экземпляр процесса winlogon.exe что-то будет читать из файла я тут же остановлюсь в отладчике и смогу посмотреть, что же было им прочитано...
Подробнее...