Trapping HANDLE creation in WOW64
Asked Answered
S

2

7

I'm trying to troubleshoot slow startup of a third-party binary (no source). It is a 32-bit application running on 64-bit Windows 7.

I've used a debugger to break into the application while it's hung with 0% CPU usage during startup, and it appears to be waiting for ReadFile to return. The first argument to ReadFile is the handle value, 000000f0. windbg's !handle command tells me:

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

I want to know what device this corresponds to. But Sysinternals Process Explorer doesn't include this handle in its list of process handles.

I've used windbg to trace all calls to ntdll!NtCreateFile and printed the path and returned handle: This handle is not among them. Breakpoints on kernel32!CreateNamedPipeW, kernel32!CallNamedPipeW, and kernel32!WaitNamedPipeW are never triggered (which is odd because Process Explorer did show another handle with path \Device\NamedPipe\).

For reference, here is the command to trace NtCreateFile (akak ZwCreateFile) on Windows x64:

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

Thanks to Skywing for pointing me in the right direction on that.

Where else can a HANDLE of type File come from? Don't the other HANDLE creation functions delegate to NtCreateFile for the actual syscall (I guess not)?

Sorbian answered 22/3, 2012 at 21:49 Comment(14)
Have you also considered process monitor to monitor startup? A second option would be livekd to look into the kernel side of things from windbg.Akilahakili
@deemok: Yes, and as far as I can tell, procmon doesn't even see the ReadFile call that's timing out. I guess I could run a kernel debugger, with a VM it wouldn't be too bad, but I've been trying to avoid that. All the necessary information ought to be available in user mode, at the time the call is made to whatever API creates the HANDLE.Sorbian
Don't know if NtCreateFile is the only system routine invoked in obtaining a HANDLE. But I believe there should be a way to discover the HANDLE properties nevertheless. Within the specific process the HANDLE should correspond to the underlying FILE_OBJECT (if it's a file handle of course). You may use ObReferenceObjectByHandle, verify its a file handle (check ObjectType), then cast the object data to FILE_OBJECT. It contains among other things a pointer to DEVICE_OBJECT, which contains a pointer to DRIVER_OBJECT. So everything theoretically can be discoveredDisarray
rsdn.ru/File/24534/handle.zip This program lists all handles for each process and if the handle is of the type 'File', then it obtains its name, using the driver, and displays it. It's hard to believe that it will be able to show something that PE can't, but you never know...Nettles
@Flot2011: Is that the same as Sysinternals Handle? It's described as a command-line equivalent to Process Explorer. I'll give the Sysinternals version a try, I'm not running binaries downloaded from some unknown Russian web server. Nope, the handle doesn't appear in the output of handle.exe either.Sorbian
Ah, but when I use the -c option to handle.exe, it finds the previously unlisted handle f0, and calls it \Device\NamedPipe. So does the -a option. I don't think that's the true path that was opened, however.Sorbian
@valdo: Is there a windbg command to do that? Does it matter if windbg is being used as a user-mode debugger?Sorbian
Perhaps the handle was inherited from its parent process?Ppi
@Neil: Good thought, but I already used !handle when the debugger breaks on process entry, and it doesn't exist yet.Sorbian
Have you tried SetupDiGetDeviceInterfaceDetail?Nettles
@Flot2011: I've used the SetupDi functions before and I don't see any connection with debugging open handles.Sorbian
In principle, shouldn't it be possible to single-step through the program, stopping as soon as the handle is created? Do windbg or the visual studio debugger support any kind of automation?Whereby
well, provided the handle is created in this process, one could use windbg's htrace extension to track handles. On the side note, using livekd does not require all the kernel mode debugging complications and you could explore the system and watch the kernel side structures.Akilahakili
@Harry: Yes, that's a reasonable idea (although it will be very very slow). Even if the path information isn't easily accessible from the instruction that makes the syscall that updates the handle table, a stack trace from that location should tell me what API to place my breakpoint on.Sorbian
F
1

It looks like you can only get the file handle information when doing a kernel debug. So there are 3 options.

  1. Do a local machine kernel debug, this shouldn't be a problem since you only need to get the file handle information and that will stay static. See the following: http://msdn.microsoft.com/en-us/library/windows/hardware/ff553382(v=vs.85).aspx
  2. Do a remote kernel debug of a VM machine. "Safer" in the sense you can't blow up your machine.
  3. BSOD your box and look at the dump that way. Again not a very nice thing to do to your box, but I've done similar things in the past when I needed to be able to do a full analysis on the machine without the machine state changing.
Forbes answered 22/3, 2012 at 22:54 Comment(0)
K
1

Handles can be inherited and can also be created by DuplicateHandle(). You can try to calling GetFileInformationByHandleEx on the handle and query for FileNameInfo.

Knap answered 23/3, 2012 at 0:14 Comment(2)
How can I do this from a debug session? Do I need to perform DLL injection to run code inside the target process?Sorbian
It's a 32-bit debugger session you can inject code with the a command. push f0 push 2 push <address of some valid r/w/ memory> push 200 call kernel32!GetFileInformationByHandleEx. int 3. Then either fix things up or just quit the debugger session.Knap

© 2022 - 2024 — McMap. All rights reserved.