ruby - Ruby 中的读/写进程内存

标签 ruby winapi ffi readprocessmemory

我一直在尝试在 Ruby 中读写进程内存,希望将一些旧的 C++ 程序转移到更动态的语言中。但是,我搬过去并不容易。我读过一些书,但找不到太多关于我的具体问题的信息。我可能在下面犯了一些非常基本的错误,因为我不太确定指针管理在 Ruby-ffi 中是如何工作的。

无论如何,我目前安装了 ffi gem 并一直使用它来获取函数。这是我的:

module Memory
  PROC_READ = 0x10
  PROC_WRITE = 0x20
  PROC_RW = PROC_READ | PROC_WRITE

  extend FFI::Library

  ffi_lib 'kernel32'

  # HANDLE WINAPI OpenProcess(DWORD, BOOL, DWORD)
  attach_function :open, :OpenProcess, [:uint, :bool, :uint], :pointer

  # BOOL WINAPI CloseHandle(HANDLE)
  attach_function :close, :CloseHandle, [:pointer], :bool

  # BOOL WINAPI ReadProcessMemory(HANDLE, LPCVOID, out LPVOID, SIZE_T, out SIZE_T)
  attach_function :read, :ReadProcessMemory, [:pointer, :pointer, :pointer, :int, :int], :bool

  # BOOL WINAPI WriteProcessMemory(HANDLE, LPCVOID, LPVOID, SIZE_T, out SIZE_T)
  attach_function :write, :WriteProcessMemory, [:pointer, :pointer, :pointer, :int, :int], :bool

  # DWORD WINAPI GetLastError(void)
  attach_function :error, :GetLastError, [], :uint
end

似乎当我调用 Memory.open 时我得到了一个正确的句柄。我不太确定,但这是存储结果的变量的输出,以防万一我错了。

#<FFI::Pointer address=0x00000000000150>

这是我目前拥有的完整代码:

# 1048 is a fixed pid currently
handle = Memory::open(Memory::PROC_RW, false, 1048)
puts "GetLastError: #{Memory::error()}"

# Address to read from
loc = 0x057C75F8

out = 0
read = 0

# Supposed to be the address of out to store the value read
val = FFI::MemoryPointer.new :uint, out

# Supposed to be a pointer to loc which holds the address to read from
addr = FFI::MemoryPointer.new :pointer, loc

res = Memory::read(handle, addr, val, 4, read)

puts "GetLastError: #{Memory::error()}"
puts "ReadProcessMemory: #{res}"
puts read
puts out

Memory::close(handle)

这会打印出以下内容:

GetLastError: 0
GetLastError: 0
ReadProcessMemory: false
0
0

我知道我一定是对指针变量做了一些根本性的错误。如果我将 addr 更改为 :uint 类型和值 locFFI::Pointer,则 ReadProcessMemory 返回 true,但 outread 变量不会改变。

我希望这已经足够清楚了。我可以尝试澄清是否缺少某些内容。

最佳答案

在阅读了项目的 Github 示例页面后,我终于能够用指针找出我的问题:

https://github.com/ffi/ffi/wiki/Examples

特别是在“Output Parameters with MemoryPointer”部分下。阅读后,我能够将我的代码更改为以下内容:

require 'ffi'

module Memory
  PROC_READ = 0x10
  PROC_WRITE = 0x20
  PROC_RW = PROC_READ | PROC_WRITE

  extend FFI::Library

  ffi_lib 'kernel32'
  ffi_convention :stdcall

  attach_function :open, :OpenProcess, [:uint, :bool, :uint], :pointer
  attach_function :close, :CloseHandle, [:pointer], :bool
  attach_function :read, :ReadProcessMemory, [:pointer, :pointer, :pointer, :size_t, :pointer], :bool
  attach_function :write, :WriteProcessMemory, [:pointer, :pointer, :pointer, :size_t, :pointer], :bool
  attach_function :error, :GetLastError, [], :uint
end

# 1048 is a fixed pid currently
handle = Memory::open(Memory::PROC_RW, false, 1048)
puts "GetLastError: #{Memory::error()}"

# Output parameters for ReadProcessMemory
out = FFI::MemoryPointer.new :pointer
read = FFI::MemoryPointer.new :pointer

# Pointer holding the location to read from
addr = FFI::Pointer.new :pointer, 0x057C75F8

res = Memory::read(handle, addr, out, 4, read)

# get_pointer(0) grabs the pointer to the value
# address holds the value we actually want (at least in this case)
read = read.get_pointer(0).address
out = out.get_pointer(0).address

puts "GetLastError: #{Memory::error()}"
puts "ReadProcessMemory: #{res}"
puts "Bytes Read: #{read}"
puts "Value Read: #{out}"
Memory::close(handle)

在我的特定情况下,上面的代码正确输出了以下内容:

GetLastError: 0
GetLastError: 0
ReadProcessMemory: true
Bytes Read: 4
Value Read: 10

我希望这对将来的人有所帮助。

关于ruby - Ruby 中的读/写进程内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20196570/

相关文章:

c++ - 为什么我的简单 C++ GUI 应用程序显示中文消息框?

python - OS X 上的 Python ctypes '_as_parameter_' 和 'from_param' 的问题

用于 C 递归结构和联合的 Haskell FFI

ruby-on-rails - 跳过载波完整性和处理验证

ruby - 如何使用 gsub 替换 ruby​​ 中的多字节字符?

c# - 如何通过代码设置另存为对话框的目录?

c++ - 使用 dart 实现 winapi(SendInput) :ffi

ruby - 在 rails_admin 中,如何关闭相关子表单中的 "add new"和 "edit"按钮?

Ruby 2.3.1 Date.parse 在分隔符为空格字符时返回另一个日期

c++ GDI打印导致系统卡住