ragweed 0.1.7.3 → 0.2.0.pre1
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/README.rdoc +33 -8
- data/Rakefile +80 -23
- data/VERSION +1 -0
- data/examples/hittracertux.rb +2 -6
- data/examples/hook_notepad.rb +1 -1
- data/examples/tux-example.rb +3 -2
- data/lib/.DS_Store +0 -0
- data/lib/ragweed/debugger32.rb +188 -145
- data/lib/ragweed/debuggerosx.rb +13 -13
- data/lib/ragweed/debuggertux.rb +267 -140
- data/lib/ragweed/rasm.rb +1 -1
- data/lib/ragweed/wrap32/debugging.rb +184 -64
- data/lib/ragweed/wrap32/hooks.rb +27 -11
- data/lib/ragweed/wrap32/process.rb +114 -7
- data/lib/ragweed/wrap32/process_token.rb +23 -7
- data/lib/ragweed/wrap32/thread_context.rb +100 -166
- data/lib/ragweed/wrap32/wrap32.rb +127 -72
- data/lib/ragweed/wrap32.rb +1 -1
- data/lib/ragweed/wraposx/constants.rb +1 -9
- data/lib/ragweed/wraposx/region_info.rb +209 -188
- data/lib/ragweed/wraposx/structs.rb +102 -0
- data/lib/ragweed/wraposx/thread_context.rb +636 -159
- data/lib/ragweed/wraposx/thread_info.rb +40 -107
- data/lib/ragweed/wraposx/thread_info.rb.old +121 -0
- data/lib/ragweed/wraposx/wraposx.rb +154 -231
- data/lib/ragweed/wraposx.rb +2 -1
- data/lib/ragweed/wraptux/constants.rb +46 -22
- data/lib/ragweed/wraptux/struct_helpers.rb +25 -0
- data/lib/ragweed/wraptux/threads.rb +0 -0
- data/lib/ragweed/wraptux/wraptux.rb +58 -62
- data/lib/ragweed/wraptux.rb +3 -4
- data/lib/ragweed.rb +36 -8
- data/ragweed.gemspec +85 -15
- metadata +50 -18
@@ -1,27 +1,29 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
1
3
|
module Ragweed::Wrap32
|
2
4
|
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)
|
5
|
+
CARRY = (1 << 0)
|
6
|
+
X0 = (1 << 1)
|
7
|
+
PARITY = (1 << 2)
|
8
|
+
X1 = (1 << 3)
|
9
|
+
ADJUST = (1 << 4)
|
10
|
+
X2 = (1 << 5)
|
11
|
+
ZERO = (1 << 6)
|
12
|
+
SIGN = (1 << 7)
|
13
|
+
TRAP = (1 << 8)
|
14
|
+
INTERRUPT = (1 << 9)
|
15
|
+
DIRECTION = (1 << 10)
|
16
|
+
OVERFLOW = (1 << 11)
|
17
|
+
IOPL1 = (1 << 12)
|
18
|
+
IOPL2 = (1 << 13)
|
19
|
+
NESTEDTASK = (1 << 14)
|
20
|
+
X3 = (1 << 15)
|
21
|
+
RESUME = (1 << 16)
|
22
|
+
V86MODE = (1 << 17)
|
23
|
+
ALIGNCHECK = (1 << 18)
|
24
|
+
VINT = (1 << 19)
|
25
|
+
VINTPENDING = (1 << 20)
|
26
|
+
CPUID = (1 << 21)
|
25
27
|
end
|
26
28
|
|
27
29
|
module ContextFlags
|
@@ -37,106 +39,93 @@ module Ragweed::Wrap32
|
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
40
|
-
class Ragweed::Wrap32::ThreadContext
|
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
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
42
|
+
class Ragweed::Wrap32::ThreadContext < FFI::Struct
|
43
|
+
include Ragweed::FFIStructInclude
|
44
|
+
|
45
|
+
## This is defined in WinNt.h
|
46
|
+
layout :context_flags, :long,
|
47
|
+
:dr0, :long,
|
48
|
+
:dr1, :long,
|
49
|
+
:dr2, :long,
|
50
|
+
:dr3, :long,
|
51
|
+
:dr6, :long,
|
52
|
+
:dr7, :long,
|
53
|
+
:floating_save, [:uint8, 112], ## XXX need a structure for this
|
54
|
+
:seg_gs, :long,
|
55
|
+
:seg_fs, :long,
|
56
|
+
:seg_es, :long,
|
57
|
+
:seg_ds, :long,
|
58
|
+
:edi, :long,
|
59
|
+
:esi, :long,
|
60
|
+
:ebx, :long,
|
61
|
+
:edx, :long,
|
62
|
+
:ecx, :long,
|
63
|
+
:eax, :long,
|
64
|
+
:ebp, :long,
|
65
|
+
:eip, :long,
|
66
|
+
:seg_cs, :long,
|
67
|
+
:eflags, :long,
|
68
|
+
:esp, :long,
|
69
|
+
:seg_ss, :long,
|
70
|
+
:spill, [:uint8, 512 ] ## MAXIMUM_SUPPORTED_EXTENSION
|
71
|
+
|
72
|
+
## XXX more helper methods here are needed
|
73
|
+
|
74
|
+
def inspect
|
75
|
+
body = lambda do
|
76
|
+
self.members.each_with_index do |m,i|
|
77
|
+
"#{self.members[i].to_s(16)} #{self.values[i].to_s.hexify}"
|
78
|
+
end.join(", ")
|
79
|
+
end
|
76
80
|
end
|
77
|
-
end
|
78
81
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
def self.get(h)
|
84
|
-
self.new(Ragweed::Wrap32::get_thread_context_raw(h))
|
85
|
-
end
|
82
|
+
def dump(&block)
|
83
|
+
maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
|
84
|
+
#maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
|
86
85
|
|
87
|
-
|
88
|
-
refresh(Ragweed::Wrap32::get_thread_context_raw(h))
|
89
|
-
end
|
90
|
-
|
91
|
-
def set(h)
|
92
|
-
Ragweed::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.hexify}"
|
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
|
86
|
+
string =<<EOM
|
110
87
|
-----------------------------------------------------------------------
|
111
88
|
CONTEXT:
|
112
|
-
EIP: #{self.eip.to_s(16).rjust(8, "0")}
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
ESP: #{self.esp.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.esp)}
|
89
|
+
EIP: #{self.eip.to_s(16).rjust(8, "0")}
|
90
|
+
EAX: #{self.eax.to_s(16).rjust(8, "0")}
|
91
|
+
EBX: #{self.ebx.to_s(16).rjust(8, "0")}
|
92
|
+
ECX: #{self.ecx.to_s(16).rjust(8, "0")}
|
93
|
+
EDX: #{self.edx.to_s(16).rjust(8, "0")}
|
94
|
+
EDI: #{self.edi.to_s(16).rjust(8, "0")}
|
95
|
+
ESI: #{self.esi.to_s(16).rjust(8, "0")}
|
96
|
+
EBP: #{self.ebp.to_s(16).rjust(8, "0")}
|
97
|
+
ESP: #{self.esp.to_s(16).rjust(8, "0")}
|
122
98
|
EFL: #{self.eflags.to_s(2).rjust(32, "0")} #{Ragweed::Wrap32::EFlags.flag_dump(self.eflags)}
|
123
99
|
EOM
|
124
|
-
|
100
|
+
end
|
125
101
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
102
|
+
def single_step(v=true)
|
103
|
+
if v
|
104
|
+
self.eflags |= Ragweed::Wrap32::EFlags::TRAP
|
105
|
+
else
|
106
|
+
self.eflags &= ~(Ragweed::Wrap32::EFlags::TRAP)
|
107
|
+
end
|
131
108
|
end
|
132
|
-
end
|
133
109
|
end
|
134
110
|
|
135
111
|
module Ragweed::Wrap32
|
112
|
+
module Win
|
113
|
+
extend FFI::Library
|
114
|
+
|
115
|
+
ffi_lib 'kernel32'
|
116
|
+
ffi_convention :stdcall
|
117
|
+
attach_function 'SetThreadContext', [ :long, :pointer ], :long
|
118
|
+
attach_function 'GetThreadContext', [ :long, :pointer ], :long
|
119
|
+
end
|
120
|
+
|
136
121
|
class << self
|
137
|
-
def
|
138
|
-
|
139
|
-
|
122
|
+
def get_thread_context(h)
|
123
|
+
c = FFI::MemoryPointer.new(Ragweed::Wrap32::ThreadContext, 1)
|
124
|
+
ctx = Ragweed::Wrap32::ThreadContext.new c
|
125
|
+
ctx.context_flags = Ragweed::Wrap32::ContextFlags::DEBUG
|
126
|
+
#suspend_thread(h)
|
127
|
+
ret = Win.GetThreadContext(h, ctx)
|
128
|
+
#resume_thread(h)
|
140
129
|
if ret != 0
|
141
130
|
return ctx
|
142
131
|
else
|
@@ -144,65 +133,10 @@ module Ragweed::Wrap32
|
|
144
133
|
end
|
145
134
|
end
|
146
135
|
|
147
|
-
def
|
148
|
-
|
149
|
-
ret = CALLS["kernel32!SetThreadContext:LP=L"].call(h, buf)
|
136
|
+
def set_thread_context(h, ctx)
|
137
|
+
ret = Win.SetThreadContext(h, ctx)
|
150
138
|
raise WinX.new(:set_thread_context) if ret == 0
|
151
139
|
return ret
|
152
140
|
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 = [Ragweed::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
141
|
end
|
208
142
|
end
|