所以我只想制作一个 Ruby 程序,从另一个进程的虚拟内存中的已知内存地址读取一些值。通过我对内存中正在运行的进程的 x86 程序集进行十六进制编辑的研究和基本知识,我找到了内存中所需值的基址和偏移量。我不想改变它们;我只是想读一下它们。我询问内存编辑器的开发人员如何处理这种语言抽象并假设 Windows 平台。他告诉我,对 OpenProcess、CreateProcess、ReadProcessMemory 和 WriteProcessMemory 的 Win32API 调用是使用 C 或 C++ 的最佳方式。我认为正确的方法就是使用 Win32API 类并映射它的两个实例;一个用于 OpenProcess 或 CreateProcess,具体取决于用户是否已经运行进程,另一个实例将映射到 ReadProcessMemory。我可能仍然需要找到用于获取正在运行的进程列表的函数,以便我知道哪个正在运行的进程是我想要的(如果它已经在运行)。

这需要一些工作才能将所有内容放在一起,但我认为编写代码不会太糟糕。这对我来说只是一个新的编程领域,因为我从未使用过高级语言(嗯,无论如何比 C 更高级别)工作过这么低的级别。我只是想知道解决这个问题的方法。我可以只使用一堆或 Win32API 调用,但这意味着必须处理一堆与系统相关的字符串和数组包和解包我希望最终使这项工作跨平台,因为我正在读取的进程是从生成的具有多个平台构建的可执行文件,(我知道内存地址因系统而异。这个想法是有一个包含所有内存映射的平面文件,这样 Ruby 程序就可以将当前平台环境与匹配的内存映射相匹配。)但从表面上看,我只需要创建一个类来包装任何内容当前平台的系统共享库内存相关函数调用。

据我所知,可能已经存在一个 Ruby gem 可以为我处理所有这一切,但我只是没有找到。我也可以尝试编辑每个构建的可执行文件,以便每当进程写入我想要读取的内存值时,它还会将新值的副本写入我以某种方式拥有的共享内存中的空间Ruby 创建一个类的实例,它是一个指向该共享内存地址的指针,并以某种方式向 Ruby 程序发出信号,表明该值已更新并且应该重新加载。基本上,基于中断的系统会很好,但由于读取这些值的目的只是发送到从中央服务器广播的记分板,因此我可以坚持使用基于轮询的系统,该系统以固定的时间间隔发送更新。我也可以完全放弃 Ruby,转而使用 C 或 C++,但我对这些也不太了解。实际上,我对 x86 的了解比对 C++ 的了解还要多,而且我只了解 C 以及与系统无关的 ANSI C,并且以前从未处理过共享系统库。

那么是否有一个 gem 或鲜为人知的模块可以做到这一点?如果没有,那么有关如何完成此操作的任何其他信息都会很好。我想,长话短说,我该怎么做这一切?

提前致谢, 格

附:另外,确认这些 Win32API 调用应该针对 kernel32.dll 库也是很好的。

有帮助吗?

解决方案

看一看 win32utils 。我在想,至少应该让你对你的脚,给你如何挖掘到API本身如果宝石本身不适合你的工作的例子。您可能需要咬紧牙关,用C写的模块。

其他提示

使用 Ruby-FFI:

如果您了解 C 和 Win32 API,那么您可能会发现它更容易使用 Ruby-FFI 宝石。 Ruby-FFI 透明地包装 C 函数,允许您使用任何 Win32 函数。

对于命名共享内存,Win32 提供 CreateFileMapping( )MapViewOfFile( ).

这些有标题

# WINBASEAPI HANDLE WINAPI CreateFileMappingA(HANDLE,LPSECURITY_ATTRIBUTES,DWORD,DWORD,DWORD,LPCSTR);
# WINBASEAPI PVOID WINAPI MapViewOfFile(HANDLE,DWORD,DWORD,DWORD,DWORD);

通过传入无效的文件句柄 0xFFFFFFFF 进入 CreateFileMapping, ,您可以完全避免处理文件,而只需使用数组和指针定义共享内存。

下面是一个从共享内存读取的简化示例。(生产质量版本将在读取器和写入器中使用信号量以及循环缓冲区,以允许两个进程异步进行,同时仍然确保写入器在读取器完成读取之前不会覆盖缓冲区。)

简化的 Ruby 示例:

require 'ffi'

module Win32
   extend FFI::Library
   ffi_lib 'kernel32'  # see winbase.h
   attach_function :CreateFileMapping, 
            :CreateFileMappingA,[ :uint, :pointer, :long, :long, :long, :pointer ], :pointer   
            # suffix A indicates the ASCII version
   attach_function :MapViewOfFile, 
            :MapViewOfFile,[ :pointer, :long, :long, :long, :long ], :pointer  
end

memoryName = "Share Memory Name"
sz_buf = 1000  # bytes  (250 ints, 4 bytes each)
num_ints = sz_buf / 4

# Windows constants
PAGE_READWRITE = 0x0004
FILE_MAP_WRITE = 2

# Get handle to shared memory
hMemory = Win32.CreateFileMapping(0xFFFFFFFF, nil, PAGE_READWRITE, 0, sz_buf, memoryName)

# Create pointer into shared memory in the reader's memory space 
pMemory = FFI::MemoryPointer.new(:int, num_ints )
pMemory = Win32.MapViewOfFile(hMemory, FILE_MAP_WRITE, 0, 0, sz_buf)

# Read from shared memory buffer
puts pMemory.read_array_of_int(sz_buf).join(" ")  

一些有用的信息:

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top