returns a virtual string proxying the specified process memory range reads are cached (4096 aligned bytes read at once), from /proc/pid/mem writes are done directly by ptrace
# File metasm/os/linux.rb, line 726 def initialize(pid, addr_start=0, length=nil, dbg=nil) @pid = pid length ||= 1 << (dbg ? dbg.cpu.size : (LinOS.open_process(@pid).addrsz rescue 32)) @readfd = File.open("/proc/#@pid/mem", 'rb') rescue nil @dbg = dbg if dbg super(addr_start, length) end
# File metasm/os/linux.rb, line 738 def do_ptrace(needproc) if dbg dbg.switch_context(@pid) { st = dbg.state next if st != :stopped if needproc # we will try to access /proc/pid/mem # if the main thread is still running, fallback to ptrace.readmem instead pst = (dbg.tid == @pid ? st : dbg.tid_stuff[@pid][:state]) if pst != :stopped savedreadfd = @readfd @readfd = nil begin yield dbg.ptrace ensure @readfd = savedreadfd end else yield dbg.ptrace end else yield dbg.ptrace end } else PTrace.open(@pid) { |ptrace| yield ptrace } end end
# File metasm/os/linux.rb, line 734 def dup(addr = @addr_start, len = @length) self.class.new(@pid, addr, len, dbg) end
# File metasm/os/linux.rb, line 773 def get_page(addr, len=@pagelength) do_ptrace(true) { |ptrace| begin if readfd and addr < (1<<63) # 1<<63: ruby seek = 'too big to fit longlong', linux read = EINVAL @readfd.pos = addr @readfd.read len elsif addr < (1<<(ptrace.host_intsize*8)) # can reach 1<<64 with peek_data only if ptrace accepts 64bit args ptrace.readmem(addr, len) end rescue Errno::EIO, Errno::ESRCH nil end } end
# File metasm/os/linux.rb, line 767 def rewrite_at(addr, data) # target must be stopped wr = do_ptrace(false) { |ptrace| ptrace.writemem(addr, data) } raise "couldn't ptrace_write at #{'%x' % addr}" if not wr end