samples/dbg-apihook.rb in metasm-1.0.1 vs samples/dbg-apihook.rb in metasm-1.0.2

- old
+ new

@@ -15,10 +15,12 @@ # require 'metasm' class ApiHook + attr_accessor :dbg + # rewrite this function to list the hooks you want # return an array of hashes def setup #[{ :function => 'WriteFile', :abi => :stdcall }, # standard function hook # { :module => 'Foo.dll', :rva => 0x2433, # arbitrary code hook @@ -31,34 +33,47 @@ if not dbg.kind_of? Metasm::Debugger process = Metasm::OS.current.find_process(dbg) raise 'no such process' if not process dbg = process.debugger end - dbg.loadallsyms @dbg = dbg - setup.each { |h| setup_hook(h) } - init_prerun if respond_to?(:init_prerun) # allow subclass to do stuff before main loop - @dbg.run_forever + begin + setup.each { |h| setup_hook(h) } + init_prerun if respond_to?(:init_prerun) # allow subclass to do stuff before main loop + @dbg.run_forever + rescue Interrupt + @dbg.detach #rescue nil + end end # setup one function hook def setup_hook(h) + @las ||= false + if not h[:lib] and not @las + @dbg.loadallsyms + @las = false + elsif h[:lib] + # avoid loadallsyms if specified (regexp against pathname, not exported lib name) + @dbg.loadsyms(h[:lib]) + end + pre = "pre_#{h[:hookname] || h[:function]}" post = "post_#{h[:hookname] || h[:function]}" - @nargs = h[:nargs] || method(pre).arity if respond_to?(pre) + nargs = h[:nargs] || method(pre).arity if respond_to?(pre) if target = h[:address] elsif target = h[:rva] modbase = @dbg.modulemap[h[:module]] raise "cant find module #{h[:module]} in #{@dbg.modulemap.join(', ')}" if not modbase target += modbase[0] else target = h[:function] end - @dbg.bpx(target) { + @dbg.bpx(target, false, h[:condition]) { + @nargs = nargs catch(:finish) { @cur_abi = h[:abi] @ret_longlong = h[:ret_longlong] if respond_to? pre args = read_arglist @@ -204,22 +219,22 @@ def post_WriteFile(retval, arglistcopy) # we can patch the API return value with this #patch_retval(42) # finish messing with the args: fake the nrofbyteswritten - handle, pbuf, size, pwritten, overlap = arglistcopy + #handle, pbuf, size, pwritten, overlap = arglistcopy + size, pwritten = arglistcopy.values_at(2, 3) written = @dbg.memory_read_int(pwritten) if written == size # if written everything, patch the value so that the program dont detect our intervention @dbg.memory_write_int(pwritten, written+2) end puts "write retval: #{retval}, written: #{written} bytes" end end -# name says it all -Metasm::WinOS.get_debug_privilege +Metasm::OS.current.get_debug_privilege if Metasm::OS.current.respond_to? :get_debug_privilege # run our Hook engine on a running 'notepad' instance MyHook.new('notepad') # the script ends when notepad exits