2011-12-06 20 views
5

Esta es la primera vez que usaré SafeHandle.¿Por qué SafeHandle.DangerousGetHandle() es "peligroso"?

Necesito llamar a este método P/Invoke que necesita un UIntPtr.

[DllImport("advapi32.dll", CharSet = CharSet.Auto)] 
    public static extern int RegOpenKeyEx(
     UIntPtr hKey, 
     string subKey, 
     int ulOptions, 
     int samDesired, 
     out UIntPtr hkResult); 

Este UIntPtr se derivará de clase RegistryKey de .NET. Me va a utilizar el método anterior para convertir la clase RegistryKey a un IntPtr para que pueda utilizar el P anterior/Invocar:

 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; 
      } 
} 

Preguntas:

  1. ¿Hay una mejor manera de escribir esto sin usar ¿Mangos "inseguros"?
  2. ¿Por qué las asas inseguras son peligrosas?

Respuesta

3

Lo que estás haciendo es, de hecho, peligroso. El objeto RegistryKey que utiliza puede obtener elementos recolectados y finalizados mientras usa el IntPtr. Lo que hace que el valor del identificador no sea válido, lo que hace que su código falle al azar. Bueno, está bien, la falla aleatoria no es exactamente peligrosa, pero sí abre la puerta a un ataque de reciclaje de asa si de hecho se mantiene el asa durante un período prolongado de tiempo. El modo de falla aleatoria debería ser suficiente para inspirarte a hacer algo al respecto.

Haga su declaración PInvoke aspecto:

[DllImport("advapi32.dll", CharSet=CharSet.Auto)] 
internal static extern int RegOpenKeyEx(SafeRegistryHandle key, string subkey, 
    int options, int sam, out SafeRegistryHandle result); 

esta manera puede utilizar constantemente la clase mango envoltorio seguro. Ajuste el código de reflexión en consecuencia.

+0

Olvidé mencionar que el objetivo de mi código es imitar el soporte de registro de 64 bits de NETFX4. Solo estamos utilizando NETFX 3.5 por lo que no hay SafeRegistryHandle disponible. – Ian

+0

Simplemente hágalo SafeHandleZeroOrMinusOneIsInvalid, la clase base de SafeRegistryHandle. O simplemente SafeHandle si odias escribir el nombre (quién no). –

4

El RegistryKey tiene una propiedad de control. Así que usted puede utilizar

private static IntPtr GetRegistryKeyHandle(RegistryKey rKey) 
{ 
    return rKey.Handle.DangerousGetHandle; 
} 

Esto es potencialmente peligroso, porque el puntero que está recibiendo no se aplica más cuando usted lo está utilizando. Presupuesto de MSDN

Utilizando el método DangerousGetHandle puede generar riesgos de seguridad, ya que, si el mango se ha marcado como no válido con SetHandleAsInvalid, DangerousGetHandle sigue devolviendo el valor de identificador original, potencialmente rancio. El asa devuelta también se puede reciclar en cualquier punto. En el mejor de los casos, esto significa que el identificador podría dejar de funcionar repentinamente. En el peor de los casos, si el identificador o el recurso que representa el identificador está expuesto a un código que no es de confianza, esto puede conducir a un ataque de seguridad de reciclaje en el identificador reutilizado o devuelto. Por ejemplo, una persona que llama que no es de confianza puede consultar datos en el identificador que acaba de devolver y recibir información de un recurso completamente no relacionado. Consulte los métodos DangerousAddRef y DangerousRelease para obtener más información sobre cómo usar el método DangerousGetHandle de forma segura.

+0

Olvidé mencionar que el objetivo de mi código es imitar el soporte de registro NETFX4 de 64 bits. Solo estamos usando NETFX 3.5, por lo que no hay un miembro de Handle en la clase RegistryKey. – Ian

Cuestiones relacionadas