Создание ловушки HANDLE в WOW64

Я пытаюсь устранить проблемы с медленным запуском стороннего бинарного файла (без источника). Это 32-битное приложение, работающее в 64-битной Windows 7.

Я использовал отладчик, чтобы проникнуть в приложение, когда оно зависло с использованием ЦП 0% во время запуска, и, похоже, оно ожидает возврата ReadFile. Первый аргумент ReadFile — это значение дескриптора, 000000f0. команда Windbg !handle говорит мне:

Handle f0
  Type            File
  Attributes      0
  GrantedAccess   0x120189:
         ReadControl,Synch
         Read/List,ReadEA,ReadAttr,WriteAttr
  HandleCount     2
  PointerCount    4
  No Object Specific Information available

Я хочу знать, какому устройству это соответствует. Но Sysinternals Process Explorer не включает этот дескриптор в свой список дескрипторов процессов.

Я использовал windbg для отслеживания всех вызовов ntdll!NtCreateFile и распечатал путь и возвращенный дескриптор: Этот дескриптор не входит в их число. Точки останова на kernel32!CreateNamedPipeW, kernel32!CallNamedPipeW и kernel32!WaitNamedPipeW никогда не запускаются (что странно, потому что Process Explorer действительно показал другой дескриптор с путем \Device\NamedPipe\).

Для справки, вот команда для трассировки NtCreateFile (он же ZwCreateFile) в Windows x64:

bp ntdll!NtCreateFile "!ustr poi(@r8+10) ; r $t0 = @rcx ; gu ; dd @$t0 L1 ; gc"

Спасибо Skywing за то, что указали мне правильное направление.

Откуда еще может взяться HANDLE типа File? Разве другие функции создания HANDLE не делегируют NtCreateFile для фактического системного вызова (я думаю, что нет)?


person Ben Voigt    schedule 22.03.2012    source источник
comment
Рассматривали ли вы также монитор процессов для мониторинга запуска? Вторым вариантом может быть livekd, чтобы заглянуть в ядро ​​вещей из windbg.   -  person deemok    schedule 23.03.2012
comment
@deemok: Да, и, насколько я могу судить, procmon даже не видит вызов ReadFile, время ожидания которого истекло. Думаю, я мог бы запустить отладчик ядра, с виртуальной машиной это было бы не так уж плохо, но я пытался этого избежать. Вся необходимая информация должна быть доступна в пользовательском режиме во время вызова любого API, создающего HANDLE.   -  person Ben Voigt    schedule 23.03.2012
comment
Не знаю, является ли NtCreateFile единственной системной процедурой, вызываемой при получении HANDLE. Но я считаю, что должен быть способ обнаружить свойства HANDLE, тем не менее. В конкретном процессе HANDLE должен соответствовать основному FILE_OBJECT (если это дескриптор файла, конечно). Вы можете использовать ObReferenceObjectByHandle, проверить, что это дескриптор файла (проверьте ObjectType), а затем преобразовать данные объекта в FILE_OBJECT. Среди прочего он содержит указатель на DEVICE_OBJECT, который содержит указатель на DRIVER_OBJECT. Так что теоретически все можно открыть   -  person valdo    schedule 23.03.2012
comment
rsdn.ru/File/24534/handle.zip Эта программа выводит список всех дескрипторов для каждого процесса, и если дескриптор имеет тип «Файл», то он получает его имя с помощью драйвера и отображает его. Трудно поверить, что он сможет показать что-то, чего не может PE, но мало ли...   -  person Flot2011    schedule 23.03.2012
comment
@Flot2011: Это то же самое, что и Sysinternals Handle? Он описывается как эквивалент командной строки Process Explorer. Попробую версию от Sysinternals, я не запускаю бинарники, скачанные с какого-то неизвестного русского веб-сервера. Нет, дескриптор также не отображается в выводе handle.exe.   -  person Ben Voigt    schedule 23.03.2012
comment
Ах, но когда я использую параметр -c для handle.exe, он находит ранее не включенный в список дескриптор f0 и называет его \Device\NamedPipe. Как и вариант -a. Однако я не думаю, что это был истинный путь, который был открыт.   -  person Ben Voigt    schedule 23.03.2012
comment
@valdo: есть ли для этого команда windbg? Имеет ли значение, если windbg используется в качестве отладчика пользовательского режима?   -  person Ben Voigt    schedule 23.03.2012
comment
Возможно, дескриптор был унаследован от родительского процесса?   -  person Neil    schedule 23.03.2012
comment
@Neil: Хорошая мысль, но я уже использовал !handle, когда отладчик прерывается при входе в процесс, а он еще не существует.   -  person Ben Voigt    schedule 23.03.2012
comment
Вы пробовали SetupDiGetDeviceInterfaceDetail?   -  person Flot2011    schedule 23.03.2012
comment
@Flot2011: я использовал функции SetupDi раньше и не вижу никакой связи с отладкой открытых дескрипторов.   -  person Ben Voigt    schedule 23.03.2012
comment
В принципе, не должно ли быть возможности выполнять программу пошагово, останавливаясь, как только дескриптор создан? Поддерживает ли windbg или отладчик Visual Studio какую-либо автоматизацию?   -  person Harry Johnston    schedule 23.03.2012
comment
хорошо, если дескриптор создается в этом процессе, можно использовать расширение htrace для Windbg для отслеживания дескрипторов. С другой стороны, использование livekd не требует всех сложностей отладки в режиме ядра, и вы можете исследовать систему и наблюдать за структурами на стороне ядра.   -  person deemok    schedule 23.03.2012
comment
@Harry: Да, это разумная идея (хотя это будет очень-очень медленно). Даже если информацию о пути нелегко получить из инструкции, выполняющей системный вызов, который обновляет таблицу дескрипторов, трассировка стека из этого места должна подсказать мне, на какой API поставить точку останова.   -  person Ben Voigt    schedule 23.03.2012


Ответы (2)


Похоже, вы можете получить информацию об дескрипторе файла только при отладке ядра. Итак, есть 3 варианта.

  1. Выполните отладку ядра локальной машины, это не должно быть проблемой, поскольку вам нужно только получить информацию о дескрипторе файла, и она останется статической. См. следующее: http://msdn.microsoft.com/en-us/library/windows/hardware/ff553382(v=vs.85).aspx
  2. Выполните удаленную отладку ядра виртуальной машины. «Безопаснее» в том смысле, что вы не можете взорвать свою машину.
  3. BSOD свой бокс и посмотри дамп таким образом. Опять же, не очень приятно делать с вашей коробкой, но я делал подобные вещи в прошлом, когда мне нужно было провести полный анализ на машине без изменения состояния машины.
person Zipper    schedule 22.03.2012

Дескрипторы могут быть унаследованы, а также могут быть созданы с помощью DuplicateHandle(). Вы можете попытаться вызвать GetFileInformationByHandleEx в дескрипторе и запросите FileNameInfo.

person John    schedule 23.03.2012
comment
Как я могу сделать это из сеанса отладки? Нужно ли выполнять внедрение DLL для запуска кода внутри целевого процесса? - person Ben Voigt; 23.03.2012
comment
Это 32-разрядный сеанс отладчика, в который вы можете внедрить код с помощью команды a. push f0 push 2 push <address of some valid r/w/ memory> push 200 call kernel32!GetFileInformationByHandleEx. int 3. Затем либо исправьте ситуацию, либо просто выйдите из сеанса отладчика. - person John; 23.03.2012