ragweed 0.2.0.pre2-java → 0.2.0.pre3-java
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/VERSION +1 -1
- data/lib/ragweed.rb +4 -4
- data/lib/ragweed/debugger32.rb +2 -0
- data/lib/ragweed/debuggertux.rb +4 -1
- data/lib/ragweed/wrap32/debugging.rb +146 -73
- data/lib/ragweed/wrap32/hooks.rb +1 -1
- data/lib/ragweed/wrap32/wrap32.rb +2 -0
- data/lib/ragweed/wraposx/thread_context.rb +222 -0
- data/lib/ragweed/wraptux.rb +0 -1
- data/lib/ragweed/wraptux/constants.rb +6 -0
- data/lib/ragweed/wraptux/process.rb +35 -0
- data/lib/ragweed/wraptux/wraptux.rb +1 -1
- data/ragweed.gemspec +3 -3
- metadata +4 -4
- data/lib/ragweed/wraptux/struct_helpers.rb +0 -25
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.0.
|
1
|
+
0.2.0.pre3
|
data/lib/ragweed.rb
CHANGED
@@ -75,11 +75,11 @@ end # module Ragweed
|
|
75
75
|
module Ragweed::FFIStructInclude
|
76
76
|
if RUBY_VERSION < "1.9"
|
77
77
|
def methods regular=true
|
78
|
-
super + self.
|
78
|
+
(super + self.members.map{|x| [x.to_s, x.to_s+"="]}).flatten
|
79
79
|
end
|
80
80
|
else
|
81
81
|
def methods regular=true
|
82
|
-
super + self.
|
82
|
+
(super + self.members.map{|x| [x, (x.to_s+"=").intern]}).flatten
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
@@ -93,8 +93,8 @@ module Ragweed::FFIStructInclude
|
|
93
93
|
end
|
94
94
|
|
95
95
|
def respond_to? meth, include_priv=false
|
96
|
-
mth = meth.to_s.gsub(/=$/,'')
|
97
|
-
self.
|
96
|
+
# mth = meth.to_s.gsub(/=$/,'')
|
97
|
+
!((self.methods & [meth, meth.to_s]).empty?) || super
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
data/lib/ragweed/debugger32.rb
CHANGED
@@ -305,6 +305,7 @@ class Ragweed::Debugger32
|
|
305
305
|
def on_heap_corruption(ev) end
|
306
306
|
def on_buffer_overrun(ev) end
|
307
307
|
def on_invalid_disposition(ev) end
|
308
|
+
def on_attach() end
|
308
309
|
|
309
310
|
## Read through me to see all the random events
|
310
311
|
## you can hook in a subclass.
|
@@ -382,6 +383,7 @@ class Ragweed::Debugger32
|
|
382
383
|
Ragweed::Wrap32::debug_active_process(@p.pid)
|
383
384
|
Ragweed::Wrap32::debug_set_process_kill_on_exit
|
384
385
|
@attached = true
|
386
|
+
try(:on_attach)
|
385
387
|
@breakpoints.each_pair do |k, bp|
|
386
388
|
bp.install
|
387
389
|
end
|
data/lib/ragweed/debuggertux.rb
CHANGED
@@ -13,7 +13,7 @@ module Ragweed; end
|
|
13
13
|
## that Debuggertux already handles, call "super", too.
|
14
14
|
class Ragweed::Debuggertux
|
15
15
|
attr_reader :pid, :status, :exited, :signal
|
16
|
-
attr_accessor :breakpoints, :mapped_regions
|
16
|
+
attr_accessor :breakpoints, :mapped_regions, :process
|
17
17
|
|
18
18
|
## Class to handle installing/uninstalling breakpoints
|
19
19
|
class Breakpoint
|
@@ -78,6 +78,8 @@ class Ragweed::Debuggertux
|
|
78
78
|
@mapped_regions = Hash.new
|
79
79
|
@breakpoints = Hash.new
|
80
80
|
@opts.each { |k, v| try(k) if v }
|
81
|
+
|
82
|
+
@process = Ragweed::Process.new(@pid)
|
81
83
|
end
|
82
84
|
|
83
85
|
def self.find_by_regex(rx)
|
@@ -462,6 +464,7 @@ class Ragweed::Debuggertux
|
|
462
464
|
def print_registers
|
463
465
|
regs = get_registers
|
464
466
|
puts "eip %08x" % regs.eip
|
467
|
+
puts "ebp %08x" % regs.ebp
|
465
468
|
puts "esi %08x" % regs.esi
|
466
469
|
puts "edi %08x" % regs.edi
|
467
470
|
puts "esp %08x" % regs.esp
|
@@ -13,6 +13,10 @@ module Ragweed::Wrap32
|
|
13
13
|
UNLOAD_DLL = 7
|
14
14
|
end
|
15
15
|
|
16
|
+
module PagePermissions
|
17
|
+
PAGE_EXECUTE_READWRITE = 0x40
|
18
|
+
end
|
19
|
+
|
16
20
|
module ExceptionCodes
|
17
21
|
ACCESS_VIOLATION = 0xC0000005
|
18
22
|
GUARD_PAGE = 0x80000001
|
@@ -136,85 +140,154 @@ class Ragweed::Wrap32::DebugEventU < FFI::Union
|
|
136
140
|
end
|
137
141
|
|
138
142
|
class Ragweed::Wrap32::DebugEvent < FFI::Struct
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
@parameters = []
|
184
|
-
|
185
|
-
self.number_of_parameters.times do |i|
|
186
|
-
@parameters << self.u.exception_debug_info.exception_record.exception_information[i]
|
143
|
+
include Ragweed::FFIStructInclude
|
144
|
+
|
145
|
+
layout :DebugEventCode, :ulong,
|
146
|
+
:ProcessId, :ulong,
|
147
|
+
:ThreadId, :ulong,
|
148
|
+
:u, Ragweed::Wrap32::DebugEventU
|
149
|
+
|
150
|
+
# backwards compatability
|
151
|
+
def code; self[:DebugEventCode]; end
|
152
|
+
def code=(cd); self[:DebugEventCode] = cd; end
|
153
|
+
def pid; self[:ProcessId]; end
|
154
|
+
def pid=(pd); self[:ProcessId]= pd; end
|
155
|
+
def tid; self[:ThreadId]; end
|
156
|
+
def tid=(td); self[:ThreadId] = td; end
|
157
|
+
|
158
|
+
# We have rubified this FFI structure by creating a bunch of proxy
|
159
|
+
# methods that are normally only accessible via self.u.x.y which is
|
160
|
+
# a lot to type. You can still use that method however these instance
|
161
|
+
# variables should allow for considerably clearer code
|
162
|
+
if RUBY_VERSION < "1.9"
|
163
|
+
def methods regular=true
|
164
|
+
ret = super + self.members.map{|x| [x.to_s, x.to_s + "="]}
|
165
|
+
ret += case self[:DebugEventCode]
|
166
|
+
when Ragweed::Wrap32::DebugCodes::CREATE_PROCESS
|
167
|
+
self[:u][:create_process_debug_info].members.map{|x| [x.to_s, x.to_s + "="]}
|
168
|
+
when Ragweed::Wrap32::DebugCodes::CREATE_THREAD
|
169
|
+
self[:u][:create_thread_debug_info].members.map{|x| [x.to_s, x.to_s + "="]}
|
170
|
+
when Ragweed::Wrap32::DebugCodes::EXIT_PROCESS
|
171
|
+
self[:u][:exit_process_debug_info].members.map{|x| [x.to_s, x.to_s + "="]}
|
172
|
+
when Ragweed::Wrap32::DebugCodes::EXIT_THREAD
|
173
|
+
self[:u][:exit_thread_debug_info].members.map{|x| [x.to_s, x.to_s + "="]}
|
174
|
+
when Ragweed::Wrap32::DebugCodes::LOAD_DLL
|
175
|
+
self[:u][:load_dll_debug_info].members.map{|x| [x.to_s, x.to_s + "="]}
|
176
|
+
when Ragweed::Wrap32::DebugCodes::OUTPUT_DEBUG_STRING
|
177
|
+
self[:u][:output_debug_string_info].members.map{|x| [x.to_s, x.to_s + "="]}
|
178
|
+
when Ragweed::Wrap32::DebugCodes::RIP
|
179
|
+
self[:u][:rip_info].members.map{|x| [x.to_s, x.to_s + "="]}
|
180
|
+
when Ragweed::Wrap32::DebugCodes::UNLOAD_DLL
|
181
|
+
self[:u][:unload_dll_debug_info].members.map{|x| [x.to_s, x.to_s + "="]}
|
182
|
+
when Ragweed::Wrap32::DebugCodes::EXCEPTION
|
183
|
+
self[:u][:exception_debug_info].members.map{|x| [x.to_s, x.to_s + "="]} + self[:u][:exception_debug_info][:exception_record].members.map{|x| [x.to_s, x.to_s + "="]}
|
184
|
+
else
|
185
|
+
[]
|
187
186
|
end
|
187
|
+
ret.flatten
|
188
|
+
end
|
189
|
+
else
|
190
|
+
def methods regular=true
|
191
|
+
ret = super + self.members.map{|x| [x, (x.to_s + "=").intern]}
|
192
|
+
ret += case self[:DebugEventCode]
|
193
|
+
when Ragweed::Wrap32::DebugCodes::CREATE_PROCESS
|
194
|
+
self[:u][:create_process_debug_info].members.map{|x| [x, (x.to_s + "=").intern]}
|
195
|
+
when Ragweed::Wrap32::DebugCodes::CREATE_THREAD
|
196
|
+
self[:u][:create_thread_debug_info].members.map{|x| [x, (x.to_s + "=").intern]}
|
197
|
+
when Ragweed::Wrap32::DebugCodes::EXIT_PROCESS
|
198
|
+
self[:u][:exit_process_debug_info].members.map{|x| [x, (x.to_s + "=").intern]}
|
199
|
+
when Ragweed::Wrap32::DebugCodes::EXIT_THREAD
|
200
|
+
self[:u][:exit_thread_debug_info].members.map{|x| [x, (x.to_s + "=").intern]}
|
201
|
+
when Ragweed::Wrap32::DebugCodes::LOAD_DLL
|
202
|
+
self[:u][:load_dll_debug_info].members.map{|x| [x, (x.to_s + "=").intern]}
|
203
|
+
when Ragweed::Wrap32::DebugCodes::OUTPUT_DEBUG_STRING
|
204
|
+
self[:u][:output_debug_string_info].members.map{|x| [x, (x.to_s + "=").intern]}
|
205
|
+
when Ragweed::Wrap32::DebugCodes::RIP
|
206
|
+
self[:u][:rip_info].members.map{|x| [x, (x.to_s + "=").intern]}
|
207
|
+
when Ragweed::Wrap32::DebugCodes::UNLOAD_DLL
|
208
|
+
self[:u][:unload_dll_debug_info].members.map{|x| [x, (x.to_s + "=").intern]}
|
209
|
+
when Ragweed::Wrap32::DebugCodes::EXCEPTION
|
210
|
+
self[:u][:exception_debug_info].members.map{|x| [x, (x.to_s + "=").intern]} + self[:u][:exception_debug_info][:exception_record].members.map{|x| [x, (x.to_s + "=").intern]}
|
211
|
+
else
|
212
|
+
[]
|
213
|
+
end
|
214
|
+
ret.flatten
|
215
|
+
end
|
216
|
+
end
|
188
217
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
218
|
+
def method_missing meth, *args
|
219
|
+
super unless self.respond_to? meth
|
220
|
+
if meth.to_s =~ /=$/
|
221
|
+
mth = meth.to_s.gsub(/=$/,'').intern
|
222
|
+
if self.members.include? mth
|
223
|
+
# don't proxy
|
224
|
+
self.__send__(:[]=, mth, *args)
|
225
|
+
else
|
226
|
+
case self[:DebugEventCode]
|
227
|
+
when Ragweed::Wrap32::DebugCodes::CREATE_PROCESS
|
228
|
+
self[:u][:create_process_debug_info].__send__(:[]=, mth, *args)
|
229
|
+
when Ragweed::Wrap32::DebugCodes::CREATE_THREAD
|
230
|
+
self[:u][:create_thread_debug_info].__send__(:[]=, mth, *args)
|
231
|
+
when Ragweed::Wrap32::DebugCodes::EXIT_PROCESS
|
232
|
+
self[:u][:exit_process_debug_info].__send__(:[]=, mth, *args)
|
233
|
+
when Ragweed::Wrap32::DebugCodes::EXIT_THREAD
|
234
|
+
self[:u][:exit_thread_debug_info].__send__(:[]=, mth, *args)
|
235
|
+
when Ragweed::Wrap32::DebugCodes::LOAD_DLL
|
236
|
+
self[:u][:load_dll_debug_info].__send__(:[]=, mth, *args)
|
237
|
+
when Ragweed::Wrap32::DebugCodes::OUTPUT_DEBUG_STRING
|
238
|
+
self[:u][:output_debug_string_info].__send__(:[]=, mth, *args)
|
239
|
+
when Ragweed::Wrap32::DebugCodes::RIP
|
240
|
+
self[:u][:rip_info].__send__(:[]=, mth, *args)
|
241
|
+
when Ragweed::Wrap32::DebugCodes::UNLOAD_DLL
|
242
|
+
self[:u][:unload_dll_debug_info].__send__(:[]=, mth, *args)
|
243
|
+
when Ragweed::Wrap32::DebugCodes::EXCEPTION
|
244
|
+
case mth
|
245
|
+
when :exception_record, :first_chance
|
246
|
+
self[:u][:exception_debug_info].__send__(:[]=, mth, *args)
|
247
|
+
else # it's in the exception_record -- gross, I know but...
|
248
|
+
self[:u][:exception_debug_info][:exception_record].__send__(meth, *args)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
213
252
|
else
|
214
|
-
|
253
|
+
if self.members.include? meth
|
254
|
+
# don't proxy
|
255
|
+
self.__send__(:[], meth, *args)
|
256
|
+
else
|
257
|
+
case self[:DebugEventCode]
|
258
|
+
when Ragweed::Wrap32::DebugCodes::CREATE_PROCESS
|
259
|
+
self[:u][:create_process_debug_info].__send__(:[], meth, *args)
|
260
|
+
when Ragweed::Wrap32::DebugCodes::CREATE_THREAD
|
261
|
+
self[:u][:create_thread_debug_info].__send__(:[], meth, *args)
|
262
|
+
when Ragweed::Wrap32::DebugCodes::EXIT_PROCESS
|
263
|
+
self[:u][:exit_process_debug_info].__send__(:[], meth, *args)
|
264
|
+
when Ragweed::Wrap32::DebugCodes::EXIT_THREAD
|
265
|
+
self[:u][:exit_thread_debug_info].__send__(:[], meth, *args)
|
266
|
+
when Ragweed::Wrap32::DebugCodes::LOAD_DLL
|
267
|
+
self[:u][:load_dll_debug_info].__send__(:[], meth, *args)
|
268
|
+
when Ragweed::Wrap32::DebugCodes::OUTPUT_DEBUG_STRING
|
269
|
+
self[:u][:output_debug_string_info].__send__(:[], meth, *args)
|
270
|
+
when Ragweed::Wrap32::DebugCodes::RIP
|
271
|
+
self[:u][:rip_info].__send__(:[], meth, *args)
|
272
|
+
when Ragweed::Wrap32::DebugCodes::UNLOAD_DLL
|
273
|
+
self[:u][:unload_dll_debug_info].__send__(:[], meth, *args)
|
274
|
+
when Ragweed::Wrap32::DebugCodes::EXCEPTION
|
275
|
+
case meth
|
276
|
+
when :exception_record, :first_chance
|
277
|
+
self[:u][:exception_debug_info].__send__(:[], meth, *args)
|
278
|
+
else # it's in the exception_record -- gross, I know but...
|
279
|
+
self[:u][:exception_debug_info][:exception_record].__send__(meth, *args)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
215
283
|
end
|
216
284
|
end
|
217
285
|
|
286
|
+
def respond_to? meth, include_priv=false
|
287
|
+
# mth = meth.to_s.gsub(/=$/,'')
|
288
|
+
!((self.methods & [meth, meth.to_s]).empty?) || super
|
289
|
+
end
|
290
|
+
|
218
291
|
def inspect_code(c)
|
219
292
|
Ragweed::Wrap32::DebugCodes.to_key_hash[c].to_s || c.to_i
|
220
293
|
end
|
data/lib/ragweed/wrap32/hooks.rb
CHANGED
@@ -25,7 +25,7 @@ class Ragweed::Debugger32
|
|
25
25
|
## get an idea of where the instruction
|
26
26
|
## is mapped.
|
27
27
|
eip = ctx.eip
|
28
|
-
if esp != 0 and esp > (eip & 0xf0000000)
|
28
|
+
if esp != 0 #and esp > (eip & 0xf0000000)
|
29
29
|
breakpoint_set(esp) do |ev,ctx|
|
30
30
|
callable.call(ev, ctx, :leave, args)
|
31
31
|
breakpoint_clear(esp)
|
@@ -117,6 +117,8 @@ module Ragweed::Wrap32
|
|
117
117
|
attach_function 'DeviceIoControl', [ :long, :long, :pointer, :long, :pointer, :long, :pointer, :pointer ], :long
|
118
118
|
attach_function 'GetOverlappedResult', [ :long, :pointer, :pointer, :long ], :long
|
119
119
|
attach_function 'WaitForMultipleObjects', [ :long, :pointer, :long, :long ], :long
|
120
|
+
attach_function 'CreateProcessA', [ :pointer, :pointer, :pointer, :pointer, :long, :long, :pointer, :pointer, :pointer, :pointer ], :long
|
121
|
+
attach_function 'CreateProcessW', [ :pointer, :pointer, :pointer, :pointer, :long, :long, :pointer, :pointer, :pointer, :pointer ], :long
|
120
122
|
|
121
123
|
ffi_lib 'ntdll'
|
122
124
|
ffi_convention :stdcall
|
@@ -255,6 +255,80 @@ EOM
|
|
255
255
|
FLAVOR = 7
|
256
256
|
layout :tsh, Ragweed::Wraposx::ThreadContext::X86StateHdr,
|
257
257
|
:uts, Ragweed::Wraposx::ThreadContext::UnionThreadState
|
258
|
+
|
259
|
+
# We have rubified this FFI structure by creating a bunch of proxy
|
260
|
+
# methods that are normally only accessible via self.v.x.y which is
|
261
|
+
# a lot to type. You can still use that method however these proxy
|
262
|
+
# methods should allow for considerably clearer code
|
263
|
+
if RUBY_VERSION < "1.9"
|
264
|
+
def methods regular=true
|
265
|
+
ret = super + self.members.map{|x| [x.to_s, x.to_s + "="]}
|
266
|
+
ret += self[:tsh].members.map{|x| [x.to_s, x.to_s + "="]}
|
267
|
+
ret + case self[:tsh][:flavor]
|
268
|
+
when Ragweed::Wraposx::ThreadContext::X86_THREAD_STATE32
|
269
|
+
self[:uts].ts32.members.map{|x| [x.to_s, x.to_s + "="]}
|
270
|
+
when Ragweed::Wraposx::ThreadContext::X86_THREAD_STATE64
|
271
|
+
self[:uts].ts64.members.map{|x| [x.to_s, x.to_s + "="]}
|
272
|
+
else
|
273
|
+
[]
|
274
|
+
end
|
275
|
+
ret.flatten
|
276
|
+
end
|
277
|
+
else
|
278
|
+
def methods regular=true
|
279
|
+
ret = super + self.members.map{|x| [x, (x.to_s + "=").intern]}
|
280
|
+
ret += self[:tsh].members.map{|x| [x, (x.to_s + "=").intern]}
|
281
|
+
ret + case self[:tsh][:flavor]
|
282
|
+
when Ragweed::Wraposx::ThreadContext::X86_THREAD_STATE32
|
283
|
+
self[:uts].ts32.members.map{|x| [x, (x.to_s + "=").intern]}
|
284
|
+
when Ragweed::Wraposx::ThreadContext::X86_THREAD_STATE64
|
285
|
+
self[:uts].ts64.members.map{|x| [x, (x.to_s + "=").intern]}
|
286
|
+
else
|
287
|
+
[]
|
288
|
+
end
|
289
|
+
ret.flatten
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def method_missing meth, *args
|
294
|
+
super unless self.respond_to? meth
|
295
|
+
if meth.to_s =~ /=$/
|
296
|
+
mth = meth.to_s.gsub(/=$/,'').intern
|
297
|
+
if self.members.include? mth
|
298
|
+
# don't proxy
|
299
|
+
self.__send__(:[]=, mth, *args)
|
300
|
+
elsif self[:tsh].members.include? meth
|
301
|
+
self[:tsh].__send__(:[]=, mth, *args)
|
302
|
+
else
|
303
|
+
case self[:tsh][:flavor]
|
304
|
+
when Ragweed::Wraposx::ThreadContext::X86_THREAD_STATE32
|
305
|
+
self[:uts].ts32.__send__(:[]=, mth, *args)
|
306
|
+
when Ragweed::Wraposx::ThreadContext::X86_THREAD_STATE64
|
307
|
+
self[:uts].ts64.__send__(:[]=, mth, *args)
|
308
|
+
end
|
309
|
+
end
|
310
|
+
else
|
311
|
+
if self.members.include? meth
|
312
|
+
# don't proxy
|
313
|
+
self.__send__(:[], meth, *args)
|
314
|
+
elsif self[:tsh].members.include? meth
|
315
|
+
self[:tsh].__send__(:[], meth, *args)
|
316
|
+
else
|
317
|
+
case self[:tsh][:flavor]
|
318
|
+
when Ragweed::Wraposx::ThreadContext::X86_THREAD_STATE32
|
319
|
+
self[:uts].ts32.__send__(:[], meth, *args)
|
320
|
+
when Ragweed::Wraposx::ThreadContext::X86_THREAD_STATE64
|
321
|
+
self[:uts].ts64.__send__(:[], meth, *args)
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
def respond_to? meth, include_priv=false
|
328
|
+
mth = meth.to_s.gsub(/=$/,'') # may not be needed anymore
|
329
|
+
self.methods.include? mth || super
|
330
|
+
end
|
331
|
+
|
258
332
|
end
|
259
333
|
|
260
334
|
# _STRUCT_X86_DEBUG_STATE32
|
@@ -352,6 +426,79 @@ EOM
|
|
352
426
|
FLAVOR = 12
|
353
427
|
layout :dsh, Ragweed::Wraposx::ThreadContext::X86StateHdr,
|
354
428
|
:uds, Ragweed::Wraposx::ThreadContext::UnionDebugState
|
429
|
+
|
430
|
+
# We have rubified this FFI structure by creating a bunch of proxy
|
431
|
+
# methods that are normally only accessible via self.v.x.y which is
|
432
|
+
# a lot to type. You can still use that method however these proxy
|
433
|
+
# methods should allow for considerably clearer code
|
434
|
+
if RUBY_VERSION < "1.9"
|
435
|
+
def methods regular=true
|
436
|
+
ret = super + self.members.map{|x| [x.to_s, x.to_s + "="]}
|
437
|
+
ret += self[:dsh].members.map{|x| [x.to_s, x.to_s + "="]}
|
438
|
+
ret + case self[:dsh][:flavor]
|
439
|
+
when Ragweed::Wraposx::ThreadContext::X86_DEBUG_STATE32
|
440
|
+
self[:uds].ds32.members.map{|x| [x.to_s, x.to_s + "="]}
|
441
|
+
when Ragweed::Wraposx::ThreadContext::X86_DEBUG_STATE64
|
442
|
+
self[:uds].ds64.members.map{|x| [x.to_s, x.to_s + "="]}
|
443
|
+
else
|
444
|
+
[]
|
445
|
+
end
|
446
|
+
ret.flatten
|
447
|
+
end
|
448
|
+
else
|
449
|
+
def methods regular=true
|
450
|
+
ret = super + self.members.map{|x| [x, (x.to_s + "=").intern]}
|
451
|
+
ret += self[:dsh].members.map{|x| [x, (x.to_s + "=").intern]}
|
452
|
+
ret + case self[:dsh][:flavor]
|
453
|
+
when Ragweed::Wraposx::ThreadContext::X86_DEBUG_STATE32
|
454
|
+
self[:uds].ds32.members.map{|x| [x, (x.to_s + "=").intern]}
|
455
|
+
when Ragweed::Wraposx::ThreadContext::X86_DEBUG_STATE64
|
456
|
+
self[:uds].ds64.members.map{|x| [x, (x.to_s + "=").intern]}
|
457
|
+
else
|
458
|
+
[]
|
459
|
+
end
|
460
|
+
ret.flatten
|
461
|
+
end
|
462
|
+
end
|
463
|
+
|
464
|
+
def method_missing meth, *args
|
465
|
+
super unless self.respond_to? meth
|
466
|
+
if meth.to_s =~ /=$/
|
467
|
+
mth = meth.to_s.gsub(/=$/,'').intern
|
468
|
+
if self.members.include? mth
|
469
|
+
# don't proxy
|
470
|
+
self.__send__(:[]=, mth, *args)
|
471
|
+
elsif self[:dsh].members.include? meth
|
472
|
+
self[:dsh].__send__(:[]=, mth, *args)
|
473
|
+
else
|
474
|
+
case self[:dsh][:flavor]
|
475
|
+
when Ragweed::Wraposx::ThreadContext::X86_DEBUG_STATE32
|
476
|
+
self[:uds].ds32.__send__(:[]=, mth, *args)
|
477
|
+
when Ragweed::Wraposx::ThreadContext::X86_DEBUG_STATE64
|
478
|
+
self[:uds].ds64.__send__(:[]=, mth, *args)
|
479
|
+
end
|
480
|
+
end
|
481
|
+
else
|
482
|
+
if self.members.include? meth
|
483
|
+
# don't proxy
|
484
|
+
self.__send__(:[], meth, *args)
|
485
|
+
elsif self[:dsh].members.include? meth
|
486
|
+
self[:dsh].__send__(:[], meth, *args)
|
487
|
+
else
|
488
|
+
case self[:dsh][:flavor]
|
489
|
+
when Ragweed::Wraposx::ThreadContext::X86_DEBUG_STATE32
|
490
|
+
self[:uds].ds32.__send__(:[], meth, *args)
|
491
|
+
when Ragweed::Wraposx::ThreadContext::X86_DEBUG_STATE64
|
492
|
+
self[:uds].ds64.__send__(:[], meth, *args)
|
493
|
+
end
|
494
|
+
end
|
495
|
+
end
|
496
|
+
end
|
497
|
+
|
498
|
+
def respond_to? meth, include_priv=false
|
499
|
+
mth = meth.to_s.gsub(/=$/,'') # may not be needed anymore
|
500
|
+
self.methods.include? mth || super
|
501
|
+
end
|
355
502
|
end
|
356
503
|
|
357
504
|
# _STRUCT_X86_EXCEPTION_STATE32
|
@@ -419,6 +566,81 @@ EOM
|
|
419
566
|
FLAVOR = 9
|
420
567
|
layout :esh, Ragweed::Wraposx::ThreadContext::X86StateHdr,
|
421
568
|
:ues, Ragweed::Wraposx::ThreadContext::UnionExceptionState
|
569
|
+
|
570
|
+
#comment
|
571
|
+
# We have rubified this FFI structure by creating a bunch of proxy
|
572
|
+
# methods that are normally only accessible via self.v.x.y which is
|
573
|
+
# a lot to type. You can still use that method however these proxy
|
574
|
+
# methods should allow for considerably clearer code
|
575
|
+
if RUBY_VERSION < "1.9"
|
576
|
+
def methods regular=true
|
577
|
+
ret = super + self.members.map{|x| [x.to_s, x.to_s + "="]}
|
578
|
+
ret += self[:esh].members.map{|x| [x.to_s, x.to_s + "="]}
|
579
|
+
ret + case self[:esh][:flavor]
|
580
|
+
when Ragweed::Wraposx::ThreadContext::X86_EXCEPTION_STATE32
|
581
|
+
self[:ues].es32.members.map{|x| [x.to_s, x.to_s + "="]}
|
582
|
+
when Ragweed::Wraposx::ThreadContext::X86_EXCEPTION_STATE64
|
583
|
+
self[:ues].es64.members.map{|x| [x.to_s, x.to_s + "="]}
|
584
|
+
else
|
585
|
+
[]
|
586
|
+
end
|
587
|
+
ret.flatten
|
588
|
+
end
|
589
|
+
else
|
590
|
+
def methods regular=true
|
591
|
+
ret = super + self.members.map{|x| [x, (x.to_s + "=").intern]}
|
592
|
+
ret += self[:esh].members.map{|x| [x, (x.to_s + "=").intern]}
|
593
|
+
ret + case self[:esh][:flavor]
|
594
|
+
when Ragweed::Wraposx::ThreadContext::X86_EXCEPTION_STATE32
|
595
|
+
self[:ues].es32.members.map{|x| [x, (x.to_s + "=").intern]}
|
596
|
+
when Ragweed::Wraposx::ThreadContext::X86_EXCEPTION_STATE64
|
597
|
+
self[:ues].es64.members.map{|x| [x, (x.to_s + "=").intern]}
|
598
|
+
else
|
599
|
+
[]
|
600
|
+
end
|
601
|
+
ret.flatten
|
602
|
+
end
|
603
|
+
end
|
604
|
+
|
605
|
+
def method_missing meth, *args
|
606
|
+
super unless self.respond_to? meth
|
607
|
+
if meth.to_s =~ /=$/
|
608
|
+
mth = meth.to_s.gsub(/=$/,'').intern
|
609
|
+
if self.members.include? mth
|
610
|
+
# don't proxy
|
611
|
+
self.__send__(:[]=, mth, *args)
|
612
|
+
elsif self[:esh].members.include? meth
|
613
|
+
self[:esh].__send__(:[]=, mth, *args)
|
614
|
+
else
|
615
|
+
case self[:esh][:flavor]
|
616
|
+
when Ragweed::Wraposx::ThreadContext::X86_EXCEPTION_STATE32
|
617
|
+
self[:ues].es32.__send__(:[]=, mth, *args)
|
618
|
+
when Ragweed::Wraposx::ThreadContext::X86_EXCEPTION_STATE64
|
619
|
+
self[:ues].es64.__send__(:[]=, mth, *args)
|
620
|
+
end
|
621
|
+
end
|
622
|
+
else
|
623
|
+
if self.members.include? meth
|
624
|
+
# don't proxy
|
625
|
+
self.__send__(:[], meth, *args)
|
626
|
+
elsif self[:esh].members.include? meth
|
627
|
+
self[:esh].__send__(:[], meth, *args)
|
628
|
+
else
|
629
|
+
case self[:esh][:flavor]
|
630
|
+
when Ragweed::Wraposx::ThreadContext::X86_EXCEPTION_STATE32
|
631
|
+
self[:ues].es32.__send__(:[], meth, *args)
|
632
|
+
when Ragweed::Wraposx::ThreadContext::X86_EXCEPTION_STATE64
|
633
|
+
self[:ues].es64.__send__(:[], meth, *args)
|
634
|
+
end
|
635
|
+
end
|
636
|
+
end
|
637
|
+
end
|
638
|
+
|
639
|
+
def respond_to? meth, include_priv=false
|
640
|
+
mth = meth.to_s.gsub(/=$/,'') # may not be needed anymore
|
641
|
+
self.methods.include? mth || super
|
642
|
+
end
|
643
|
+
|
422
644
|
end
|
423
645
|
|
424
646
|
# _STRUCT_X86_FLOAT_STATE32
|
data/lib/ragweed/wraptux.rb
CHANGED
@@ -0,0 +1,35 @@
|
|
1
|
+
class Ragweed::Process
|
2
|
+
|
3
|
+
include Ragweed
|
4
|
+
attr_reader :pid
|
5
|
+
|
6
|
+
def initialize(pid); @pid = pid; end
|
7
|
+
|
8
|
+
## Read/write ranges of data or fixnums to/from the process by address.
|
9
|
+
def read(off, sz=4096)
|
10
|
+
a = []
|
11
|
+
while off < off+sz
|
12
|
+
a.push(Ragweed::Wraptux::ptrace(Ragweed::Wraptux::Ptrace::PEEK_TEXT, @pid, off, 0))
|
13
|
+
return a.pack('L*') if a.last == -1 and FFI.errno != 0
|
14
|
+
off+=4
|
15
|
+
end
|
16
|
+
a.pack('L*')
|
17
|
+
end
|
18
|
+
|
19
|
+
## ptrace sucks, writing 8 or 16 bytes will probably
|
20
|
+
## result in failure unless you PTRACE_POKE first and
|
21
|
+
## get the rest of the original value at the address
|
22
|
+
def write(off, data)
|
23
|
+
while off < data.size
|
24
|
+
Ragweed::Wraptux::ptrace(Ragweed::Wraptux::Ptrace::POKE_TEXT, @pid, off, data[off,4].unpack('L').first)
|
25
|
+
off += 4
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def read32(off); read(off, 4).unpack("L").first; end
|
30
|
+
def read16(off); read(off, 2).unpack("v").first; end
|
31
|
+
def read8(off); read(off, 1)[0]; end
|
32
|
+
def write32(off, v); write(off, [v].pack("L")); end
|
33
|
+
def write16(off, v); write(off, [v].pack("v")); end
|
34
|
+
def write8(off, v); write(off, v.chr); end
|
35
|
+
end
|
@@ -48,7 +48,7 @@ module Ragweed::Wraptux
|
|
48
48
|
p = FFI::MemoryPointer.new(:int, 1)
|
49
49
|
FFI.errno = 0
|
50
50
|
r = Libc.waitpid(pid,p,opts)
|
51
|
-
raise
|
51
|
+
raise SystemCallError.new "waitpid", FFI.errno if r == -1
|
52
52
|
status = p.get_int32(0)
|
53
53
|
[r, status]
|
54
54
|
end
|
data/ragweed.gemspec
CHANGED
@@ -5,12 +5,12 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{ragweed}
|
8
|
-
s.version = "0.2.0.
|
8
|
+
s.version = "0.2.0.pre3"
|
9
9
|
s.platform = %q{java}
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.authors = ["tduehr", "struct", "tqbf"]
|
13
|
-
s.date = %q{2011-
|
13
|
+
s.date = %q{2011-03-09}
|
14
14
|
s.description = %q{General debugging tool written in Ruby for OSX/Win32/Linux}
|
15
15
|
s.email = %q{td@matasano.com}
|
16
16
|
s.extra_rdoc_files = [
|
@@ -65,7 +65,7 @@ Gem::Specification.new do |s|
|
|
65
65
|
"lib/ragweed/wraposx/wraposx.rb",
|
66
66
|
"lib/ragweed/wraptux.rb",
|
67
67
|
"lib/ragweed/wraptux/constants.rb",
|
68
|
-
"lib/ragweed/wraptux/
|
68
|
+
"lib/ragweed/wraptux/process.rb",
|
69
69
|
"lib/ragweed/wraptux/threads.rb",
|
70
70
|
"lib/ragweed/wraptux/wraptux.rb",
|
71
71
|
"ragweed.gemspec",
|
metadata
CHANGED
@@ -6,8 +6,8 @@ version: !ruby/object:Gem::Version
|
|
6
6
|
- 0
|
7
7
|
- 2
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.2.0.
|
9
|
+
- pre3
|
10
|
+
version: 0.2.0.pre3
|
11
11
|
platform: java
|
12
12
|
authors:
|
13
13
|
- tduehr
|
@@ -17,7 +17,7 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2011-
|
20
|
+
date: 2011-03-09 00:00:00 -06:00
|
21
21
|
default_executable:
|
22
22
|
dependencies: []
|
23
23
|
|
@@ -78,7 +78,7 @@ files:
|
|
78
78
|
- lib/ragweed/wraposx/wraposx.rb
|
79
79
|
- lib/ragweed/wraptux.rb
|
80
80
|
- lib/ragweed/wraptux/constants.rb
|
81
|
-
- lib/ragweed/wraptux/
|
81
|
+
- lib/ragweed/wraptux/process.rb
|
82
82
|
- lib/ragweed/wraptux/threads.rb
|
83
83
|
- lib/ragweed/wraptux/wraptux.rb
|
84
84
|
- ragweed.gemspec
|
@@ -1,25 +0,0 @@
|
|
1
|
-
module Ragweed::FFIStructInclude
|
2
|
-
if RUBY_VERSION < "1.9"
|
3
|
-
def methods regular=true
|
4
|
-
super + self.offsets.map{|x| x.first.to_s}
|
5
|
-
end
|
6
|
-
else
|
7
|
-
def methods regular=true
|
8
|
-
super + self.offsets.map{|x| x.first}
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def method_missing meth, *args
|
13
|
-
super unless self.respond_to? meth
|
14
|
-
if meth.to_s =~ /=$/
|
15
|
-
self.__send__(:[]=, meth.to_s.gsub(/=$/,'').intern, *args)
|
16
|
-
else
|
17
|
-
self.__send__(:[], meth, *args)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def respond_to? meth, include_priv=false
|
22
|
-
mth = meth.to_s.gsub(/=$/,'')
|
23
|
-
self.offsets.map{|x| x.first.to_s}.include? mth || super
|
24
|
-
end
|
25
|
-
end
|