所以我只想做一个Ruby程序,从另一个进程的虚拟内存中的已知内存地址读取一些值。通过我对十六进制编辑内存中运行进程的x86程序集的研究和基础知识,我找到了我想要的内存中的值的基址和偏移量。我不想改变它们;我只是想读它们。我问一位内存编辑器的开发人员如何处理这种语言摘要并假设一个Windows平台。他告诉我Win32API调用OpenProcess,CreateProcess,ReadProcessMemory和WriteProcessMemory是使用C或C ++的方法。我认为要走的路只是使用Win32API类并映射它的两个实例;一个用于OpenProcess或CreateProcess,具体取决于用户是否已经运行了进程,另一个实例将映射到ReadProcessMemory。我可能仍然需要找到获取正在运行的进程列表的函数,所以我知道哪个正在运行的进程是我想要的。
这需要一些工作才能将所有内容放在一起,但我认为编写代码并不算太糟糕。这对我来说只是一个新的编程领域,因为我从来没有从高级语言(低级别,高于C级)开始这个低级别的工作。我只是想知道如何处理这个问题。我可以使用一堆或Win32API调用,但这意味着必须处理一堆字符串和数据包以及依赖于系统的解包我希望最终使这个工作跨平台,因为我正在阅读的过程是从一个具有多个平台构建的可执行文件(我知道内存地址在不同系统之间发生变化。想法是拥有一个包含所有内存映射的平面文件,因此Ruby程序可以将当前平台环境与匹配的内存映射相匹配。 )但是从事物的外观来看,我只需要创建一个包装当前平台的系统共享库内存相关函数调用的类。
就我所知,我可能已经存在一个Ruby宝石,它为我提供了所有这些,我只是没有找到。我也可以尝试编辑每个构建的可执行文件,以便每当我想要读取的内存值被进程写入时,它还会将新值的副本写入共享内存中的空间,我不知何故Ruby创建了一个类的实例,该类是指向该共享内存地址的指针,并以某种方式向Ruby程序发出信号,表明该值已更新并应重新加载。基本上一个基于中断的系统会很好,但是由于读取这些值的目的只是发送到从中央服务器广播的记分板,我可以坚持一个基于轮询的系统,它以固定的时间间隔发送更新。我也可以完全抛弃Ruby并使用C或C ++,但我不太了解它们。我实际上比C ++知道更多的x86,我只知道C和系统无关的ANSI C,并且之前从未处理过共享系统库。
那么有没有可用的宝石或鲜为人知的模块?如果没有,那么关于如何实现这一点的任何其他信息都会很好。我想,长话短说,我怎么做这一切?
提前致谢, GRG
PS:还确认那些Win32API调用应该针对kernel32.dll库会很好。
答案 0 :(得分:2)
看看win32utils。我认为至少应该让你站起来,并举例说明如果宝石本身不适合你,如何深入了解api本身。您可能需要咬紧牙关并在C中编写模块。
答案 1 :(得分:2)
使用Ruby-FFI:
如果您了解C和Win32 API,那么您可能会发现使用Ruby-FFI
gem更容易。 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(" ")
一些有用的信息:
char *
更改为int
。