How to Find the Owner of a Named Pipe


This is a follow-up on the LPC hang blog. The same hang troubleshooting techniques apply to this, but when a named pipe is involved you’ll have to use a slightly different method to following the chain from a client application to the server application. For the purpose of this exercise I’ll use the named pipe server (http://msdn2.microsoft.com/en-us/library/aa365588.aspx) and client (http://msdn2.microsoft.com/en-us/library/aa365592.aspx) given by MSDN.



 


 


Here is a diagram of our scenario.




named_pipes



 



Here we have the client application that is waiting on a read operation to a named pipe. We need to determine what process will be putting data into the named pipe which will let the client application move forward.



Here is the thread in the client application.


 


 


THREAD 81e70858  Cid 06bc.06c0  Teb: 7ffdf000 Win32Thread: 00000000 WAIT: (Executive) UserMode Non-Alertable


    81baaf7c  NotificationEvent


Not impersonating


DeviceMap                 e25176b8


Owning Process            81b3a020       Image:         client.exe


Attached Process          N/A            Image:         N/A


Wait Start TickCount      73194          Ticks: 1599 (0:00:00:24.984)


Context Switch Count      21            


UserTime                  00:00:00.000


KernelTime                00:00:00.000


Win32 Start Address client (0x00401376)


Start Address kernel32!BaseProcessStartThunk (0x77e617f8)


Stack Init f7450000 Current f744fc04 Base f7450000 Limit f744d000 Call 0


Priority 10 BasePriority 8 PriorityDecrement 2


ChildEBP RetAddr  Args to Child             


f744fc1c 808202b6 81e70858 81e70900 00000700 nt!KiSwapContext+0x25 (FPO: [Uses EBP] [0,0,4])


f744fc34 8081fb6e 8207dac0 00000000 81baaf20 nt!KiSwapThread+0x83 (FPO: [Non-Fpo])


f744fc78 8092deb3 81baaf7c 00000000 81f93601 nt!KeWaitForSingleObject+0x2e0 (FPO: [Non-Fpo])


f744fca0 80924ca9 81f936e0 00000103 81baaf20 nt!IopSynchronousServiceTail+0x180 (FPO: [Non-Fpo])


f744fd38 8082350b 00000024 00000000 00000000 nt!NtReadFile+0x5d5 (FPO: [Non-Fpo])


f744fd38 7c8285ec 00000024 00000000 00000000 nt!KiFastCallEntry+0xf8 (FPO: [0,0] TrapFrame @ f744fd64)


0012eed4 7c82776b 77e418b2 00000024 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0])


0012eed8 77e418b2 00000024 00000000 00000000 ntdll!NtReadFile+0xc (FPO: [9,0,0])


0012ef40 004010ab 00000024 0012ef60 00001000 kernel32!ReadFile+0x16c (FPO: [Non-Fpo])


0012ff78 0040131f 00000001 00323038 00323078 client+0x10ab


0012ffc0 77e6f23b 00000000 00000000 7ffd8000 client+0x131f


0012fff0 00000000 00401376 00000000 78746341 kernel32!BaseProcessStart+0x23 (FPO: [Non-Fpo])



 


We have highlighted the first parameter to the ReadFile function. This parameter is the handle to the file we are trying to read.


Knowing this we can use the !handle extension to display details on this handle. The !handle extension takes three parameters: 1. The handle to get details on, 2: a flag controlling the level of verbosity the extension will display (f being the most verbose level), and 3: the process address.

 



kd> !handle 00000024 f 81b3a020


processor number 0, process 81b3a020


PROCESS 81b3a020  SessionId: 0  Cid: 06bc    Peb: 7ffd8000  ParentCid: 0f2c


    DirBase: 1d486000  ObjectTable: e252bbc8  HandleCount:  10.


    Image: client.exe



Handle table at e2845000 with 10 Entries in use


0024: Object: 81baaf20  GrantedAccess: 0012019f Entry: e2845048


Object: 81baaf20  Type: (823ceca0) File


    ObjectHeader: 81baaf08 (old version)


        HandleCount: 1  PointerCount: 3


        Directory Object: 00000000  Name: \mynamedpipe {NamedPipe}


We have highlighted the object address (yellow) and the type of the object (green) above. The object is of type file which is defined by the FILE_OBJECT structure. So we can examine that using the dt (Display Type) command. The dt command can take 3 parameters: 1. The structure you want to cast the data as, 2: the address of the object, and 3: the field in the structure to be displayed.


 


kd> dt nt!_FILE_OBJECT 81baaf20 FsContext2


   +0x010 FsContext2       : 0x81b5cc90


 


The FsContext2 field points to an NPFS CCB structure. The importance of this structure is that it is charged to the server process which created it. The !pool extension can be used to display information about the ownership of the memory the file object is stored in.

 


kd> !pool 0x81b5cc90  2


Pool page 81b5cc90 region is Nonpaged pool


*81b5cc88 size:   50 previous size:  140  (Allocated) *NpFc Process: 81be0d88


              Pooltag NpFc : CCB, client control block, Binary : npfs.sys



PROCESS 81be0d88  SessionId: 0  Cid: 07b4    Peb: 7ffd4000  ParentCid: 0160


    DirBase: 02b6f000  ObjectTable: e234a530  HandleCount:  10.


    Image: server.exe



 


 


Now you have the established the link from the client application and the server application. Now you will be able to move forward in your debugging and figure out why the server process isn’t writing data back to the client.


 


– Bryan