虚拟内存处理
我正在开发一个PE加载器,就像Windows加载器一样
,我的目标是一个可执行文件而不是DLL,我首先尝试了loadlibrary,但遇到了重新分配问题,得到了一些代码来修复它,但它不适用于所有目标(某些exe的需要可能要在同一个 BaseAdress 处加载才能工作
,所以我说到了重点,我必须实现我的加载程序以确保 BaseAddress 问题并且不需要重新分配
我强制我的应用程序以较高的速度加载addr(0x10000000),在使用 VirtualAlloc 为目标应用程序的标头和部分分配内存时,
我使用 VirtualQuery 来查看要分配的地址的状态,如果没有空闲,则如果页面类型为 MEM_MAPPED,则使用 UnMapViewOfFile,否则 VirtualFree(MEM_RELEASE)
问题是,如果内存页面是 MEM_MAPPED 和 MEM_COMMIT(始终是页面文件支持的页面),则所有方法都会失败并显示错误代码; 0x57 ERROR_INVALID_PARAMETER
寻找解决方案/想法这里是代码:
MylpAddr = (DWORD)lpAddr ;
MemInfo.RegionSize = 0 ;
NtUnmapViewOfSection= (NTUNMAPVIEWOFSECTION)GetProcAddress(LoadLibrary(TEXT("ntdll.dll")), "NtUnmapViewOfSection");
NtProtectVirtualMemory= (NTPROTECTVIRTUALMEMORY)GetProcAddress(LoadLibrary(TEXT("ntdll.dll")), "NtProtectVirtualMemory");
NtUnlockVirtualMemory= (NTUNLOCKVIRTUALMEMORY)GetProcAddress(LoadLibrary(TEXT("ntdll.dll")), "NtUnlockVirtualMemory");
GetSystemInfo(&siSysInfo);
szPage = siSysInfo.dwPageSize ;
i = VirtualQuery( (LPCVOID)MylpAddr , &MemInfo , 0x20 ) ;
if (!i) return NULL ;
if ( !(MemInfo.State & MEM_FREE) )
{
if ( MemInfo.Type & MEM_MAPPED )
{
hProc = GetCurrentProcess() ;
szPage = MemInfo.RegionSize ;
i = NtUnlockVirtualMemory(hProc , (PVOID *)MemInfo.AllocationBase , (PULONG)szPage , LOCK_VM_IN_WORKING_SET | LOCK_VM_IN_RAM );
i = NtProtectVirtualMemory(hProc , (PVOID *)MemInfo.AllocationBase , (PULONG)szPage , PAGE_READWRITE , &OldProt ) ;
i = NtUnmapViewOfSection( hProc , (LPVOID)MemInfo.AllocationBase );
i = UnmapViewOfFile( (LPVOID)MemInfo.AllocationBase );
if (!i) i =1 ;
}
else
{
j = VirtualUnlock(MemInfo.BaseAddress , MemInfo.RegionSize);
i = VirtualFree( (LPVOID)MemInfo.AllocationBase , NULL , MEM_RELEASE ) ;
}
if (!i) return NULL ;
}
MylpAddr = (DWORD)VirtualAlloc( lpAddr , dwSize , AllocType , ProtFlags );
I'm working on a PE Loader, just like windows loader
my target is an executable not DLL,i tried first loadlibrary but faced reallocation problems,got some code to fix it, but it didn't work with all targets (some exe's needs to be loaded at the same BaseAdress to work probably
so i got to the point, i've to implement my loader to ensure the BaseAddress issue and no need for reallocation
I'm forcing my application to load at a high addr(0x10000000),while using VirtualAlloc to allocate memory for headers & sections for the target app
i use VirtualQuery to see the state of the address i want to allocate, if not free i use UnMapViewOfFile if Page type MEM_MAPPED else VirtualFree(MEM_RELEASE)
The problem is that if the memory pages are MEM_MAPPED & MEM_COMMIT (always page file backed pages) all methods fails with error code 0x57 ERROR_INVALID_PARAMETER
looking for solutions/ideas here's the code :
MylpAddr = (DWORD)lpAddr ;
MemInfo.RegionSize = 0 ;
NtUnmapViewOfSection= (NTUNMAPVIEWOFSECTION)GetProcAddress(LoadLibrary(TEXT("ntdll.dll")), "NtUnmapViewOfSection");
NtProtectVirtualMemory= (NTPROTECTVIRTUALMEMORY)GetProcAddress(LoadLibrary(TEXT("ntdll.dll")), "NtProtectVirtualMemory");
NtUnlockVirtualMemory= (NTUNLOCKVIRTUALMEMORY)GetProcAddress(LoadLibrary(TEXT("ntdll.dll")), "NtUnlockVirtualMemory");
GetSystemInfo(&siSysInfo);
szPage = siSysInfo.dwPageSize ;
i = VirtualQuery( (LPCVOID)MylpAddr , &MemInfo , 0x20 ) ;
if (!i) return NULL ;
if ( !(MemInfo.State & MEM_FREE) )
{
if ( MemInfo.Type & MEM_MAPPED )
{
hProc = GetCurrentProcess() ;
szPage = MemInfo.RegionSize ;
i = NtUnlockVirtualMemory(hProc , (PVOID *)MemInfo.AllocationBase , (PULONG)szPage , LOCK_VM_IN_WORKING_SET | LOCK_VM_IN_RAM );
i = NtProtectVirtualMemory(hProc , (PVOID *)MemInfo.AllocationBase , (PULONG)szPage , PAGE_READWRITE , &OldProt ) ;
i = NtUnmapViewOfSection( hProc , (LPVOID)MemInfo.AllocationBase );
i = UnmapViewOfFile( (LPVOID)MemInfo.AllocationBase );
if (!i) i =1 ;
}
else
{
j = VirtualUnlock(MemInfo.BaseAddress , MemInfo.RegionSize);
i = VirtualFree( (LPVOID)MemInfo.AllocationBase , NULL , MEM_RELEASE ) ;
}
if (!i) return NULL ;
}
MylpAddr = (DWORD)VirtualAlloc( lpAddr , dwSize , AllocType , ProtFlags );
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
抱歉提出这么老的问题,我只是认为这可能对某人有帮助。
据我所知,要分叉一个进程,您必须使用 CreateProcess 函数。因此,您需要使用 VirtualQueryEx 和 VirtualAllocEx 而不是 VirtualQuery 和 VirtualAlloc。还将 hProc 值替换为您创建的进程的句柄。我还注意到您已明确使用 0x20 作为 dwLength,您可能需要使用 dwSize 更改它。
总结:
Sorry for bringing up such an old question, I just thought it might help someone.
As far as I know, to fork a process you must have used CreateProcess function. Therefore you need to use VirtualQueryEx and VirtualAllocEx instead of VirtualQuery and VirtualAlloc. Also replace hProc value with a handle to your created process. I also noticed that you have explicitly used 0x20 as dwLength that you probably need to change it with dwSize.
In summary: