Class: Ragweed::Detour::Detour
Overview
“Ghetto Detours”, as Scott Stender might say. Patch subprograms in to running programs as a hooking mechanism.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#dpoint ⇒ Object
readonly
Returns the value of attribute dpoint.
-
#snarfed ⇒ Object
readonly
Returns the value of attribute snarfed.
-
#stack ⇒ Object
readonly
Returns the value of attribute stack.
Instance Method Summary collapse
-
#call ⇒ Object
Patch the target function.
-
#initialize(p, opts = {}) ⇒ Detour
constructor
Easiest way to do this is just to ask WinProcess#detour.
-
#inner_block ⇒ Object
Hook function.
-
#release ⇒ Object
Release the detour and its associated memory, unpatch the target function.
Constructor Details
#initialize(p, opts = {}) ⇒ Detour
Easiest way to do this is just to ask WinProcess#detour. Wants “p” to be a pointer into the process, presumable returned from WinProcess#get_proc.
In theory, “p” should be OK anywhere as long as there are 5 bytes of instructions before the end of the basic block its in. In practice, this only really stands a chance of working if “p” points to a function prologue.
17 18 19 20 21 22 23 24 |
# File 'lib/ragweed/detour.rb', line 17 def initialize(p, opts={}) @p = p.p @dpoint = p @opts = opts @a = @opts[:arena] || @p.arena @stack = @a.alloc(2048) @snarfed = snarf_prologue end |
Instance Attribute Details
#dpoint ⇒ Object (readonly)
Returns the value of attribute dpoint.
6 7 8 |
# File 'lib/ragweed/detour.rb', line 6 def dpoint @dpoint end |
#snarfed ⇒ Object (readonly)
Returns the value of attribute snarfed.
5 6 7 |
# File 'lib/ragweed/detour.rb', line 5 def snarfed @snarfed end |
#stack ⇒ Object (readonly)
Returns the value of attribute stack.
7 8 9 |
# File 'lib/ragweed/detour.rb', line 7 def stack @stack end |
Instance Method Details
#call ⇒ Object
Patch the target function. There is a 70% chance this will totally fuck your process.
You would be wise to have the threads in the process suspended while you do this, but I’m not going to do it for you.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/ragweed/detour.rb', line 38 def call # a Detours-style trampoline --- the location we patch the # target function to jump to --- consists of: # # - A stack switch (to push/pop w/o fucking the program) # - A context save # - The Detour code # - A context restore # - A stack restore # - The code we patched out of the target # - A jump back to the target function (after the prologue) # Do this now to make room for the (probably 5 byte) jump. # We don't know what the address will be until we allocate. jumpback = (Jmp 0xDEADBEEF) # patch back later # Build the trampoline tramp = trampoline(@stack).assemble # Figure out how big the whole mess will be, allocate it tsz = tramp.size + @snarfed.size + jumpback.to_s.size tbuf = @a.alloc(tsz + 10) # assume trampoline is ahead of the patched program text; # jump to [dpoint+patch] jumpback.dst = (@dpoint.to_i + @snarfed.size) - (tbuf + tsz) # Write it into memory. It's not "live" yet because we haven't # patched the target function. @p.write(tbuf, tramp + @snarfed + jumpback.to_s) # But now it is. =) @p.write(@dpoint, injection(tbuf).assemRASble) end |
#inner_block ⇒ Object
Hook function. Override this in subclasses to provide different behavior.
75 76 77 78 |
# File 'lib/ragweed/detour.rb', line 75 def inner_block i = Ragweed::Rasm::Subprogram.new i.<< Int(3) end |
#release ⇒ Object
Release the detour and its associated memory, unpatch the target function.
28 29 30 31 |
# File 'lib/ragweed/detour.rb', line 28 def release @dpoint.write(@snarfed) @a.release if not @opts[:arena] end |