Pregunta

Quiero crear un asignador que proporciona la memoria con los siguientes atributos:

  • no puede ser paginado en el disco.
  • es increíblemente difícil acceso a través de un adjunto depurador

La idea es que este va a contener información sensible (como la información sobre la licencia), que debe ser inaccesible para el usuario.He hecho la habitual línea de investigación y pregunté a un par de otras personas acerca de esto, pero no puedo encontrar un buen lugar de inicio en este problema.

Actualizaciones

Josh menciona el uso de VirtualAlloc para configurar la protección en el espacio de la memoria.He creado un asignador personalizado ( se muestra abajo ) he encontrado que el uso de la VirtualLock la función se limita la cantidad de memoria que puedo asignar.Esto parece ser por el diseño, aunque.Desde que la estoy usando para objetos pequeños esto no es un problema.

//
template<class _Ty>
class LockedVirtualMemAllocator : public std::allocator<_Ty>
{
public:
    template<class _Other>
    LockedVirtualMemAllocator<_Ty>& operator=(const LockedVirtualMemAllocator<_Other>&)
    {   // assign from a related LockedVirtualMemAllocator (do nothing)
        return (*this);
    }

    template<class Other>
    struct rebind {
        typedef LockedVirtualMemAllocator<Other> other;
    };

    pointer allocate( size_type _n )
    {
        SIZE_T  allocLen = (_n * sizeof(_Ty));
        DWORD   allocType = MEM_COMMIT;
        DWORD   allocProtect = PAGE_READWRITE;
        LPVOID pMem = ::VirtualAlloc( NULL, allocLen, allocType, allocProtect );
        if ( pMem != NULL ) {
            ::VirtualLock( pMem, allocLen );
        }
        return reinterpret_cast<pointer>( pMem );
    }
    pointer allocate( size_type _n, const void* )
    {
        return allocate( _n );
    }

    void deallocate(void* _pPtr, size_type _n )
    {
        if ( _pPtr != NULL ) {
            SIZE_T  allocLen = (_n * sizeof(_Ty));
            ::SecureZeroMemory( _pPtr, allocLen );
            ::VirtualUnlock( _pPtr, allocLen );
            ::VirtualFree( _pPtr, 0, MEM_RELEASE );
        }
    }
};

y se utiliza

 //a memory safe std::string
 typedef std::basic_string<char, std::char_traits<char>, 
                           LockedVirtualMemAllocato<char> > modulestring_t;

Ted Percival menciona mlock, pero yo no tengo ninguna aplicación de las que todavía.

He encontrado Práctica de Criptografía por Neil Furguson y Bruce Schneier muy útil también.

¿Fue útil?

Solución

Realmente no se puede proteger contra el acceso a la memoria.Usted probablemente puede evitar la paginación si está ejecutando como administrador o como el sistema, pero no puede evitar que la administración o de sistema a partir de la lectura de su memoria.Incluso si de alguna manera podría bloquear por completo los otros procesos de la lectura de su memoria (que no puede), otro proceso aún podría introducir un nuevo hilo en el proceso y leer la memoria de esa manera.

Incluso si se pudiera de alguna manera completamente bloquear el proceso y la garantía de que el sistema operativo sería nunca permitir que nadie tenga acceso a su proceso, usted todavía no tiene una protección completa.Todo OS podría estar ejecutando en una máquina virtual, que podría ser detenido e inspeccionado en cualquier momento.

Usted no proteger el contenido de la memoria del propietario del sistema.Hollywood y la industria de la música han estado doliendo por esto durante años.Si es posible, que ya había logrado hacer.

Otros consejos

En los sistemas Unix que puede utilizar mlock(2) para bloquear las páginas de memoria en la memoria RAM, evitando que ellos se paginado.

mlock() y mlockall (), respectivamente bloqueo de parte o de todas las llamadas proceso del espacio de direcciones virtuales en la memoria RAM, evitando que la memoria de ser paginada para el área de swap.

Hay un límite a la cantidad de memoria de cada proceso, se puede bloquear, puede ser demostrado con ulimit -l y se mide en kilobytes.En mi sistema, el límite predeterminado es 32 kiB por proceso.

Si usted está en desarrollo para Windows, hay maneras que usted puede restringir el acceso a la memoria, pero absolutamente el bloqueo de los demás no es factible.Si usted está esperando para guardar un secreto secreto, leer Escribir Código Seguro - que se ocupa de este problema en algunos de longitud, pero tenga en cuenta que usted no tiene ninguna manera de saber si el código se está ejecutando en una máquina o en una máquina virtual.Hay un montón de API de Win32 cosas para tratar de cifrado, que se encarga de este tipo de cosas, incluyendo el almacenamiento seguro de los secretos - el libro habla de eso.Usted puede mirar en el online Microsoft CyproAPI para más detalles;el sistema operativo de los diseñadores de reconocer este problema y la necesidad de mantener el texto sin cifrar de forma segura (de nuevo, leer Escribir Código Seguro).

La función de API de Win32 VirtualAlloc es el nivel de SO asignador de memoria.Te permite configurar la protección de acceso;lo que puedes hacer es configurar el acceso a PAGE_GUARD o PAGE_NOACCESS, y voltear el acceso a algo más amigable mientras el programa lee y se restablecerá después, pero esto es simplemente un badén si alguien está tratando muy duro para echar un vistazo a su secreto.

En resumen, mirar el Api de cifrado en su plataforma, que van a tratar mejor el problema de algo que hackear a ti mismo.

Vamos a tomar esto un poco a un tiempo:

Quiero crear un asignador que proporciona la memoria con el siguiente atributos:

Que es bastante justo.

* cannot be paged to disk.

Que va a ser difícil.Hasta donde yo soy consciente, no se puede deshabilitar Virtual de Paginación como es manejado por el sistema operativo.Si hay una manera, entonces usted va a ser la espeleología en las entrañas del sistema operativo.

* is incredibly hard to access through an attached debugger

Puede ejecutar a través de PGP y la tienda se cifran en la memoria y descifrar si es necesario.Enorme impacto en el rendimiento.

La idea es que este contendrá la información sensible (como la licencia información) que debe ser inaccesible para el usuario.He hecho la costumbre de investigación en línea, y le pidió a una algunas otras personas sobre esto, pero me no se puede encontrar un buen lugar de inicio de esta problema.

Mantener toda la información confidencial fuera de la máquina.En serio.No almacenamos información sensible en la memoria.Escribir una costumbre eliminar la rutina que eliminará automáticamente todos los datos de las asignaciones de realizar.Nunca permitir el acceso general a una máquina con el material sensible en él.Si realiza db de acceso, asegúrese de que todo el acceso es desinfectado antes de su cocción.Sólo personas con el log-ins tienen permitido el acceso.Ningún general de acceso de grupo.

En una nota de lado, ¿qué otros métodos se hay de acceso a la memoria de un proceso otro que el de colocación de un depurador?

Tomando un volcado de la memoria.

instalar Libsodium, el uso de mecanismos de asignación de #incluyendo <sodium.h>

Vigilado las asignaciones del montón

Más lento que malloc() y sus amigos, se requieren 3 o 4 páginas de la memoria virtual.

void *sodium_malloc(size_t size);

Asignar memoria para almacenar datos confidenciales mediante sodium_malloc() y sodium_allocarray().Tendrás que llamar sodium_init() antes de usar estas montón de guardias.

void *sodium_allocarray(size_t count, size_t size);

El sodium_allocarray() la función devuelve un puntero a partir de la cual el conteo de objetos que son de tamaño bytes de memoria cada uno puede tener acceso.Ofrece las mismas garantías que sodium_malloc() pero también protege contra la aritmética se desborda cuando count * size supera SIZE_MAX.

Estas funciones agregar páginas de protección en torno a la protección de datos para que sea menos probable a ser accesible en un heartbleed-como escenario.

Además, la protección de las regiones de memoria asignada de esa manera puede ser cambiado mediante el bloqueo de las operaciones de la memoria: sodium_mprotect_noaccess(), sodium_mprotect_readonly() y sodium_mprotect_readwrite().

Después de sodium_malloc puede utilizar sodium_free() para desbloquear y liberar memoria.En este punto de su aplicación considere la posibilidad de puesta a cero de la memoria después de su uso.

cero de la memoria después de su uso

void sodium_memzero(void * const pnt, const size_t len);

Después de su uso, de datos sensibles deben ser sobrescritos, pero memset() y el código a mano puede ser en silencio despojado por un compilador de optimización o por el enlazador.

El sodium_memzero() función intenta efectivamente cero len bytes a partir pnt, incluso si las optimizaciones se aplica el código.

el bloqueo de la asignación de memoria

int sodium_mlock(void * const addr, const size_t len);

El sodium_mlock() la función de los bloqueos al menos len bytes de memoria comenzando en la dirección.Esto puede ayudar a evitar el intercambio de datos confidenciales en el disco.

int sodium_mprotect_noaccess(void *ptr);

El sodium_mprotect_noaccess() función hace que una región asignada usando sodium_malloc() o sodium_allocarray() inaccesible.No puede ser leído o escrito, pero los datos son conservados.Esta función puede ser utilizada para hacer que los datos confidenciales inaccesibles, excepto cuando sea realmente necesario para una operación específica.

int sodium_mprotect_readonly(void *ptr);

El sodium_mprotect_readonly() la función de las marcas de una región asignada usando sodium_malloc() o sodium_allocarray() como de sólo lectura.El intento de modificar los datos provocará la terminación del proceso.

int sodium_mprotect_readwrite(void *ptr);

El sodium_mprotect_readwrite() la función de las marcas de una región asignada usando sodium_malloc() o sodium_allocarray() como lectura y escritura, después de haber sido protegido mediante sodium_mprotect_readonly() o sodium_mprotect_noaccess().

Lo que usted está pidiendo que se maneja a nivel de sistema operativo.Una vez que los datos están en su programa, es responsable de la paginada.

Para acceder a la memoria, un individuo motivado, se puede adjuntar un depurador de hardware.

@graham

Puede ejecutar a través de PGP y la tienda se cifran en la memoria y descifrar si es necesario.Enorme impacto en el rendimiento.

Luego tendrías que tener la clave en la memoria.Que sería un poco más difícil, pero no imposible.Alguien motivado todavía se las arreglan para obtener los datos de la memoria.

Su mejor apuesta es implementar algo similar .NET SecureString de la clase, y ser muy cuidadoso a cero cualquier texto de copias de sus datos, tan pronto como haya terminado (no te olvides de limpieza, incluso cuando se producen excepciones).Una buena manera de hacer esto con std::string, y tal es el uso de un asignador personalizado.

En Windows, si usas CryptProtectMemory (o RtlEncryptMemory para los sistemas más antiguos), el cifrado de la contraseña se almacena en no paginable (kernel?) memoria.En mis pruebas, estas funciones son bastante rápida, esp.teniendo en cuenta la protección que le están dando.

En otros sistemas, me gusta usar Blowfish, ya que es una buena mezcla entre la velocidad y la fuerza.En el último caso, usted tendrá que generan su propia contraseña (16+ bytes de entropía para Blowfish) al inicio del programa.Por desgracia, no hay mucho que usted puede hacer para proteger la contraseña sin soporte en el sistema operativo, aunque es posible que el uso general de las técnicas de ofuscación para incrustar una rígida sal valor a tu ejecutable que puedes combinar con la contraseña (cada poco ayuda).

En general, esta estrategia es sólo una parte de un más amplio de la defensa-en-profundidad de enfoque.También hay que tener en cuenta que errores simples, tales como desbordamientos de búfer y no de desinfección programa de entrada siendo, con mucho, el más común de los vectores de ataque.

Usted puede proteger el contenido de la memoria del propietario del sistema.Hollywood y la industria de la música han estado doliendo por esto durante años.Si es posible, que ya había logrado hacer.

Ha tenido usted un vistazo a la Vista (y por encima) Protegida De Los Procesos De (directo .descargar doc).Creo que el sistema operativo forzada de protección es cortesía de la industria del entretenimiento.

@Derek:Oh, pero con trusted computing, puede utilizar memoria cortinas!:-P</devils-advocate>

@roo

Yo estaba realmente esperando que es posible, y que yo no había encontrado todavía.Su ejemplo me hizo darse cuenta de que eso es exactamente lo que estamos tratando de hacer - sólo se permite el acceso a los archivos en el contexto de nuestro programa y así preservar la IP.

Supongo que tengo que aceptar que no hay realmente manera segura para almacenar alguien archivos en otro equipo, especialmente si en algún momento se permite el acceso a ese archivo por el propietario.

Ese es definitivamente el problema.Usted puede guardar de forma segura tanto tiempo como nunca el acceso a la subvención, pero tan pronto como el acceso a la subvención, su control se ha ido.Usted puede hacer un poco más difícil, pero eso es todo.

@Chris

Oh, pero con trusted computing, usted puede usar la memoria de cortinas!:-P

Pero entonces usted tiene que estar dispuesto a pagar por un equipo que pertenece a otra persona.:p

@Derek Parque

Él sólo dijo más difícil, que no imposible.PGP haría más difícil, que no imposible.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top