Autor
|
Tema: ERROR_INVALID_ADDRESS al usar VirtualAllocEx con una dirección fija (Leído 3,971 veces)
|
[Zero]
Wiki
Desconectado
Mensajes: 1.082
CALL DWORD PTR DS:[0]
|
Bueno, pues la duda es lo que dice el título, estoy intentando usar VirtualAlloc o VirtualAllocEx, me da igual, para reservar memoria en una dirección de memoria fija, en concreto en 0x0040000 (teniendo el base address de mi ejecutable en 00300000). Levo días buscando la razón del error pero no encuentro nada que me sirva, ejecutando lo siguiente: #pragma comment(linker,"/NODEFAULTLIB") #pragma comment(linker,"/ENTRY:main") #include <Windows.h> int main() { //CHAR MSG[1024]; //SYSTEM_INFO SystemInfo; //GetSystemInfo(&SystemInfo); //wsprintfA(MSG,"%s%X%s%X","MinimumApplicationAddress: ",SystemInfo.lpMinimumApplicationAddress,"\nMaximumApplicationAddress: ",SystemInfo.lpMaximumApplicationAddress); //MessageBoxA(0,MSG,"Info",MB_ICONINFORMATION); if(!VirtualAllocEx(GetCurrentProcess(),(LPVOID)0x00400000,0x1000,MEM_RESERVE|MEM_COMMIT,PAGE_EXECUTE_READWRITE)) { MessageBoxA(0,"Error al reservar memoria en 0x00400000",0,MB_ICONERROR); return 0; } MessageBoxA(0,"Memoria Reservada correctamente en 0x00400000","Éxito",MB_ICONINFORMATION); return 0; }
Ojo, linkear el ejecutable con una dirección base diferente de 0x00400000 o en su defecto cambiar la dirección fija a reservar. Éste código, en mi PC Win7 32bits reserva memoria bien sólo a veces, otras veces falla devolviendo last_error ERROR_INVALID_ADDRESS. Viendo con olly me dice que la dirección no está en uso incluso cuando falla, pero el error es como sí la dirección estuviera ya reservada . Gracias por adelandato
|
|
« Última modificación: 31 Agosto 2010, 20:50 pm por [Zero] »
|
En línea
|
“El Hombre, en su orgullo, creó a Dios a su imagen y semejanza. Nietzsche
|
|
|
>FedeX<
|
Con cheat engenie se ve como a veces en 0x00400000 hay memoria en uso...
|
|
|
En línea
|
|
|
|
Littlehorse
All the world's a stage
Moderador
Desconectado
Mensajes: 2.714
Nie Dam Sie
|
Es necesario utilizar una dirección fija que posiblemente pueda no estar libre, o solo es por probar?
Utiliza VirtualQuery para chequear el estado de la región, o en su defecto VADUMP.
Saludos
|
|
|
En línea
|
An expert is a man who has made all the mistakes which can be made, in a very narrow field.
|
|
|
[Zero]
Wiki
Desconectado
Mensajes: 1.082
CALL DWORD PTR DS:[0]
|
Necesito usarlo con una dirección fija, me da igual cual pero es necesario que sea fija. En la documentación de la MSDN dice que es perfectamente posible, y ese parámetro no tendría sentido si no fuera así, pero buscando no encuentro más que gente con el mismo problema e hilos a los que no se llega a una solución. Si esa memoria está reservada, el proceso no la está utilizando aparentemente para nada, intente hacer VirtualFree pero sigue sin funcionar . Al ejecutar VirtualQuery VirtualAlloc falla siempre, incluso cuando ésta me devuelve MEM_FREE . Saludos
Edito: Hice ésto para ver si me quedaba algo más claro que pasaba, pero sólo logró confundirme más : #pragma comment(linker,"/NODEFAULTLIB") #pragma comment(linker,"/ENTRY:main") #include <Windows.h> int main() { MEMORY_BASIC_INFORMATION Buffer; VirtualQuery((LPVOID)0x00400000,&Buffer,sizeof(MEMORY_BASIC_INFORMATION)); switch(Buffer.State) { case MEM_COMMIT: MessageBoxA(0,"MEM_COMMIT","Info",MB_ICONINFORMATION); if(!VirtualFree((LPVOID)0x00400000,0x1000,MEM_DECOMMIT)) { MessageBoxA(0,"Error al desencomendar memoria",0,MB_ICONERROR); } else { MessageBoxA(0,"Memoria Desencomendada","Info",MB_ICONINFORMATION); if(!VirtualFree((LPVOID)0x00400000,0,MEM_RELEASE)) { MessageBoxA(0,"Error liberar memoria",0,MB_ICONERROR); } else { MessageBoxA(0,"Memoria Reservada Liberada","Info",MB_ICONINFORMATION); } } break; case MEM_RESERVE: MessageBoxA(0,"MEM_RESERVE","Info",MB_ICONINFORMATION); if(!VirtualFree((LPVOID)0x00400000,0,MEM_RELEASE)) { MessageBoxA(0,"Error liberar memoria",0,MB_ICONERROR); } else { MessageBoxA(0,"Memoria Reservada Liberada","Info",MB_ICONINFORMATION); } break; case MEM_FREE: MessageBoxA(0,"Memoria Libre","Info",MB_ICONINFORMATION); break; } if(!VirtualAlloc((LPVOID)0x00400000,0x1000,MEM_RESERVE|MEM_COMMIT,PAGE_EXECUTE_READWRITE)) { MessageBoxA(0,"Error al reservar memoria en 0x00400000",0,MB_ICONERROR); return 0; } MessageBoxA(0,"Memoria Reservada correctamente en 0x00400000","Éxito",MB_ICONINFORMATION); return 0; }
|
|
« Última modificación: 2 Septiembre 2010, 15:53 pm por [Zero] »
|
En línea
|
“El Hombre, en su orgullo, creó a Dios a su imagen y semejanza. Nietzsche
|
|
|
Littlehorse
All the world's a stage
Moderador
Desconectado
Mensajes: 2.714
Nie Dam Sie
|
VirtualAlloc mas direcciones hardcodeadas, no es la mejor combinación. Cuidado con los 0 de mas y de menos en las direcciones, que a simple vista ya se ven errores: if(Buffer.State==MEM_COMMIT) { if(!VirtualFree((LPVOID)0x0040000,0x1000,MEM_DECOMMIT))
0x0040000!=0x0040000 0case MEM_RESERVE|MEM_COMMIT:
Ese case esta de mas. VirtualFreeEx(GetCurrentProcess(),(LPVOID)0x00400000,0,MEM_DECOMMIT);
Si utilizas decommit en una región de memoria sin utilizar release, esta cambia su estado a reservado , o sea, lista para asignar (Suponiendo que sea posible). Por ende, la llamada a VirtualAllocEx va a fallar del modo que estas usando, porque estas intentando reservar una dirección que ya esta reservada. Asignarla es lo que debería seguir. VirtualAllocEx(GetCurrentProcess(),ADR,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
Antes de seguir, busca los artículos de Mark Russinovich acerca de todo esto ya que explican todo con lujo de detalle. Y sobre todo atención a los "remarks" de la documentación de cada API, porque es eso lo que te esta trayendo dramas. . Cabe destacar también, que el proceso real que debería realizarse es mucho mas largo, porque esto vale como ejemplo pero en una aplicacion no podes dejar pasar cosas como las posibles medidas de protección de cada región. Tengo por acá un código que quizas te pueda servir ya que realiza lo que necesitas, es bastante largo y pesado pero de seguro sacas en limpio lo necesario. En un rato lo busco y si lo encuentro te lo mando por pm. Saludos
|
|
« Última modificación: 2 Septiembre 2010, 01:02 am por Littlehorse »
|
En línea
|
An expert is a man who has made all the mistakes which can be made, in a very narrow field.
|
|
|
[Zero]
Wiki
Desconectado
Mensajes: 1.082
CALL DWORD PTR DS:[0]
|
Muchas gracias Littlehorse, seguiré trabajando y leyendo esta tarde siguiendo tus indicaciones . Saludos
Edito: Arreglé el código de antes, sigue fallando pero al menos ahora los resultados que devuelve son coherentes. Por cierto, ¿que programa usaste arriba para ver el estado de las páginas de memoria?
|
|
« Última modificación: 2 Septiembre 2010, 15:55 pm por [Zero] »
|
En línea
|
“El Hombre, en su orgullo, creó a Dios a su imagen y semejanza. Nietzsche
|
|
|
Littlehorse
All the world's a stage
Moderador
Desconectado
Mensajes: 2.714
Nie Dam Sie
|
De nada . El programa del screen es Cheat Engine que para este caso vale perfectamente, pero para el resto lo ideal es WinDBG. Con Cheat Engine: Memory view + (ctrl +R) Con WinDBG: !address -summary !address Addr Saludos!
|
|
|
En línea
|
An expert is a man who has made all the mistakes which can be made, in a very narrow field.
|
|
|
|
|