- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在编写一个函数,允许用户在指定地址的 2GB +/- 范围内分配内存。我正在查询内存以找到一个空闲页面,并在那里分配。这是x64 trampoline hooking ,因为我使用的是相对 jmp 指令。
我的问题是 NtQueryVirtualMemory
因 STATUS_ACCESS_VIOLATION
错误而失败,因此总是返回 0。我很困惑为什么会发生这种情况,因为 min
(可能的最低地址)在我 checkin Process Explorer 时似乎是免费的。
LPVOID Allocate2GBRange(UINT_PTR address, SIZE_T dwSize)
{
NtQueryVirtualMemory_t NtQueryVirtualMemory = (NtQueryVirtualMemory_t)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtQueryVirtualMemory");
UINT_PTR min, max;
min = address >= 0x80000000 ? address - 0x80000000 : 0;
max = address < (UINTPTR_MAX - 0x80000000) ? address + 0x80000000 : UINTPTR_MAX;
MEMORY_BASIC_INFORMATION mbi = { 0 };
while (min < max)
{
NTSTATUS a = NtQueryVirtualMemory(INVALID_HANDLE_VALUE, min, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), NULL);
if (a)
return 0;
if (mbi.State == MEM_FREE)
{
LPVOID addr = VirtualAlloc(mbi.AllocationBase, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (addr)
return addr;
}
min += mbi.RegionSize;
}
}
最佳答案
首先是几个一般性的注释(不是关于错误的)
从我的搭配来看很奇怪NtQueryVirtualMemory
与 VirtualAlloc
.存在意义或使用
NtQueryVirtualMemory
与 NtAllocateVirtualMemory
或
VirtualQuery
与 VirtualAlloc
NtQueryVirtualMemory
与 VirtualQueryEx
相比没有任何额外功能(与 NtAllocateVirtualMemory
相比,VirtualAllocEx
通过 ZeroBits
参数具有额外的功能)
那么如果已经使用 NtQueryVirtualMemory
不需要GetProcAddress
- 您可以使用来自 wdk 的 ntdll.lib 或 ntdllp.lib 的静态链接 - 这个 api 曾经存在,并将从 ntdll.dll 喜欢VirtualQuery
从 kernel32.dll 导出,然后链接到 kernel32.lib如果你想使用 GetProcAddress
- 存在意义不是每次都这样做 Allocate2GBRange
被调用,但是一次。和调用的主要检查结果 - 可能是 GetProcAddress
返回 0 ?如果你确定 GetProcAddress
永远不会失败 - 你确定 NtQueryVirtualMemory
总是从 ntdll.dll 导出 - 所以使用 ntdll[p].lib 的静态链接
然后 INVALID_HANDLE_VALUE
就位ProcessHandle
尽管正确,但看起来很不自然。更好用NtCurrentProcess()
此处宏或 GetCurrentProcess()
.但无论如何,因为你使用 kernel32 api - 没有任何理由使用 NtQueryVirtualMemory
相反 VirtualQuery
这里
你不需要零初始化 mbi
在调用之前 - 这只是参数,因为最初总是 min < max
更好用do {} while (min < max)
改为循环 while(min < max) {}
现在关于代码中的严重错误:
mbi.AllocationBase
- 当mbi.State == MEM_FREE
- 在这个案例mbi.AllocationBase == 0
- 所以你告诉 VirtualAlloc
在任何可用空间中分配。min += mbi.RegionSize;
- mbi.RegionSize
来自 mbi.BaseAddress
- 所以将其添加到 min
不正确 - 你需要使用 min
= (UINT_PTR)mbi.BaseAddress + mbi.RegionSize;
VirtualAlloc
(当 lpAddress != 0 时)您必须使用 MEM_COMMIT|MEM_RESERVE
相反 MEM_COMMIT
仅。以及关于传递给 VirtualAlloc
的地址- 通过 mbi.AllocationBase
(只是 0)不正确。但通过 mbi.BaseAddress
万一我们找到mbi.State == MEM_FREE
区域也不正确。为什么 ?来自 VirtualAlloc
If the memory is being reserved, the specified address is rounded down to the nearest multiple of the allocation granularity.
这意味着VirtualAlloc
真的尝试分配内存而不是通过 mbi.BaseAddress
但来自 mbi.BaseAddress & ~(dwAllocationGranularity - 1)
- 较小的地址。但是这个地址可能已经很忙,结果你得到了STATUS_CONFLICTING_ADDRESSES
(ERROR_INVALID_ADDRESS
win32 错误)状态。
举个具体的例子——让你有
[00007FF787650000, 00007FF787673000) busy memory
[00007FF787673000, ****************) free memory
最初是你的 min
将在[00007FF787650000, 00007FF787673000)
繁忙的内存区域 - 结果你得到了 mbi.BaseAddress == 0x00007FF787650000
和 mbi.RegionSize == 0x23000
,因为区域繁忙 - 您将在 mbi.BaseAddress + mbi.RegionSize;
尝试下一个区域- 所以在 00007FF787673000
地址。你有mbi.State == MEM_FREE
为此,但如果您尝试调用 VirtualAlloc
与 00007FF787673000
地址 - 它将此地址向下舍入为 00007FF787670000
因为现在分配粒度是0x10000
.但是00007FF787670000
属于[00007FF787650000, 00007FF787673000)
繁忙的内存区域 - 结果 VirtualAlloc
失败 STATUS_CONFLICTING_ADDRESSES
(ERROR_INVALID_ADDRESS
)。
所以你需要使用(BaseAddress + (AllocationGranularity-1)) & ~(AllocationGranularity-1)
真的 - 地址向上舍入到最接近分配粒度的倍数。
所有代码都可以是这样的:
PVOID Allocate2GBRange(UINT_PTR address, SIZE_T dwSize)
{
static ULONG dwAllocationGranularity;
if (!dwAllocationGranularity)
{
SYSTEM_INFO si;
GetSystemInfo(&si);
dwAllocationGranularity = si.dwAllocationGranularity;
}
UINT_PTR min, max, addr, add = dwAllocationGranularity - 1, mask = ~add;
min = address >= 0x80000000 ? (address - 0x80000000 + add) & mask : 0;
max = address < (UINTPTR_MAX - 0x80000000) ? (address + 0x80000000) & mask : UINTPTR_MAX;
::MEMORY_BASIC_INFORMATION mbi;
do
{
if (!VirtualQuery((void*)min, &mbi, sizeof(mbi))) return NULL;
min = (UINT_PTR)mbi.BaseAddress + mbi.RegionSize;
if (mbi.State == MEM_FREE)
{
addr = ((UINT_PTR)mbi.BaseAddress + add) & mask;
if (addr < min && dwSize <= (min - addr))
{
if (addr = (UINT_PTR)VirtualAlloc((PVOID)addr, dwSize, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE))
return (PVOID)addr;
}
}
} while (min < max);
return NULL;
}
关于c - 在 2GB 范围内分配内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54729401/
我有一个应用程序,它会抛出 GKSession 并在各种条件下(连接超时、 session 失败等)创建一个新的 GKSession。不过,我遇到了内存泄漏问题,并且有时会在重新连接几次循环后崩溃。
比如我在宿主代码中有一个浮点指针 float *p 是否可以确定他指向的内存类型(设备/主机)? 最佳答案 在 UVA system 中, 运行时 API 函数 cudaPointerGetAttri
我已将项目转换为 .Net 4.0 并且以下代码不起作用: typeof(RuntimeTypeHandle).GetMethod("Allocate", BindingFlags.Instance
当我声明 char ch = 'ab' 时,ch 只包含 'b',为什么它不存储 'a'? #include int main() { char ch = 'ab'; printf("%c"
我对 Disk Sector 和 Block 有疑问。扇区是一个单位,通常为 512 字节或 1k、2k、4k 等取决于硬件。文件系统 block 大小是一组扇区大小。 假设我正在存储一个 5KB 的
假设我有 8 个人和5000 个苹果。 我想将所有苹果分发给所有 8 个人,这样我就没有苹果了。 但每个人都应该得到不同数量 将它们全部分发出去的最佳方式是什么? 我是这样开始的: let peopl
我正在构建的网站顶部有一个搜索栏。与 Trello 或 Gmail 类似,我希望当用户按下“/”键时,他们的焦点就会转到该搜索框。 我的 JavaScript 看起来像这样: document.onk
我有一小段代码: if (PZ_APP.dom.isAnyDomElement($textInputs)){ $textInputs.on("focus", function(){
我观察到以下行为。 接受了两个属性变量。 @property (nonatomic, retain) NSString *stringOne; @property (nonatomic, assign
我正在解决这样的问题 - 实现一个计算由以下内容组成的表达式的函数以下操作数:“(”、“)”、“+”、“-”、“*”、“/”。中的每个数字表达式可能很大(与由字符串表示的一样大)1000 位)。 “/
我有一组主机和一组任务。 每个主机都有 cpu、mem 和任务容量,每个任务都有 cpu、mem 要求。 每个主机都属于一个延迟类别,并且可以与具有特定延迟值的其他主机通信。 每个任务可能需要以等于或
该程序的作用:从文件中读取一个包含 nrRows 行和 nrColomns 列的矩阵(二维数组)。矩阵的所有元素都是 [0,100) 之间的整数。程序必须重新排列矩阵内的所有元素,使每个元素等于其所在
世界!我有个问题。今天我尝试创建一个代码,它可以找到加泰罗尼亚语号码。但是在我的程序中可以是长数字。我找到了分子和分母。但我不能分割长数字!此外,只有标准库必须在此程序中使用。请帮帮我。这是我的代码
我确定我遗漏了一些明显的东西,但我想在 Objective C 中创建一个 NSInteger 指针的实例。 -(NSInteger*) getIntegerPointer{ NSInteger
这个问题在这里已经有了答案: Difference between self.ivar and ivar? (4 个答案) 关闭 9 年前。
我如何将 v[i] 分配给一系列整数(v 的类型是 vector )而无需最初填充 最佳答案 你的意思是将 std::vector 初始化为一系列整数? int i[] = {1, 2, 3, 4,
我想寻求分配方面的帮助....我把这个作业带到了学校......我必须编写程序来加载一个 G 矩阵和第二个 G 矩阵,并搜索第二个 G 矩阵以获取存在数第一个 G 矩阵的......但是,当我尝试运行
我必须管理资源。它基本上是一个唯一的编号,用于标识交换机中的第 2 层连接。可以有 16k 个这样的连接,因此每次用户希望配置连接时,他/她都需要分配一个唯一索引。同样,当用户希望删除连接时,资源(号
是否有任何通用的命名约定来区分已分配和未分配的字符串?我正在寻找的是希望类似于 us/s 来自 Making Wrong Code Look Wrong ,但我宁愿使用常见的东西也不愿自己动手。 最佳
我需要读取一个 .txt 文件并将文件中的每个单词分配到一个结构中,该结构从结构 vector 指向。我将在下面更好地解释。 感谢您的帮助。 我的程序只分配文件的第一个字... 我知道问题出在函数 i
我是一名优秀的程序员,十分优秀!