Skip to content

Instantly share code, notes, and snippets.

@santisq
Last active January 31, 2025 21:17
Show Gist options
  • Save santisq/28b79c0ae6b9fc974772c04e41ba6c32 to your computer and use it in GitHub Desktop.
Save santisq/28b79c0ae6b9fc974772c04e41ba6c32 to your computer and use it in GitHub Desktop.
some thing about handles
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
namespace HandleStuff
{
public class SystemHandle
{
private readonly SYSTEM_HANDLE _handle;
private readonly string _type;
public string TypeName
{
get { return _type; }
}
public IntPtr Object
{
get { return _handle.Object; }
}
public IntPtr UniqueProcessId
{
get { return _handle.UniqueProcessId; }
}
public IntPtr HandleValue
{
get { return _handle.HandleValue; }
}
public uint GrantedAccess
{
get { return _handle.GrantedAccess; }
}
public ushort ObjectTypeIndex
{
get { return _handle.ObjectTypeIndex; }
}
public uint HandleAttributes
{
get { return _handle.HandleAttributes; }
}
internal SystemHandle(string type, SYSTEM_HANDLE handle)
{
_type = type;
_handle = handle;
}
}
internal enum OBJECT_INFORMATION_CLASS
{
ObjectTypeInformation = 2
}
[StructLayout(LayoutKind.Sequential)]
internal struct PUBLIC_OBJECT_TYPE_INFORMATION
{
internal UNICODE_STRING TypeName;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 22)]
internal uint[] Reserved;
}
[StructLayout(LayoutKind.Sequential)]
internal struct UNICODE_STRING
{
internal ushort Length;
internal ushort MaximumLength;
internal IntPtr Buffer;
}
[StructLayout(LayoutKind.Sequential)]
internal struct SYSTEM_HANDLE
{
internal IntPtr Object;
internal IntPtr UniqueProcessId;
internal IntPtr HandleValue;
internal uint GrantedAccess;
internal ushort CreatorBackTraceIndex;
internal ushort ObjectTypeIndex;
internal uint HandleAttributes;
internal uint Reserved;
}
[StructLayout(LayoutKind.Sequential)]
internal struct SYSTEM_HANDLE_INFORMATION_EX
{
internal UIntPtr HandleCount;
internal UIntPtr Reserved;
internal SYSTEM_HANDLE Handles;
}
internal enum SYSTEM_INFORMATION_CLASS
{
SystemExtendedHandleInformation = 64
}
public static class Native
{
[DllImport("ntdll.dll")]
private static extern uint NtQuerySystemInformation(
[In] SYSTEM_INFORMATION_CLASS SystemInformationClass,
[Out] IntPtr SystemInformation,
[In] int SystemInformationLength,
[Out] out int ReturnLength);
[DllImport("ntdll.dll")]
private static extern uint RtlNtStatusToDosError(
[In] uint Status);
[DllImport("ntdll.dll")]
private static extern uint NtQueryObject(
[In] IntPtr Handle,
[In] OBJECT_INFORMATION_CLASS ObjectInformationClass,
[Out] IntPtr ObjectInformation,
[In] int ObjectInformationLength,
[Out] out int ReturnLength);
public static SystemHandle[] GetSystemHandles()
{
List<SystemHandle> handles;
IntPtr sysInfo = IntPtr.Zero;
try
{
sysInfo = GetSysHandleInfo();
SYSTEM_HANDLE_INFORMATION_EX handleInfo = Marshal
.PtrToStructure<SYSTEM_HANDLE_INFORMATION_EX>(sysInfo);
IntPtr handlesPtr = IntPtr.Add(
sysInfo,
Marshal.OffsetOf<SYSTEM_HANDLE_INFORMATION_EX>("Handles").ToInt32());
uint handleCount = handleInfo.HandleCount.ToUInt32();
int handleSize = Marshal.SizeOf<SYSTEM_HANDLE>();
handles = new List<SystemHandle>((int)handleCount);
for (int i = 0; i < handleCount; i++)
{
IntPtr handlePtr = IntPtr.Add(handlesPtr, i * handleSize);
SYSTEM_HANDLE handle = Marshal.PtrToStructure<SYSTEM_HANDLE>(handlePtr);
handles.Add(new SystemHandle(GetHandleTypeName(handle.HandleValue), handle));
}
}
finally
{
if (sysInfo != IntPtr.Zero)
{
Marshal.FreeHGlobal(sysInfo);
}
}
return handles.ToArray();
}
private static IntPtr GetSysHandleInfo()
{
int size = 512;
IntPtr sysInfo = IntPtr.Zero;
while (true)
{
if (sysInfo != IntPtr.Zero)
{
Marshal.FreeHGlobal(sysInfo);
}
sysInfo = Marshal.AllocHGlobal(size);
uint status = NtQuerySystemInformation(
SYSTEM_INFORMATION_CLASS.SystemExtendedHandleInformation,
sysInfo,
size,
out size);
if (status == 0)
{
break;
}
if (status != 0xc0000004)
{
throw new Win32Exception((int)RtlNtStatusToDosError(status));
}
size *= 2;
}
return sysInfo;
}
private static string GetHandleTypeName(IntPtr handle)
{
int size = 512;
IntPtr objectInfoBuffer = IntPtr.Zero;
try
{
while (true)
{
if (objectInfoBuffer != IntPtr.Zero)
{
Marshal.FreeHGlobal(objectInfoBuffer);
}
objectInfoBuffer = Marshal.AllocHGlobal(size);
uint status = NtQueryObject(
handle,
OBJECT_INFORMATION_CLASS.ObjectTypeInformation,
objectInfoBuffer,
size,
out size);
if (status == 0)
{
PUBLIC_OBJECT_TYPE_INFORMATION info = Marshal
.PtrToStructure<PUBLIC_OBJECT_TYPE_INFORMATION>(objectInfoBuffer);
if (info.TypeName.Buffer == IntPtr.Zero)
{
return string.Empty;
}
return Marshal.PtrToStringUni(info.TypeName.Buffer, info.TypeName.Length / 2);
}
if (status != 0xc0000004)
{
return string.Empty;
}
size *= 2;
}
}
finally
{
if (objectInfoBuffer != IntPtr.Zero)
{
Marshal.FreeHGlobal(objectInfoBuffer);
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment