在Linux(或Solaris)上,有一种比手动解析更好的方法/proc/self/maps来确定您是否可以读取,写入或执行存储在内存中一个或多个地址的任何内容?
例如,在Windows中你有VirtualQuery.
在Linux中,我可以mprotect更改这些值,但我无法读回它们.
此外,是否有任何方法可以知道这些权限何时发生变化(例如,当有人使用mmap我背后的文件时),而不是做一些非常具有侵略性的事情并ptrace在进程中的所有线程上使用并拦截任何syscall可能影响内存的尝试地图?
更新:
不幸的是,我在JIT中使用它,它几乎没有关于它正在执行的代码的信息,以获得常量的近似值.是的,我意识到我可以有一个可变数据的常量映射,比如Linux使用的vsyscall页面.我可以放心地假设任何未包含在初始解析中的内容都是可变且危险的,但我对这个选项并不完全满意.
现在我所做的是阅读/proc/self/maps并构建一个结构,我可以通过二进制搜索来获得给定地址的保护.每当我需要了解一些不在我的结构中的页面时,我会重新阅读/ proc/self/maps,假设它已经同时添加,或者我将要进行段错误.
它似乎解析文本以获取此信息,而不知道它何时更改是非常苛刻的.(/dev/inotify几乎不适用于任何事情/proc)
我使用ReadProcessMemory函数从地址空间读取数据.我尝试从所有具有MEM_PRIVATE类型的块读取.但是当该块具有PAGE_GUARD保护时,我得到错误(函数返回0),为什么?
谢谢大家.
windows operating-system readprocessmemory virtualquery virtual-address-space
我试图在 Windows 应用程序中加载的 DLL 中的某个内存范围内分配一定数量的内存。
我这样做的方式是使用VirtualQuery()搜索标记为空闲且在我需要进行分配的边界内的内存区域。我看到的是,即使该区域被标记为MEM_FREE VirtualAlloc()失败,有时也无法分配内存。
该代码非常接近以下内容:
LPVOID address = NULL, mem = NULL;
for (address = LOWER_RANGE; address < UPPER_RANGE;) {
MEMORY_BASIC_INFORMATION mbi = {0};
if (VirtualQuery(address, &mbi, sizeof(mbi))) {
if (mbi.State == MEM_FREE && mbi.RegionSize >= ALLOC_SIZE) {
mem = VirtualAlloc(address, ALLOC_SIZE,
MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READ);
if (mem) {
break;
}
}
}
address = mbi.BaseAddress + mbi.RegionSize;
}
Run Code Online (Sandbox Code Playgroud)
当VirtualAlloc()失败时,GetLastError()返回ERROR_INVALID_ADDRESS (487).
我解决它的方法是,如果它足够大,则mbi.RegionSize使用页面大小步骤扫描以查找允许我分配所需内存的地址。
为什么根据VirtualQuery整个区域应该是空闲的并且我应该能够在我想要的任何地址内分配,但是通常当第一个VirtualAlloc失败时我必须循环几个步骤直到它最终成功。
virtualquery ×3
c ×1
c++ ×1
linux ×1
mprotect ×1
system-calls ×1
virtualalloc ×1
winapi ×1
windows ×1