Skip to content
This repository has been archived by the owner on Sep 2, 2022. It is now read-only.

Potential memory leak due to not implementing IDisposable correctly in LocalGroupTasks #38

Open
JohnLaTwC opened this issue Jul 12, 2021 · 1 comment

Comments

@JohnLaTwC
Copy link

I am not an expert on this but from my reading, if you need to free unmanaged resources, you can implement IDisposable. LocalGroupTasks.cs has a helper class that tries to do this, but it looks to have two bugs.

Bug 1: Failure to inherit from IDisposable.

OBJECT_ATTRIBUTES implements Dispose() but does not inherit from IDisposable. Without this, Dispose may never be called.

Note the definition here: (https://www.pinvoke.net/default.aspx/Structures/OBJECT_ATTRIBUTES.html)

-        internal struct OBJECT_ATTRIBUTES
+       internal struct OBJECT_ATTRIBUTES : IDisposable
        {
            public int Length;
            public IntPtr RootDirectory;
            public uint Attributes;
            public IntPtr SecurityDescriptor;
            public IntPtr QualityOfService;
            private IntPtr _objectName;
            public UNICODE_STRING ObjectName;

            public void Dispose()
            {
                if (_objectName == IntPtr.Zero)
                    return;

                Marshal.DestroyStructure(_objectName, typeof(UNICODE_STRING));
                Marshal.FreeHGlobal(_objectName);
                _objectName = IntPtr.Zero;
            }
        }

internal struct OBJECT_ATTRIBUTES

Bug 2: Need to call Dispose() explicitly

The documentation on implementing Dispose says that you should call it explicitly or wrap the object in a using block--as the GC is not guaranteed to call it. The easiest thing here is to call Dispose in the finally block.

            finally
            {
                //Free memory from handles acquired during the process
                if (serverHandle != IntPtr.Zero)
                    SamCloseHandle(serverHandle);
                if (domainHandle != IntPtr.Zero)
                    SamCloseHandle(domainHandle);
                if (aliasHandle != IntPtr.Zero)
                    SamCloseHandle(aliasHandle);
+                if (objectAttributes != null)
+                    objectAttributes.Dispose();

                if (members != IntPtr.Zero)
                    SamFreeMemory(members);
            }

SamCloseHandle(aliasHandle);

@rvazarkar
Copy link
Contributor

Will be fixed in vnext:

SpecterOps/SharpHoundCommon@5a05d6d

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants