Skip to content

Instantly share code, notes, and snippets.

@oupo
Created April 12, 2010 14:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oupo/363616 to your computer and use it in GitHub Desktop.
Save oupo/363616 to your computer and use it in GitHub Desktop.
#!ruby
require "Win32API"
module MarktimeSupport
EXENAME = "DeSmuME.exe"
BASE_ADDR = 0x00c70b20
REGISTER_ADDR = 0x007afd20
INFLOOP_CODE = 0xe7fe
module_function
def main
main0(0x0223B2D8) do |p|
seed = read_memory_long(p, read_register(p, 0) + 0x2448)
next_seed = seed * 0x41C64E6D + 0x6073 & 0xffffffff
lr = read_register(p, 14)
puts "%#.8x -> %#.8x, %#.8x" % [seed, next_seed, lr]
end
end
def main0(breakpoint)
id = search_process_id(EXENAME)
open_process(id) do |p|
orig_code1 = read_memory_short(p, breakpoint)
orig_code2 = read_memory_short(p, breakpoint + 2)
while true
write_memory_short p, breakpoint, INFLOOP_CODE
wait_for_break p, breakpoint
yield p
write_memory_short p, breakpoint + 2, INFLOOP_CODE
write_memory_short p, breakpoint, orig_code1
wait_for_break p, breakpoint + 2
write_memory_short p, breakpoint, INFLOOP_CODE
write_memory_short p, breakpoint + 2, orig_code2
end
end
end
def wait_for_break(p, breakpoint)
while read_register(p, 15) != breakpoint + 4
sleep 0.1
end
end
def read_memory_byte(p, addr)
read_memory(p, addr, "C", 1)
end
def read_memory_short(p, addr)
read_memory(p, addr, "S", 2)
end
def read_memory_long(p, addr)
read_memory(p, addr, "L", 4)
end
def write_memory_byte(p, addr, val)
write_memory(p, addr, val, "C")
end
def write_memory_short(p, addr, val)
write_memory(p, addr, val, "S")
end
def write_memory_long(p, addr, val)
write_memory(p, addr, val, "L")
end
def read_memory(p, addr, format, len)
buf = process_read(p, BASE_ADDR + (addr - 0x02000000), len)
buf.unpack(format)[0]
end
def write_memory(p, addr, val, format)
buf = [val].pack(format)
process_write(p, BASE_ADDR + (addr - 0x02000000), buf)
end
def read_register(p, n)
buf = process_read(p, REGISTER_ADDR + n * 4, 4)
buf.unpack("L")[0]
end
@read = Win32API.new("kernel32", "ReadProcessMemory", %w(p p p i p), "i")
@write = Win32API.new("kernel32", "WriteProcessMemory", %w(p p p i p), "i")
@open = Win32API.new("kernel32", "OpenProcess", %w(i i i), "i")
@close = Win32API.new("kernel32", "CloseHandle", %w(p), "i")
@create_snapshot = Win32API.new("kernel32", "CreateToolhelp32Snapshot", %w(i i), "i")
@first = Win32API.new("kernel32", "Process32First", %w(i p), "i")
@next = Win32API.new("kernel32", "Process32Next", %w(i p), "i")
def process_read(hprocess, addr, size)
buf = "\0" * size
ret = @read.call(hprocess, addr, buf, size, 0)
raise "process memory read error: %#.8x" % [addr] if ret == 0
buf
end
def process_write(hprocess, addr, buf)
ret = @write.call(hprocess, addr, buf, buf.size, 0)
raise "process memory write error: %#.8x" % [addr] if ret == 0
end
def open_process(process_id)
p = open_process0(process_id)
return p unless block_given?
begin
yield p
ensure
close_handle(p) if p
end
end
PROCESS_ALL_ACCESS = 0x001F0FFF
def open_process0(process_id)
handle = @open.call(PROCESS_ALL_ACCESS, 0, process_id)
raise "failed to open process" if handle == 0
handle
end
def close_handle(handle)
@close.call(handle)
end
TH32CS_SNAPPROCESS = 2
def list_process
snapshot = @create_snapshot.call(TH32CS_SNAPPROCESS, 0)
pe32 = gen_struct(296)
result = []
if @first.call(snapshot, pe32) != 0
begin
_,_,process_id,_,_,_,_,_,_,path = pe32.unpack("L!7l!L!Z260")
result << [process_id, path]
end while @next.call(snapshot, pe32) != 0
end
close_handle snapshot
result
end
def search_process_id(exename)
list_process().each do |(id, name)|
if name == exename
return id
end
end
raise "process not found: %p" % [exename]
end
def gen_struct(size)
s = [size].pack("L!")
s << "\0" * (size - s.size)
s
end
end
if $0 == __FILE__
MarktimeSupport.main
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment