Why is SafeHandle.DangerousGetHandle() "Dangerous"
本文关键字:quot Dangerous is SafeHandle DangerousGetHandle Why | 更新日期: 2023-09-27 18:16:49
这是我第一次使用SafeHandle
。
我需要调用这个p/Invoke方法,它需要一个UIntPtr。
[DllImport("advapi32.dll", CharSet = CharSet.Auto)] public static extern int RegOpenKeyEx( UIntPtr hKey, string subKey, int ulOptions, int samDesired, out UIntPtr hkResult);
这个UIntPtr将从。net的RegistryKey类派生。我将使用上面的方法将RegistryKey类转换为IntPtr,因此我可以使用上面的P/Invoke:
private static IntPtr GetRegistryKeyHandle(RegistryKey rKey)
{
//Get the type of the RegistryKey
Type registryKeyType = typeof(RegistryKey);
//Get the FieldInfo of the 'hkey' member of RegistryKey
System.Reflection.FieldInfo fieldInfo =
registryKeyType.GetField("hkey", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
//Get the handle held by hkey
if (fieldInfo != null)
{
SafeHandle handle = (SafeHandle)fieldInfo.GetValue(rKey);
//Get the unsafe handle
IntPtr dangerousHandle = handle.DangerousGetHandle();
return dangerousHandle;
}
}
问题:
- 有没有更好的方法来写这个不使用"不安全"句柄?
- 为什么不安全把手是危险的?
RegistryKey有一个handle属性。所以你可以使用
private static IntPtr GetRegistryKeyHandle(RegistryKey rKey)
{
return rKey.Handle.DangerousGetHandle();
}
这是潜在的危险,因为当您使用它时,您获取的指针可能不再有效。引用自MSDN
使用DangerousGetHandle方法可能会带来安全风险,因为如果句柄已经被SetHandleAsInvalid标记为无效,那么DangerousGetHandle仍然会返回原始的、可能过时的句柄值。返回的句柄也可以在任何时候回收。最好的情况是,这意味着手柄可能突然停止工作。在最坏的情况下,如果句柄或句柄所代表的资源暴露给不受信任的代码,这可能导致对重用或返回的句柄进行回收安全性攻击。例如,不受信任的调用者可以查询刚刚返回的句柄上的数据,并接收完全不相关资源的信息。有关安全使用DangerousGetHandle方法的更多信息,请参阅DangerousAddRef和DangerousRelease方法。
你所做的实际上是危险的。当您使用IntPtr时,您使用的RegistryKey对象可以获得垃圾收集和最终确定。这使得句柄值无效,使您的代码随机失败。好吧,随机故障并不完全是危险的,但它确实为手柄循环攻击打开了大门,如果你实际上长时间持有手柄。随机的失败模式应该足以激励你做点什么。
让你的pinvoke声明看起来像这样:
[DllImport("advapi32.dll", CharSet=CharSet.Auto)]
internal static extern int RegOpenKeyEx(SafeRegistryHandle key, string subkey,
int options, int sam, out SafeRegistryHandle result);
因此您可以始终使用安全句柄包装器类。