ragweed 0.2.0.pre2-java → 0.2.0.pre3-java
Sign up to get free protection for your applications and to get access to all the features.
- 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
|