Memoria segura en Windows Win32?

Iniciado por t4r0x, 31 Julio 2014, 23:28 PM

0 Miembros y 1 Visitante están viendo este tema.

t4r0x

Buenas a todos quisiera saber si alguien me puede decir como puedo implementar un codigo el cual me asegura en
no escribir mas bytes que el tamaño del buffer destino.

Lo que pasa es que en un proyecto tengo que crear memoria dinamica para muchas estructuras las cuales mantiene informacion en diferentes partes del proyecto usando HeapAlloc pero accidentalmente ya sea por mal calculos o mal escritura a la hora de escribir
coidigo podria sobrepasar el tamaño de la memoria retornada por Heapalloc y lo peor de todos es que Windows no me dice
cuando sobre escribo más del tamaño, ningun excepcion o algo así podrian darme alguna idea?

Si la idea es en C/C++ tambien me ayudaria gracias

Eternal Idol

Tenes que encapsular el acceso - al menos para escritura - a la memoria en cuestion para nunca acceder a la misma directamente, por ejemplo usando funciones propias que lo primero que hagan sea llamar a HeapSize y comprobar si debe o no continuar ...
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

t4r0x

Cita de: Eternal Idol en  1 Agosto 2014, 01:39 AM
Tenes que encapsular el acceso - al menos para escritura - a la memoria en cuestion para nunca acceder a la misma directamente, por ejemplo usando funciones propias que lo primero que hagan sea llamar a HeapSize y comprobar si debe o no continuar ...
Gracias eso me funciona para hacer una funcion tipo memcpy y comprobar
pero como haria si por ejemplo tengo un array de algun tipo y no acceder a un indice superior al limite osea
estaria accediendo a memoria no resevada, tambien situaciones donde pueda escribir mal un codigo

puntero = HeapAlloc(sizeof(typedef de estructura));  // en este caso un incorrecto typedef o tamaño incorrecto
puntero->miembro = valor;
puntero->miembro = valor;
...

podria estar accediendo a miembros pero que no hay memoria reservada para ellos.


Eternal Idol

Cita de: t4r0x en  1 Agosto 2014, 03:20 AMGracias eso me funciona para hacer una funcion tipo memcpy y comprobar
pero como haria si por ejemplo tengo un array de algun tipo y no acceder a un indice superior al limite osea
estaria accediendo a memoria no resevada, tambien situaciones donde pueda escribir mal un codigo

Eso ya no seria assembly pero la respuesta es la misma, no accedes directamente, tenes una funcion (metodo de la clase si hablamos de C++) que comprueba el limite del array.

Cita de: t4r0x en  1 Agosto 2014, 03:20 AMpuntero = HeapAlloc(sizeof(typedef de estructura));  // en este caso un incorrecto typedef o tamaño incorrecto
puntero->miembro = valor;
puntero->miembro = valor;
...

podria estar accediendo a miembros pero que no hay memoria reservada para ellos.

Seguimos en la misma, no uses HeapAlloc directamente, usa un constructor de C++ o una funcion de inicializacion. Usa codigo seguro para todo ...
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

t4r0x

Cita de: Eternal Idol en  1 Agosto 2014, 09:06 AM
Eso ya no seria assembly pero la respuesta es la misma, no accedes directamente, tenes una funcion (metodo de la clase si hablamos de C++) que comprueba el limite del array.

Seguimos en la misma, no uses HeapAlloc directamente, usa un constructor de C++ o una funcion de inicializacion. Usa codigo seguro para todo ...
Ya te entiendo muchas gracias!

Eternal Idol

La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

x64core

Cuidado con HeapSize ya que este podría no retornar el mismo valor pasado a HeapAlloc, la función retorna el tamaño del buffer, este
podría ser mayor debido a un posible alineamiento, esos bytes adicionales son validos a usar, así que donde podría haber un error copiando un numero mayor de bytes que el numero supuestos a reservados, serian copiados correctamente.

En mi experiencia podría decir que para aplicaciones donde se requiera gran uso de memoria dinámica del heap y quieran mantener control
de ella además de prevenir cualquier fuga de memoria es mejor crear tu propio heap privado para la aplicación ( HeapCreate ) y reservar
memoria desde ese heap así al final o en cualquier punto del programa que queramos comprobar cualquier fuga podemos validar los nodos
eso ahorra un montón de tiempo en depuración.

Además si es C++ se implementa una clase como te dijo Eternal Idol, el acceso a esa memoria no seria de ninguna manera directa
y la implementación de HeapAlloc o wrapper a ella debería retornar un descriptor no un puntero a la memoria en sí, ya que si se retorna el
puntero, este podría ser manipulado y también estar apuntando a memoria no reservada o en el peor de los casos a memoria valida pero
de al bloque que esperamos a copiar sino a otro.

t4r0x

Cita de: x64Core en  2 Agosto 2014, 17:30 PM
Cuidado con HeapSize ya que este podría no retornar el mismo valor pasado a HeapAlloc, la función retorna el tamaño del buffer, este
podría ser mayor debido a un posible alineamiento, esos bytes adicionales son validos a usar, así que donde podría haber un error copiando un numero mayor de bytes que el numero supuestos a reservados, serian copiados correctamente.

En mi experiencia podría decir que para aplicaciones donde se requiera gran uso de memoria dinámica del heap y quieran mantener control
de ella además de prevenir cualquier fuga de memoria es mejor crear tu propio heap privado para la aplicación ( HeapCreate ) y reservar
memoria desde ese heap así al final o en cualquier punto del programa que queramos comprobar cualquier fuga podemos validar los nodos
eso ahorra un montón de tiempo en depuración.

Además si es C++ se implementa una clase como te dijo Eternal Idol, el acceso a esa memoria no seria de ninguna manera directa
y la implementación de HeapAlloc o wrapper a ella debería retornar un descriptor no un puntero a la memoria en sí, ya que si se retorna el
puntero, este podría ser manipulado y también estar apuntando a memoria no reservada o en el peor de los casos a memoria valida pero
de al bloque que esperamos a copiar sino a otro.
Gracias por eso, lo que no entiendo es eso del descriptor podrias decirme como es que funciona?

tambien vuelvo a retomar el tema ya que no logro aun hacer lo que se supone que se debe este es mi codigo:


class MiMemoria
{
public:
   void* MyMalloc(int Size);
   void MyFree(void* Pointer);
   void MyMemcpy(void* Dest, void* Src, int size);
private:

};

void* MiMemoria::MyMalloc(int Size)
{
   return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
}

void MiMemoria::MyFree(void* Pointer)
{
   HeapFree(GetProcessHeap(), 0, Pointer);
}

void MyMemcpy(void* Dest, void* Src, int Size)
{
   int Memsize;
   Memsize = HeapSize(GetProcessHeap(), 0, Dest);

   if (Memsize > Size)
   {
       memcpy(Dest, Src, Size);
   }
   else
   {
       printf("Error!\n");
   }
}


o MASM:


.386
.model flat,stdcall

include masm32rt.inc

.code

MyMalloc proc MySize:DWORD
   invoke GetProcessHeap
   invoke HeapAlloc,eax,HEAP_ZERO_MEMORY,MySize
   ret
MyMalloc endp

MyFree proc Pointer:LPVOID
   invoke GetProcessHeap
   invoke HeapFree,eax,0,Pointer
   ret
MyFree endp


MyMemcpy proc Dest:LPVOID,Src:LPVOID,MySize:DWORD
   
   invoke GetProcessHeap
   invoke HeapSize,eax,0,Dest
   
   .if eax > MySize
       invoke RtlMoveMemory,Dest,Src,MySize
   .else
       print chr$("Error!\n")
   .endif
   
   ret
MyMemcpy endp

end


por favor diganme si lo estoy haciendo bien pero en la funcion MyMemcpy no funciona al veces, además intente hacer algo asi:

MiMemoria Test1;
MY_TYPE* Tipo1;

Tipo1 = Test1.MyMalloc(sizeof(MY_TYPE));
Test1.MyMemcpy(&Tipo1->Miembro1,&Variable_Test_1,sizeof(Variable_Test_1));
Test1.MyMemcpy(&Tipo1->Miembro2,&Variable_Test_2,sizeof(Variable_Test_2));
Test1.MyMemcpy(&Tipo1->Miembro3,&Variable_Test_3,sizeof(Variable_Test_3));
Test1.MyMemcpy(&Tipo1->Miembro4,&Variable_Test_4,sizeof(Variable_Test_4));


me dio error creo que es el puntero, y quiero preguntarles si es buena practica hacer eso es que veo que cada vez que quiero establecer un miembro tendria
que llamar a muchas funciones, nose si esta bien o no... y el codigo lo veo bien 'raro' en lugar de solo hacer esto

Tipo1->Miembro1 = Variable_Test_1;
Tipo1->Miembro2 = Variable_Test_2;
Tipo1->Miembro3 = Variable_Test_3;
Tipo1->Miembro4 = Variable_Test_4;

eso se mira mas normal creo...







Eternal Idol

http://en.wikipedia.org/wiki/Handle_%28computing%29

En definitiva son punteros indirectos, una manera MUY sencilla de implementarlos es usando un array, cada indice es un HANDLE y ese elemento del array es un puntero, el programa trabaja con los HANDLEs e internamente se hace la referencia al puntero.

En lenguajes de bajo nivel lo normal es trabajar con la memoria directamente (en C++ tambien podes usar los contenedores de la STL), es mucho mas eficiente el codigo correcto que encapsular todo, es decir esto "pero accidentalmente ya sea por mal calculos o mal escritura a la hora de escribir" no sucede con un codigo bien escrito ...

Test1.MyMemcpy(&Tipo1->Miembro1,&Variable_Test_1,sizeof(Variable_Test_1));

HeapSize dice que le pases:
A pointer to the memory block whose size the function will obtain. This is a pointer returned by the HeapAlloc or HeapReAlloc function.

No sera el caso evidentemente, solo Tipo1 en si mismo es un puntero devuelto por HeapAlloc.

En fin, es tu codigo, no esta completo y lo escribiste en dos lenguajes asi que depuralo para ver cual es el problema.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

t4r0x

Cita de: Eternal Idol en  3 Agosto 2014, 18:48 PM
http://en.wikipedia.org/wiki/Handle_%28computing%29

En definitiva son punteros indirectos, una manera MUY sencilla de implementarlos es usando un array, cada indice es un HANDLE y ese elemento del array es un puntero, el programa trabaja con los HANDLEs e internamente se hace la referencia al puntero.

En lenguajes de bajo nivel lo normal es trabajar con la memoria directamente (en C++ tambien podes usar los contenedores de la STL), es mucho mas eficiente el codigo correcto que encapsular todo, es decir esto "pero accidentalmente ya sea por mal calculos o mal escritura a la hora de escribir" no sucede con un codigo bien escrito ...

Test1.MyMemcpy(&Tipo1->Miembro1,&Variable_Test_1,sizeof(Variable_Test_1));

HeapSize dice que le pases:
A pointer to the memory block whose size the function will obtain. This is a pointer returned by the HeapAlloc or HeapReAlloc function.

No sera el caso evidentemente, solo Tipo1 en si mismo es un puntero devuelto por HeapAlloc.

En fin, es tu codigo, no esta completo y lo escribiste en dos lenguajes asi que depuralo para ver cual es el problema.
Yo pense que en lenguajes de bajo nivel como ensamblador, C y C++ es donde se usaba mas cosas seguras como esto que estoy intentando
hacer... pero si, en programas en ensamblador, C , C++ creo que no he visto clases que encapsuland el acceso a memoria... la verda me he
desanimado a continuar esta clase y mejor intentar a escribir solo codigo bien escrito pero si me pueden decir si esta bien o no, realmente el
buen habito es acostumbrarse a lenguajes de bajo nivel y escribir codigo buen seguro sin hacer tantas clases? asi es como hacen los
profesionales? por ejemplo asi es como programas como chrome, firefox son escritos? gracias por eso.