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.
- data/History.txt +15 -0
- data/README.rdoc +35 -0
- data/README.txt +9 -0
- data/Rakefile +30 -0
- data/examples/hittracertux.rb +48 -0
- data/examples/hittracerx.rb +63 -0
- data/examples/hook_notepad.rb +9 -0
- data/examples/snicker.rb +183 -0
- data/examples/tux-example.rb +23 -0
- data/lib/ragweed/arena.rb +55 -0
- data/lib/ragweed/blocks.rb +128 -0
- data/lib/ragweed/debugger32.rb +338 -0
- data/lib/ragweed/debuggerosx.rb +419 -0
- data/lib/ragweed/debuggertux.rb +347 -0
- data/lib/ragweed/detour.rb +223 -0
- data/lib/ragweed/ptr.rb +48 -0
- data/lib/ragweed/rasm/isa.rb +1046 -0
- data/lib/ragweed/rasm/util.rb +26 -0
- data/lib/ragweed/rasm.rb +53 -0
- data/lib/ragweed/sbuf.rb +197 -0
- data/lib/ragweed/trampoline.rb +103 -0
- data/lib/ragweed/utils.rb +87 -0
- data/lib/ragweed/wrap32/debugging.rb +163 -0
- data/lib/ragweed/wrap32/device.rb +49 -0
- data/lib/ragweed/wrap32/event.rb +50 -0
- data/lib/ragweed/wrap32/hooks.rb +23 -0
- data/lib/ragweed/wrap32/overlapped.rb +46 -0
- data/lib/ragweed/wrap32/process.rb +506 -0
- data/lib/ragweed/wrap32/process_token.rb +59 -0
- data/lib/ragweed/wrap32/thread_context.rb +208 -0
- data/lib/ragweed/wrap32/winx.rb +16 -0
- data/lib/ragweed/wrap32/wrap32.rb +526 -0
- data/lib/ragweed/wrap32.rb +53 -0
- data/lib/ragweed/wraposx/constants.rb +101 -0
- data/lib/ragweed/wraposx/kernelerrorx.rb +147 -0
- data/lib/ragweed/wraposx/region_info.rb +244 -0
- data/lib/ragweed/wraposx/thread_context.rb +203 -0
- data/lib/ragweed/wraposx/thread_info.rb +213 -0
- data/lib/ragweed/wraposx/wraposx.rb +376 -0
- data/lib/ragweed/wraposx.rb +53 -0
- data/lib/ragweed/wraptux/constants.rb +68 -0
- data/lib/ragweed/wraptux/threads.rb +3 -0
- data/lib/ragweed/wraptux/wraptux.rb +76 -0
- data/lib/ragweed/wraptux.rb +53 -0
- data/lib/ragweed.rb +84 -0
- data/spec/ragweed_spec.rb +7 -0
- data/spec/spec_helper.rb +16 -0
- data/tasks/ann.rake +80 -0
- data/tasks/bones.rake +20 -0
- data/tasks/gem.rake +201 -0
- data/tasks/git.rake +40 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +34 -0
- data/tasks/rdoc.rake +51 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +292 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- data/tasks/zentest.rake +36 -0
- data/test/test_ragweed.rb +0 -0
- 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
|