tduehr-ragweed 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. data/History.txt +15 -0
  2. data/README.rdoc +35 -0
  3. data/README.txt +9 -0
  4. data/Rakefile +30 -0
  5. data/examples/hittracertux.rb +48 -0
  6. data/examples/hittracerx.rb +63 -0
  7. data/examples/hook_notepad.rb +9 -0
  8. data/examples/snicker.rb +183 -0
  9. data/examples/tux-example.rb +23 -0
  10. data/lib/ragweed/arena.rb +55 -0
  11. data/lib/ragweed/blocks.rb +128 -0
  12. data/lib/ragweed/debugger32.rb +338 -0
  13. data/lib/ragweed/debuggerosx.rb +419 -0
  14. data/lib/ragweed/debuggertux.rb +347 -0
  15. data/lib/ragweed/detour.rb +223 -0
  16. data/lib/ragweed/ptr.rb +48 -0
  17. data/lib/ragweed/rasm/isa.rb +1046 -0
  18. data/lib/ragweed/rasm/util.rb +26 -0
  19. data/lib/ragweed/rasm.rb +53 -0
  20. data/lib/ragweed/sbuf.rb +197 -0
  21. data/lib/ragweed/trampoline.rb +103 -0
  22. data/lib/ragweed/utils.rb +87 -0
  23. data/lib/ragweed/wrap32/debugging.rb +163 -0
  24. data/lib/ragweed/wrap32/device.rb +49 -0
  25. data/lib/ragweed/wrap32/event.rb +50 -0
  26. data/lib/ragweed/wrap32/hooks.rb +23 -0
  27. data/lib/ragweed/wrap32/overlapped.rb +46 -0
  28. data/lib/ragweed/wrap32/process.rb +506 -0
  29. data/lib/ragweed/wrap32/process_token.rb +59 -0
  30. data/lib/ragweed/wrap32/thread_context.rb +208 -0
  31. data/lib/ragweed/wrap32/winx.rb +16 -0
  32. data/lib/ragweed/wrap32/wrap32.rb +526 -0
  33. data/lib/ragweed/wrap32.rb +53 -0
  34. data/lib/ragweed/wraposx/constants.rb +101 -0
  35. data/lib/ragweed/wraposx/kernelerrorx.rb +147 -0
  36. data/lib/ragweed/wraposx/region_info.rb +244 -0
  37. data/lib/ragweed/wraposx/thread_context.rb +203 -0
  38. data/lib/ragweed/wraposx/thread_info.rb +213 -0
  39. data/lib/ragweed/wraposx/wraposx.rb +376 -0
  40. data/lib/ragweed/wraposx.rb +53 -0
  41. data/lib/ragweed/wraptux/constants.rb +68 -0
  42. data/lib/ragweed/wraptux/threads.rb +3 -0
  43. data/lib/ragweed/wraptux/wraptux.rb +76 -0
  44. data/lib/ragweed/wraptux.rb +53 -0
  45. data/lib/ragweed.rb +84 -0
  46. data/spec/ragweed_spec.rb +7 -0
  47. data/spec/spec_helper.rb +16 -0
  48. data/tasks/ann.rake +80 -0
  49. data/tasks/bones.rake +20 -0
  50. data/tasks/gem.rake +201 -0
  51. data/tasks/git.rake +40 -0
  52. data/tasks/notes.rake +27 -0
  53. data/tasks/post_load.rake +34 -0
  54. data/tasks/rdoc.rake +51 -0
  55. data/tasks/rubyforge.rake +55 -0
  56. data/tasks/setup.rb +292 -0
  57. data/tasks/spec.rake +54 -0
  58. data/tasks/svn.rake +47 -0
  59. data/tasks/test.rake +40 -0
  60. data/tasks/zentest.rake +36 -0
  61. data/test/test_ragweed.rb +0 -0
  62. metadata +127 -0
@@ -0,0 +1,208 @@
1
+ module Ragweed::Wrap32
2
+ module EFlags
3
+ CARRY = (1<< 0)
4
+ X0 = (1<< 1)
5
+ PARITY = (1<< 2)
6
+ X1 = (1<< 3)
7
+ ADJUST = (1<< 4)
8
+ X2 = (1<< 5)
9
+ ZERO = (1<< 6)
10
+ SIGN = (1<< 7)
11
+ TRAP = (1<< 8)
12
+ INTERRUPT = (1<< 9)
13
+ DIRECTION = (1<< 10)
14
+ OVERFLOW = (1<< 11)
15
+ IOPL1 = (1<< 12)
16
+ IOPL2 = (1<< 13)
17
+ NESTEDTASK = (1<< 14)
18
+ X3 = (1<< 15)
19
+ RESUME = (1<< 16)
20
+ V86MODE = (1<< 17)
21
+ ALIGNCHECK = (1<< 18)
22
+ VINT = (1<< 19)
23
+ VINTPENDING = (1<< 20)
24
+ CPUID = (1<< 21)
25
+ end
26
+
27
+ module ContextFlags
28
+ I386 = 0x10000
29
+ CONTROL = 1
30
+ INTEGER = 2
31
+ SEGMENTS = 4
32
+ FLOATING_POINT = 8
33
+ DEBUG_REGISTERS = 0x10
34
+
35
+ FULL = (I386|CONTROL|INTEGER|SEGMENTS)
36
+ DEBUG = (FULL|DEBUG_REGISTERS)
37
+ end
38
+ end
39
+
40
+ class Ragweed::Wrap32::ThreadContext
41
+ (FIELDS = [ [:context_flags, "L"],
42
+ [:dr0, "L"],
43
+ [:dr1, "L"],
44
+ [:dr2, "L"],
45
+ [:dr3, "L"],
46
+ [:dr6, "L"],
47
+ [:dr7, "L"],
48
+ [:floating_save, "a112"],
49
+ [:seg_gs, "L"],
50
+ [:seg_gs, "L"],
51
+ [:seg_es, "L"],
52
+ [:seg_ds, "L"],
53
+ [:edi, "L"],
54
+ [:esi, "L"],
55
+ [:ebx, "L"],
56
+ [:edx, "L"],
57
+ [:ecx, "L"],
58
+ [:eax, "L"],
59
+ [:ebp, "L"],
60
+ [:eip, "L"],
61
+ [:seg_cs, "L"],
62
+ [:eflags, "L"],
63
+ [:esp, "L"],
64
+ [:seg_ss, "L"],
65
+ [:spill, "a1024"]]).each {|x| attr_accessor x[0]}
66
+
67
+ def initialize(str=nil)
68
+ refresh(str) if str
69
+ end
70
+
71
+ def refresh(str)
72
+ if str
73
+ str.unpack(FIELDS.map {|x| x[1]}.join("")).each_with_index do |val, i|
74
+ instance_variable_set "@#{ FIELDS[i][0] }".intern, val
75
+ end
76
+ end
77
+ end
78
+
79
+ def to_s
80
+ FIELDS.map {|f| send(f[0])}.pack(FIELDS.map {|x| x[1]}.join(""))
81
+ end
82
+
83
+ def self.get(h)
84
+ self.new(Wrap32::get_thread_context_raw(h))
85
+ end
86
+
87
+ def get(h)
88
+ refresh(Wrap32::get_thread_context_raw(h))
89
+ end
90
+
91
+ def set(h)
92
+ Wrap32::set_thread_context_raw(h, self.to_s)
93
+ end
94
+
95
+ def inspect
96
+ body = lambda do
97
+ FIELDS.map do |f|
98
+ val = send(f[0])
99
+ "#{f[0]}=#{val.to_s(16) rescue val.to_s}"
100
+ end.join(", ")
101
+ end
102
+ "#<ThreadContext #{body.call}>"
103
+ end
104
+
105
+ def dump(&block)
106
+ maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
107
+ maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
108
+
109
+ string =<<EOM
110
+ -----------------------------------------------------------------------
111
+ CONTEXT:
112
+ EIP: #{self.eip.to_s(16).rjust(8, "0")} #{maybe_dis.call(self.eip)}
113
+
114
+ EAX: #{self.eax.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.eax)}
115
+ EBX: #{self.ebx.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.ebx)}
116
+ ECX: #{self.ecx.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.ecx)}
117
+ EDX: #{self.edx.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.edx)}
118
+ EDI: #{self.edi.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.edi)}
119
+ ESI: #{self.esi.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.esi)}
120
+ EBP: #{self.ebp.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.ebp)}
121
+ ESP: #{self.esp.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.esp)}
122
+ EFL: #{self.eflags.to_s(2).rjust(32, "0")} #{Wrap32::EFlags.flag_dump(self.eflags)}
123
+ EOM
124
+ end
125
+
126
+ def single_step(v=true)
127
+ if v
128
+ @eflags |= Wrap32::EFlags::TRAP
129
+ else
130
+ @eflags &= ~(Wrap32::EFlags::TRAP)
131
+ end
132
+ end
133
+ end
134
+
135
+ module Ragweed::Wrap32
136
+ class << self
137
+ def get_thread_context_raw(h)
138
+ ctx = [Wrap32::ContextFlags::DEBUG,0,0,0,0,0,0,"\x00"*112,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"\x00"*1024].pack("LLLLLLLa112LLLLLLLLLLLLLLLLa1024")
139
+ ret = CALLS["kernel32!GetThreadContext:LP=L"].call(h, ctx)
140
+ if ret != 0
141
+ return ctx
142
+ else
143
+ raise WinX.new(:get_thread_context)
144
+ end
145
+ end
146
+
147
+ def set_thread_context_raw(h, c)
148
+ buf = c.to_s
149
+ ret = CALLS["kernel32!SetThreadContext:LP=L"].call(h, buf)
150
+ raise WinX.new(:set_thread_context) if ret == 0
151
+ return ret
152
+ end
153
+
154
+ def str2context(str)
155
+ ret = OpenStruct.new
156
+ ret.ContextFlags,
157
+ ret.Dr0,
158
+ ret.Dr1,
159
+ ret.Dr2,
160
+ ret.Dr3,
161
+ ret.Dr6,
162
+ ret.Dr7,
163
+ ret.FloatControlWord,
164
+ ret.FloatStatusWord,
165
+ ret.FloatTagWord,
166
+ ret.FloatErrorOffset,
167
+ ret.FloatErrorSelector,
168
+ ret.FloatDataOffset,
169
+ ret.FloatDataSelector,
170
+ ret.FloatRegisterArea,
171
+ ret.FloatCr0NpxState,
172
+ ret.SegGs,
173
+ ret.SegFs,
174
+ ret.SegEs,
175
+ ret.SegDs,
176
+ ret.Edi,
177
+ ret.Esi,
178
+ ret.Ebx,
179
+ ret.Edx,
180
+ ret.Ecx,
181
+ ret.Eax,
182
+ ret.Ebp,
183
+ ret.Eip,
184
+ ret.SegCs,
185
+ ret.EFlags,
186
+ ret.Esp,
187
+ ret.SegSs,
188
+ ret.Spill = str.unpack("LLLLLLLLLLLLLLA80LLLLLLLLLLLLLLLLLA1024")
189
+ return ret
190
+ end
191
+
192
+ # Retrieve the running context of a thread given its handle, returning a
193
+ # struct that mostly contains register values. Note that this will suspend
194
+ # and then resume the thread. Useful (among many other things) to sample
195
+ # EIP values to see what the code is doing.
196
+ def get_thread_context(h)
197
+ ctx = [Wrap32::ContextFlags::DEBUG,0,0,0,0,0,0,"\x00"*112,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"\x00"*1024].pack("LLLLLLLa112LLLLLLLLLLLLLLLLa1024")
198
+ suspend_thread(h)
199
+ ret = CALLS["kernel32!GetThreadContext:LP=L"].call(h, ctx)
200
+ resume_thread(h)
201
+ if ret != 0
202
+ return str2context(ctx)
203
+ else
204
+ raise WinX.new(:get_thread_context)
205
+ end
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,16 @@
1
+ %w[ostruct Win32API pp].each {|x| require x}
2
+
3
+ module Ragweed;end
4
+ module Ragweed::Wrap32
5
+ class WinX < StandardError
6
+ attr_reader :code
7
+ attr_reader :msg
8
+ attr_reader :call
9
+ def initialize(sym=nil)
10
+ @call = sym
11
+ @code = Ragweed::Wrap32::get_last_error()
12
+ @msg = "#{(@call ? @call.to_s + ": " : "")}(#{@code}) #{ Ragweed::Wrap32::format_message(@code) }"
13
+ super @msg
14
+ end
15
+ end
16
+ end