Windows process handle leak

Process Handles and Identifiers

When a new process is created by the CreateProcess function, handles of the new process and its primary thread are returned. These handles are created with full access rights, and — subject to security access checking — can be used in any of the functions that accept thread or process handles. These handles can be inherited by child processes, depending on the inheritance flag specified when they are created. The handles are valid until closed, even after the process or thread they represent has been terminated.

The CreateProcess function also returns an identifier that uniquely identifies the process throughout the system. A process can use the GetCurrentProcessId function to get its own process identifier (also known as the process ID or PID). The identifier is valid from the time the process is created until the process has been terminated. A process can use the Process32First function to obtain the process identifier of its parent process.

If you have a process identifier, you can get the process handle by calling the OpenProcess function. OpenProcess enables you to specify the handle’s access rights and whether it can be inherited.

A process can use the GetCurrentProcess function to retrieve a pseudo handle to its own process object. This pseudo handle is valid only for the calling process; it cannot be inherited or duplicated for use by other processes. To get the real handle to the process, call the DuplicateHandle function.

Process handle leak on Windows #3179

Comments

niallnsec commented Oct 30, 2019

Wire version: Version 3.10.3138
Wire for web version: Wire for Web Version 2019.10.16.1539
Operating system: Windows 10 x64
Which antivirus software do you have installed: Malwarebytes Anti-Malware

What steps will reproduce the problem?

  1. Launch Wire
  2. Handles are leaked almost immediately

What is the expected result?

The main wire process closes all open handles to child processes once they have exited.

What is the actual result?

The process handles remain open, preventing the OS from reclaiming the PID and associated resources (other than memory). Presumably the process objects are still being referenced somewhere or are not being disposed of.

Please provide any additional information below. Attach a screenshot if possible.

The following is a screenshot from ProcessHacker showing the open handles. After having Wire running on a system continuously for several days the resource consumption becomes significant. After a week I found my system started to have issues with other tasks (source compilation to be specific, as this requires many processes to spawn) which is what lead me to notice this issue during investigation.

Currently the issue can be worked around by simply quitting and restarting wire.

The text was updated successfully, but these errors were encountered:

Handle leak occurs in the Audiodg.exe process in Windows 7 or in Windows Server 2008 R2

Symptoms

Assume that you play sound repeatedly on a computer that is running Windows 7 or Windows Server 2008 R2. In this situation, a handle leak occurs in the Audiodg.exe process. When this issue occurs, the handle count of the Audiodg.exe process in Task Manager increases.

Resolution

Hotfix information

A supported hotfix is available from Microsoft. However, this hotfix is intended to correct only the problem that is described in this article. Apply this hotfix only to systems that are experiencing the problem described in this article. This hotfix might receive additional testing. Therefore, if you are not severely affected by this problem, we recommend that you wait for the next software update that contains this hotfix.

If the hotfix is available for download, there is a «Hotfix download available» section at the top of this Knowledge Base article. If this section does not appear, contact Microsoft Customer Service and Support to obtain the hotfix.

Note If additional issues occur or if any troubleshooting is required, you might have to create a separate service request. The usual support costs will apply to additional support questions and issues that do not qualify for this specific hotfix. For a complete list of Microsoft Customer Service and Support telephone numbers or to create a separate service request, visit the following Microsoft website:

http://support.microsoft.com/contactus/?ws=supportNote The «Hotfix download available» form displays the languages for which the hotfix is available. If you do not see your language, it is because a hotfix is not available for that language.

Prerequisites

To apply this hotfix, you must be running Windows 7 Service Pack 1 (SP1) or Windows Server 2008 R2 Service Pack 1 (SP1).

For more information about how to obtain a Windows 7 or Windows Server 2008 R2 service pack, click the following article number to view the article in the Microsoft Knowledge Base:

Читайте также:  Windows 10 настройка кнопки выключения компьютера windows

976932 Information about Service Pack 1 for Windows 7 and for Windows Server 2008 R2

Registry information

