为什么 SafeHandle.DangerousGetHandle() 是“危险的”?
这是我第一次使用 SafeHandle
。
我需要调用这个需要 UIntPtr 的 P/Invoke 方法。
[DllImport("advapi32.dll", CharSet = CharSet.Auto)] 公共静态 extern int RegOpenKeyEx( UIntPtr hKey, 字符串子键, int ul选项, int sam期望, 输出 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;
}
}
问题:
- 有没有更好的方法来编写这个而不使用“不安全”句柄?
- 为什么不安全的手柄很危险?
This is the first time ever that I'll be using SafeHandle
.
I need to call this P/Invoke method that needs an UIntPtr.
[DllImport("advapi32.dll", CharSet = CharSet.Auto)] public static extern int RegOpenKeyEx( UIntPtr hKey, string subKey, int ulOptions, int samDesired, out UIntPtr hkResult);
This UIntPtr will be derived from .NET's RegistryKey class. I will be using the method above to convert the RegistryKey class to an IntPtr so I can use the above 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;
}
}
Questions:
- Is there a better way to write this without using "unsafe" handles?
- Why are unsafe handles dangerous?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
该RegistryKey有一个句柄属性。所以你可以使用
这有潜在的危险,因为当你使用它时,你得到的指针可能不再有效。引用自 MSDN
The RegistryKey has a handle property. So you can use
This is potentially dangerous, because the pointer you are getting may not be valid anymore when you are using it. Quote from MSDN
你所做的事情实际上是危险的。当您使用 IntPtr 时,您使用的RegistryKey 对象可能会被垃圾收集并最终确定。这使得句柄值无效,从而使您的代码随机失败。好吧,随机故障并不完全危险,但如果您实际上长时间握住手柄,它确实为手柄回收攻击打开了大门。随机故障模式应该足以激励您采取措施。
使您的 pinvoke 声明如下所示:
这样您就可以一致地使用安全句柄包装类。相应地调整反射代码。
What you are doing is in fact dangerous. The RegistryKey object you use can get garbage collected and finalized while you are using the IntPtr. Which makes the handle value invalid which makes your code randomly fail. Well, okay, random failure is not exactly dangerous but it does open the door to a handle recycle attack if you in fact keep a hold of the handle for an extended period of time. The random failure mode ought to be enough to inspire you to do something about it.
Make your pinvoke declaration look like this:
So you can consistently use the safe handle wrapper class. Adjust the reflection code accordingly.