- 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/
我有三个 td,并且正在尝试将每个内部的函数限制为仅该 td。我该怎么做呢?使用此代码,它会获取所有 3 个图像并将它们全部插入到 h2 之前: jQuery("td.frontpage_news")
这是所需的通用公式:if((b2-b1)=c1,True,False但是,我需要 b2-b1约等于 c1 , 在 5 内大约单位(在本例中为秒)。有没有可以处理这个的函数? 最佳答案 你也可以试试这个
我有三个整数,作为命令行参数传入后赋值给变量。我想验证每个整数都在 1-5 范围内。有没有一种方法可以在不使用如下所示的 if 语句的情况下在 Java 中完成此操作?我想避免这样做(注意伪代码):
检查某个变量 X 是否在某个变量 Z 的 n 个数字之内的最简洁方法是什么。n 是任意定义的数字(即 3)。 所以我想要 if (z {something} x){ // run code i
我的顶级 build.gradle (Gradle 2.2) 中有类似的东西 ext.repo = "https://my-artifactory-repo" buildscript { re
我只是在我的 jsp 页面中进行随机技巧和测试。我想使用 Attributes 将 request 范围对象存储在 session 范围对象中。存储后,当尝试从请求属性中提取值(存储在 session
我正在使用 Spring 。我有一个外部化属性文件。我正在按如下方式加载它。 现在我如何将 session 中的属性作为键值对保存? 我尝试编写一个扩展 ServletContextListene
我有以下范围: scope :billable, -> (range_start = nil, range_end = nil) { joins(:bids) .where("au
请看我的示例代码: var testObject = new SomeClass(); using (testObject) { //At this point how can the te
我目前在保持在 vector 范围内时遇到一些问题。 在下面的代码中,我试图检查正在检查的数字是否小于或等于它后面的数字 #include #include #include bool fun(
有人可以帮我解决下面的(简化的)代码吗?我试图从幻灯片事件函数中调用 doTheSlide() 函数。我对 JS 范围的理解仍然有点可疑。 实现这一目标的正确方法是什么?我收到此错误: Uncaugh
如何在 Swift 中检查时间是否在下午 6 点到晚上 11 点之间?我在使用 NSDateFormatter 时遇到了困难,我觉得一定有更简单的方法。 最佳答案 使用NSCalendar: let
我目前正在尝试创建一个 2D 横向滚动条,并且我目前有我的“世界”绘图(暂时是一个大白框),但我无法弄清楚世界地图的边缘与边缘之间的任何关系确保视口(viewport)始终完全被 map 覆盖。 我的
我正在学习李普曼,而且我只是在学习。我在这里尝试编写一个代码,该代码将返回 vector 中的最小元素。当我在 Codeblocks 中编译我的代码时,它说:“模板声明不能出现在 block 范围内”
我有三个日期对象。我该如何比较它们才能确定它们之间的相对差异。 oldDate = newDate() - 5; midDate = newDate() - 2.5; newDate = newDat
我需要检查对象“objCR”是否存在于当前范围内。我尝试使用以下代码。 if(objCR == null) alert("object is not defined"); 让我知道哪里错了。 最佳答案
如何检查 IP 地址是否属于私有(private)类别? if(isPrivateIPAddress(ipAddress)) { //do something } 如有
我正在开发一个 Firefox 插件,它可以转换用户通过用户选择突出显示的屏幕温度。转换后,用户选择将替换为 ID 为 alreadyconverted 的 span HTML 元素,其中包含原始温度
我正在开发一个邮资应用程序,该应用程序需要根据多个邮政编码范围检查整数邮政编码,并根据邮政编码匹配的范围返回不同的代码。 每个代码都有多个邮政编码范围。例如,如果邮政编码在 1000-2429、254
我正在使用 excel 范围进行连接:Set rng = Range("A1:A8")如果范围内的单元格之一为空,则会添加一个空格。 你如何阻止这个空间被添加? 最佳答案 假设您在那些非空单元格中有常
我是一名优秀的程序员,十分优秀!