To apply this hotfix, you do not have to make any changes to the registry.

Restart requirement

You must restart the computer after you apply this hotfix.

Hotfix replacement information

This hotfix does not replace a previously released hotfix.

File information

The global version of this hotfix installs files that have the attributes that are listed in the following tables. The dates and the times for these files are listed in Coordinated Universal Time (UTC). The dates and the times for these files on your local computer are displayed in your local time together with your current daylight saving time (DST) bias. Additionally, the dates and the times may change when you perform certain operations on the files.

Windows 7 and Windows Server 2008 R2 file information notes

The files that apply to a specific product, milestone (RTM, SP n), and service branch (LDR, GDR) can be identified by examining the file version numbers as shown in the following table:

Windows 7 and Windows Server 2008 R2

Windows 7 and Windows Server 2008 R2

GDR service branches contain only those fixes that are widely released to address widespread, extremely important issues. LDR service branches contain hotfixes in addition to widely released fixes.

The MANIFEST files (.manifest) and the MUM files (.mum) that are installed for each environment are listed separately in the «Additional file information for Windows Server 2008 R2 and for Windows 7» section. MUM and MANIFEST files, and the associated security catalog (.cat) files, are extremely important to maintain the state of the updated components. The security catalog files, for which the attributes are not listed, are signed with a Microsoft digital signature.

Windows process handle leak

I feel like I’m in school; excellent address once again. 5

Sign In· View Thread

How to Avoid Deadlocks

Turion 28-Nov-09 14:16
Hi all,

I’ve run across this problem so much that I finally found the solution by myself. Nobody seems to know how Process Explorer and other programs avoid deadlocks on pipes, so I thought I’d share what I found out.

Yes, you can use the SYNCHRONIZE access mask and avoid anything that is synchronous, but that is way too broad. And no, using ObQueryNameString in a driver doesn’t change anything. The key is to use the pointer to the object (which you get along with the handle when you retrieve all the handles in the system) and see if ALL of these conditions are satisfied (I assume the pointer is named pObject):

1. *(SHORT*)pObject == 5
> In other words, is this a FILE_OBJECT, which means it can be a pipe? (I assume pObject is of type FILE_OBJECT in the next steps.)

2. CONTAINING_RECORD(pObject, OBJECT_HEADER, NameInfoOffset) == 0
> Gets the object’s header from the object, and sees if there’s no pre-determined name already given to the object (if there is, we won’t deadlock)
> You can find the definition of OBJECT_HEADER in ReactOS, but just as a note, the beginning of object’s header is (sizeof(LONG) + sizeof(PVOID) * 2 + 4 * sizeof(BYTE) + sizeof(PVOID) * 2) bytes behind beginning of the object.

3. (pObject->Flags & FO_SYNCHRONOUS_IO) == 0
> Is this file/pipe opened synchronously?

4. (pObject->Device != NULL) && ((pObject-Device->DeviceType != FILE_DEVICE_DISK) & (pObject-Device->DeviceType != FILE_DEVICE_DISK_FILE_SYSTEM))
> Is there a device behind the object (there should be) and is it something other than a disk or disk file system (they don’t deadlock)?

If TRUE for ALL of these, then deadlock is possible. The solution? Get the object name for the pObject’s device (ObQueryNameString(pObject-Device)) and concatenate it to the object’s file name (pObject->FileName, a UNICODE_STRING value). This last step uses ObQueryNameString, a kernel-mode function; however, if pObject-Device->DeviceType == FILE_DEVICE_NAMED_PIPE, then you can assume it’s \Device\NamedPipe.

How do you actually access the kernel-mode memory to do all this without a driver? NtSystemDebugControl and SysDbgReadVirtual are your friends! (Google them.)

Hope this helps!

Sign In· View Thread
Re: How to Avoid Deadlocks

TheRaven 18-Sep-11 17:39

Sign In· View Thread
Handle.exe

Baroon 1-Sep-08 7:35
Hi Toby, So Many thanks for this article. I have a question about handle.exe’s output. When I use handle -a, it shows all open handles include objects with no name! Would you please tell me what are these objects? There are some Files, Sections, Ports, Mutants, Events and Semaphores that don’t have any name.

Thank you in advance.

Sign In· View Thread
ntCreateFile Handles

Kharfax 22-Jun-06 3:09
Hi mate, first of all, thanks for writing great articles

I’m working in a windows hook, and I need to get a copy of the handles generated by zwCreateFile
I was geting the pointer of the stack, calling the real service, and then copying the value pointed by the PHANDLE I got before.
And in your article I see you are getting the handle from EAX, wich is a LOTTTT simpler than what I’m doing.

So the question is, where did you get that info? It would be really helpfull to me.

Thanks a lot mate

Sign In· View Thread
Re: ntCreateFile Handles

Toby Opferman 22-Jun-06 6:58

The return value from a function is put into EAX/RAX and so the user mode API «CreateFile» will return you the handle in EAX. However, «ZwCreateFile» I believe returns a status code and requires you pass a pointer to recieve the handle as a parameter to the API. So, what you are doing is what you would need to do for that API.

The article in any case does not actually display the location of where it currently is when I dump the handle, so I could be anywhere executing that has just put the handle value into EAX actually. I wrote this article a few years ago, but most likely I was at the return from CreateFile when I copied that text.

8bc7c0ec02c0e404c0cc0680f7018827ebee

Sign In· View Thread
Re: ntCreateFile Handles

Kharfax 22-Jun-06 7:33

damn :S
Thanks a lot for the explanation, and yes, zwCreateFile first parameter is a pointer to the handle.
So, I think the suffering continues

Sign In· View Thread
!process

mtavis 26-May-05 5:00
When I attempt to use !process in WinDbg it complains that no export was found. !handle works fine though. Is there some sort of extension I need to install?

P.S. Great series of articles

Sign In· View Thread
Re: !process

Toby Opferman 27-May-05 20:02

Thanks for the complement. In order to use !process you must be kernel debugging, this will not work with debugging a user mode process. It should be loaded by default when kernel debugging though.

8bc7c0ec02c0e404c0cc0680f7018827ebee

Sign In· View Thread
NtQueryObject and Sync question

Neil 14-Feb-05 3:04

Neil

14-Feb-05 3:04
Thank you, first of all. Excellent article. As somebody thrust into C++ at the moment, it is extremely helpful.

The article mentions deadlocking NTQueryObject calls, and mentions avoiding this by use of checking masks.

I am encountering exactly this symptom on an in-house written application I am trying to wade through, but have been able to suss out more information on it. By mask, I assume we’re talking about the SystemHandleInfo->HandleInfo.AccessMask property (this code is using a duplicated handle to look for things).

Could anybody point me to further information on checking for SYNC access, or the use of masks to avoid this deadlock?

P.S. Although I am not (yet) an experienced C++ programmer, I have a good bit of experience with APIs and programming in general — it doesn’t have to be a totally newbie source.

Neil

Sign In· View Thread
Re: NtQueryObject and Sync question

Toby Opferman 14-Feb-05 9:53

The code I wrote is in assembly. I think I have some C code somewhere else but not with me here.

The code I used in quick view to attempt to avoid deadlock:

@HandView_NoPortInfo:
LEA EAX, [dwTempLong]
PUSH EAX
PUSH 512
PUSH EBX ; Unicode String is appened to the END of the structure.
PUSH ObjectTypeInformation
PUSH [hObject]
CALL [ZwQueryObject]

CMP EAX, 0
JL @HandView_SkipWithCloseAndCloseObject

CMP DWORD PTR [EBX + 4] , 0
JZ @HandView_SkipWithCloseAndCloseObject

MOV EAX, [EBX + 4]
PUSH EAX
PUSH 2
PUSH [dwCount]
PUSH [hWnd]
CALL ListView_SetItemTextW

MOV WORD PTR [EBX], 500
MOV WORD PTR [EBX + 2], 500
LEA EAX, [EBX + 8]
MOV [EBX + 4], EAX

