3

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

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

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

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

提前致谢, Grg

PS:另外确认那些 Win32API 调用应该针对 kernel32.dll 库会很好。

4

2 回答 2

2

看看win32utils。我认为这至少应该让你站起来,并举例说明如果宝石本身不适合你,如何深入研究 API 本身。您可能需要硬着头皮用 C 语言编写一个模块。

于 2010-05-15T01:16:37.870 回答
2

使用 Ruby-FFI:

如果您了解 C 和 Win32 API,那么您可能会发现使用Ruby-FFIgem 更容易。 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(" ")  

一些有用的信息:

于 2013-01-20T17:45:06.733 回答