2010-05-15 76 views
3

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

这将需要一些工作,把所有在一起,但我认定它不会太糟糕的代码了。这对我来说只是一个新的编程领域,因为我从来没有从高级语言开发过这个低级别(好吧,比C级更高)。我只是想知道如何解决这个问题。我可以使用一堆或Win32API调用,但这意味着不得不处理一堆字符串和数组打包,这是系统依赖的,我想最终使这个工作跨平台,因为我正在阅读的过程是从一个具有多个平台构建的可执行文件(我知道内存地址从系统到系统的变化,想法是有一个包含所有内存映射的平面文件,这样Ruby程序就可以将当前平台环境匹配到匹配的内存映射。 ),但是从外观上看,我只需要创建一个包装当前平台系统共享库内存相关函数调用的类。

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

那么,有没有一种宝石或鲜为人知的模块可用的已经做到了这一点?如果没有,那么如何做到这一点的任何额外信息将是很好的。我想,长话短说,我该怎么办?

由于提前, GRG

PS:也确认,这些Win32API的呼叫应针对KERNEL32.DLL库将是很好。

+1

对不起人TL;博士 – horseyguy 2010-05-15 19:09:22

回答

2

看看win32utils。我在想,至少应该让你站起来,并给你如何钻进API的例子,如果宝石本身不适合你。您可能需要咬紧牙关,然后用C写一个模块。

+0

是啊,我看着早。通过他们组织win32utils模块的方式,我将要寻找的是win32-process子模块,它包含的函数与我在win32-api中需要的过程函数相同,但开发人员(s)win32utils尚未实现ReadProcessMemory和/或WriteProcessMemory函数。 – 2010-05-15 02:52:31

+0

对于双重评论感到抱歉,但我想知道为什么我要制作一个C模块而不是制作与不同函数调用相关联的多个Win32API类实例并将它们包装到一个Ruby类中,我可以称其为ExternalProcessMemory? – 2010-05-15 04:13:56

2

使用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); 

通过传递一个无效的文件句柄0xFFFFFFFFCreateFileMapping,从而避免与文件打交道的一切,只需使用数组和指针定义共享内存即可。

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

简化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(" ") 

一些有用的信息:

相关问题