MOV EAX, [pModInfo]

MOV EAX, [pModInfo]

TEST DWORD PTR [EAX + 12], SYNCHRONIZE_ACCESS ; *SOME* Sync Objects can cause deadlock! Unfortunately, this is the only way to
JZ @HandView_Good ; tell right now, excluding all sync objects.

CMP DWORD PTR [EAX + 12], 01f01ffh ; This seems to be OK access.
JNE @HandView_SkipWithCloseAndCloseObject

; TODO: See if you can remove Sync Access or another way to get the
; object name from user-mode without having to acquire the lock.
; could be bad though and bluescreen? Also, irrelevant if I
; change this to use a driver. The driver would be able to
; directly read the object’s memory location in the kernel
; and read the name directly from there without the need to lock.

LEA EAX, [dwTempLong]
MOV DWORD PTR [EAX], 0
PUSH EAX
PUSH 500
PUSH EBX ; Unicode String is appened to the END of the UNICODE_STRING structure.
PUSH ObjectNameInformation
PUSH [hObject]
CALL [ZwQueryObject]

; TODO: Try ZwQueryInformationFile with «name».

; Sysinternals uses their own driver to do this and does not deadlock.
; If we aren’t getting all the information, I may need to write a driver.
; TODO: Write a driver for this application, we need one anyway for
; a force bluescreen option when Ctrl ScrollLock ScrollLock is not set.

CMP EAX, 0
JL @HandView_SkipWithCloseAndCloseObject

TEST EAX, EAX
JZ @HandView_SkipWithCloseAndCloseObject

PUSH EAX
PUSH 1
PUSH [dwCount]
PUSH [hWnd]
CALL ListView_SetItemTextW

MOV EAX, [pModInfo]

TEST BYTE PTR [EAX + 5], 1 ; We need to fix this in order to close the handle.
JZ @HandView_CloseIt

PUSH 0
PUSH 0FFFFFFFEh
PUSH [hObject]
CALL SetHandleInformation ; Clear the «protect from close» bit so we can close the handle.

@HandView_CloseIt:
PUSH [hObject]
CALL CloseHandle

@HandView_SkipWithClose:
@HandView_SkipHandleInfo:
ADD ESP, 512
POP EBX
LEA EAX, [dwShortToLong]

Sign In· View Thread
Re: NtQueryObject and Sync question

Toby Opferman 14-Feb-05 10:31

The definition of:

SYNCHRONIZE_ACCESS EQU 0100000h

This is actually the granted access mask of the handle.
Excerpt from CDB. Notice «Synch» and the bits set.

0:000> !handle 0 ff
Handle c
Type File
Attributes 0
GrantedAccess 0x100020:
Synch
Execute/Traverse
HandleCount 3
PointerCount 4
No Object Specific Information available
Handle 7ec
Type Port
Attributes 0
GrantedAccess 0x1f0001:
Delete,ReadControl,WriteDac,WriteOwner,Synch
Connect
HandleCount 2
PointerCount 4
Name
No Object Specific Information available

Sign In· View Thread
Re: NtQueryObject and Sync question

Anonymous 15-Feb-05 2:25

Thank you very much =]

This will take some muddling through and processing, but it looks like exactly what I need. I’m sure I’ll be back to thank you again

Neil

Sign In· View Thread
Re: NtQueryObject and Sync question

Neil 16-Feb-05 10:07

Neil

16-Feb-05 10:07

Thanks. That worked just fine. (And I learned a *lot* more about C ). Interesting thing is that most of the system had SYNCHRONIZE_ACCESS set, and the app wouldn’t hang at the same location (or on the same object type/access mask). It works well with a very restricted mask (like you used, except h160001).

I’m mostly just thrilled that I can still follow the assembly code, after all these years

Neil

Sign In· View Thread
Re: NtQueryObject and Sync question

Neil 3-Mar-05 6:45

Neil

3-Mar-05 6:45

I received an anonymous request for details on how I got around this in C (CodeProject doesn’t necessarily include your email if you mail thorugh the forums).

Here is the boiled-down code that I used. Please don’t accept this as a good example of code — it’s kludged together from various sources, and probably not well. It does almost exactly what

If it doesn’t copy-and-paste, I apologize. My system at work and codeproject can’t seem to get together . . .

Sign In· View Thread
Re: NtQueryObject and Sync question

Neil 3-Mar-05 7:00

Neil

3-Mar-05 7:00

Please note, this is almost exactly the same as what Toby does (all credit to him, code errors are my fault) with the exception of the actual value; Toby’s code assumes it won’t block if the AccessMask does not have h100000 set or if it equals h01f01ff. In my case, everything I was looking for *did* have the bit set, and objects with a mask of h160001 locked up (other object masks did, too, but inconsistently, and this fixed it for my specific circumstances).

Toby’s version would be more along these lines (except better-written):
if (!(pSystemHandleInfo->HandleInfo[i].AccessMask && 0x100000) || (pSystemHandleInfo->HandleInfo[i].AccessMask == 0x01f01ff))

Chances are that you will have to figure out what mask you need independantly — mine isn’t as safe as Toby’s, it’s just all that worked.

The code included is from where I got it to work — the printfs showed me the masks on the fly, and I ran it a number of times, until I could figure out which masks I needed or didn’t need.

Neil

Sign In· View Thread
Re: NtQueryObject and Sync question

Rajkumar-Kannan 4-Mar-05 4:23

Hi,
Thank you very much for taking the time out for replying. I have found some combination of access masks that are specific to my environment and seem to work well.

Thanks again!
Raj.

Sign In· View Thread
oh.exe — tool for tracking handle leaks

mattiash 27-May-04 10:50
Great article.

In addition I’d like to recommend OH.EXE, which is a handy and free tool from Microsoft really useful for tracking down handle leaks. Basically you let the OS keep track of callstacks when handles are opened and closed. Then you can take snapshots and compare, so you see the allocated handles that haven’t been closed so you can identify leaks.

Sign In· View Thread
!htrace Pavel Lebedinsky 12-May-04 21:32
!htrace is a very useful command for debugging handle leaks because it gives you the stack traces of recent operations on a handle.

To use it you need to enable handle checks in the appverifer first:

c:\debuggers> gflags -v image /enable notepad.exe HANDLE_CHECKS
c:\debuggers> cdb notepad

0:004> !htrace 4dc
—————————————
Handle = 0x000004DC — OPEN
Thread Process/>
0x77D06D25: ntdll!RtlpInitializeTimerThreadPool+0x0000009E
0x77D06DFD: ntdll!RtlpInitializeWorkerThreadPool+0x0000001C
0x77D082FB: ntdll!RtlQueueWorkItem+0x00000055
0x77E6EC01: kernel32!QueueUserWorkItem+0x00000014
0x772DB369: SHLWAPI!SHQueueUserWorkItem+0x00000076
0x75F845C2: +0x000045C2
0x763B48C3: comdlg32!AutoComplete+0x0000008C
0x763BD372: comdlg32!InitLocation+0x00000520
0x763B3D70: comdlg32!OpenDlgProc+0x000003AF
0x77D8857A: USER32!InternalCallWinProc+0x00000028
0x77D96422: USER32!UserCallDlgProcCheckWow+0x000000F0

Sign In· View Thread
Re: !htrace

Toby Opferman 13-May-04 3:30

Yea, I remember seeing that in the help a while back and getting excited.

One thing to note though is that it’s for Windows 2003/XP only. As I stated above, there’s a lot of new cool features in 2003/XP that aren’t in 2000

Sign In· View Thread
Last Visit: 31-Dec-99 18:00 Last Update: 17-Apr-21 7:27 Refresh 1

General News Suggestion Question Bug Answer Joke Praise Rant Admin

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Читайте также:  Вызов эмодзи windows 10
Оцените статью