2010-05-15 33 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(" ") 

一些有用的信息: