Created
April 12, 2010 14:32
-
-
Save oupo/363616 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!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