I have been experimenting with reading and writing process memory in Ruby in hopes to move some old C++ programs to a more dynamic language. However I've not been having an easy time moving over. I've done some reading but I can't find much on my specific problem. I probably have some pretty fundamental mistakes below as I'm not too sure how pointer management works in Ruby-ffi.
Anyway, I currently have the ffi
gem installed and have been using that to grab functions. This is what I have:
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
It seems that when I call Memory.open I get a correct handle. I'm not quite sure, but here's the output of a variable storing the result in-case I'm wrong.
#<FFI::Pointer address=0x00000000000150>
Here's the full code I have currently:
# 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)
This prints out the following:
GetLastError: 0
GetLastError: 0
ReadProcessMemory: false
0
0
I know I must be doing something fundamentally wrong with the pointer variables. If I change addr
to an FFI::Pointer
of type :uint
and value loc
then ReadProcessMemory returns true
, but the out
and read
variables do not change.
I hope this has been clear enough. I can try to clarify if something seems like it's missing.