我敢肯定这是一个非常奇怪的问题,但相信我,它有道理。我在 GameMaker 语言中有一个值数组,我希望能够在数组中搜索数组边界之外的值,并检索这些超出边界的值,而不是返回错误并停止游戏。基本上,在使用越界索引搜索数组时,我想故意从附近的内存中提取不正确的数据。这可能吗?先感谢您!
问问题
74 次
1 回答
1
但相信我,这有道理
最好提及您为什么要做某事,以便如果无法做到,可以在没有后续问题的情况下给出建议。
GameMaker 不允许无效的内存访问(外来错误除外),尽管即使允许,也会有更多问题 - 如果您检查 YYGML.h(在运行时目录中),GML 值由 表示struct RValue
,即 16 -byte 结构,由 8 个值字节(如数值、字符串指针、数组指针等)、值类型索引和元数据标志组成。换句话说,尝试将任意内存作为 GML 值读取是行不通的,因为类型和标志都是垃圾,当您点击指向无效内存的指针类型值时,很可能会导致运行时因访问冲突而崩溃地点。
如果你想在你的进程中读取任意内存,你可以编写一个本地扩展(通常在 C++ 中),它带有一个函数,该函数接受一个缓冲区地址(来自buffer_get_address
)、起始地址和长度,通过调用VirtualQuery
(验证内存区域是否可访问并检索边界),然后memcpy
。
此类函数的非 GML 特定实现可能如下所示:
bool safeCopy(byte* out, const byte* from, size_t size) {
const auto pmask = PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE |
PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY;
auto at = from;
auto till = at + size;
::MEMORY_BASIC_INFORMATION mbi{};
while (at < till) {
if (!VirtualQuery(at, &mbi, sizeof mbi)) return false;
if ((mbi.State == MEM_COMMIT) && !(mbi.Protect & PAGE_GUARD) && (mbi.Protect & pmask)) {
const byte* m_begin = static_cast<const byte*>(mbi.BaseAddress);
const byte* m_end = m_begin + mbi.RegionSize;
at = m_end;
if (m_end > till) m_end = till;
if (m_begin < from) m_begin = from;
memcpy(out + (m_begin - from), m_begin, m_end - m_begin);
} else return false;
}
return true;
}
于 2020-12-21T10:26:49.130 回答