tduehr-ragweed 0.1.7 → 0.1.7.1

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/lib/ragweed/utils.rb CHANGED
@@ -1,41 +1,59 @@
1
+ class Array
2
+ module ArrayExtensions
3
+ # Convert to hash
4
+ ##
5
+ def to_hash
6
+ # too clever.
7
+ # Hash[*self.flatten]
8
+
9
+ h = Hash.new
10
+ each do |k,v|
11
+ h[k] = v
12
+ end
13
+ h
14
+ end
15
+ end
16
+ include ArrayExtensions
17
+ end
18
+
1
19
  # These should probably be extensions to Module since that's the location of instance_eval and friends.
2
20
  class Object
3
- module ObjectExtensions
4
- # Every object has a "singleton" class, which you can think
5
- # of as the class (ie, 1.metaclass =~ Fixnum) --- but that you
6
- # can modify and extend without fucking up the actual class.
7
- def metaclass; class << self; self; end; end
8
- def meta_eval(&blk) metaclass.instance_eval &blk; end
9
- def meta_def(name, &blk) meta_eval { define_method name, &blk }; end
10
- def try(meth, *args); send(meth, *args) if respond_to? meth; end
11
-
12
- def through(meth, *args)
13
- if respond_to? meth
14
- send(meth, *args)
15
- else
16
- self
17
- end
18
- end
21
+ module ObjectExtensions
22
+ # Every object has a "singleton" class, which you can think
23
+ # of as the class (ie, 1.metaclass =~ Fixnum) --- but that you
24
+ # can modify and extend without fucking up the actual class.
25
+ def metaclass; class << self; self; end; end
26
+ def meta_eval(&blk) metaclass.instance_eval &blk; end
27
+ def meta_def(name, &blk) meta_eval { define_method name, &blk }; end
28
+ def try(meth, *args); send(meth, *args) if respond_to? meth; end
19
29
 
20
- ## This is from Topher Cyll's Stupd IRB tricks
21
- def mymethods
22
- (self.methods - self.class.superclass.methods).sort
30
+ def through(meth, *args)
31
+ if respond_to? meth
32
+ send(meth, *args)
33
+ else
34
+ self
23
35
  end
24
- # self-evident
25
- def callable?; respond_to? :call; end
26
- def number?; kind_of? Numeric; end
27
-
28
- # while X remains callable, keep calling it to get its value
29
- def derive
30
- # also, don't drink and derive
31
- x = self
32
- while x.callable?
33
- x = x()
34
- end
35
- return x
36
+ end
37
+
38
+ ## This is from Topher Cyll's Stupd IRB tricks
39
+ def mymethods
40
+ (self.methods - self.class.superclass.methods).sort
41
+ end
42
+ # self-evident
43
+ def callable?; respond_to? :call; end
44
+ def number?; kind_of? Numeric; end
45
+
46
+ # while X remains callable, keep calling it to get its value
47
+ def derive
48
+ # also, don't drink and derive
49
+ x = self
50
+ while x.callable?
51
+ x = x()
36
52
  end
53
+ return x
37
54
  end
38
- include ObjectExtensions
55
+ end
56
+ include ObjectExtensions
39
57
  end
40
58
 
41
59
  class String
@@ -51,21 +69,31 @@ class String
51
69
  def shift_u8; shift(1).to_u8; end
52
70
 
53
71
  def shift(count=1)
54
- return self if count == 0
55
- slice! 0..(count-1)
72
+ return self if count == 0
73
+ slice! 0..(count-1)
74
+ end
75
+
76
+ # Sometimes string buffers passed through Win32 interfaces come with
77
+ # garbage after the trailing NUL; this method gets rid of that, like
78
+ # String#trim
79
+ def asciiz
80
+ begin
81
+ self[0..self.index("\x00")-1]
82
+ rescue
83
+ self
84
+ end
56
85
  end
86
+
87
+ def asciiz!; replace asciiz; end
57
88
 
58
89
  # Convert a string into hex characters
59
90
  def hexify
60
- l = []
61
- each_byte{|b| l << "%02x" % b}
62
- l.join
91
+ self.unpack("H*").first
63
92
  end
64
93
 
65
94
  # Convert a string of raw hex characters (no %'s or anything) into binary
66
95
  def dehexify
67
- (ret||="") << (me||=clone).shift(2).to_i(16).chr while not (me||=clone).empty?
68
- return ret
96
+ [self].pack("H*")
69
97
  end
70
98
  end
71
99
 
@@ -77,11 +105,17 @@ class Integer
77
105
  def to_l16; [self].pack "v"; end
78
106
  def to_b16; [self].pack "n"; end
79
107
  def to_u8; [self].pack "C"; end
108
+
109
+ # sign extend
110
+ def sx8; ([self].pack "c").unpack("C").first; end
111
+ def sx16; ([self].pack "s").unpack("S").first; end
112
+ def sx32; ([self].pack "l").unpack("L").first; end
113
+
80
114
  def ffs
81
115
  i = 0
82
116
  v = self
83
117
  while((v >>= 1) != 0)
84
- i += 1
118
+ i += 1
85
119
  end
86
120
  return i
87
121
  end
@@ -90,6 +124,14 @@ class Integer
90
124
  end
91
125
 
92
126
  class Module
127
+ def to_name_hash
128
+ @name_hash ||= constants.map {|k| [k.intern, const_get(k.intern)]}.to_hash
129
+ end
130
+
131
+ def to_key_hash
132
+ @key_hash ||= constants.map {|k| [const_get(k.intern), k.intern]}.to_hash
133
+ end
134
+
93
135
  def flag_dump(i)
94
136
  @bit_map ||= constants.map do |k|
95
137
  [k, const_get(k.intern).ffs]
@@ -111,4 +153,4 @@ class Module
111
153
  end
112
154
  return r.reverse
113
155
  end
114
- end
156
+ end
@@ -63,14 +63,14 @@ class Ragweed::Wrap32::DebugEvent
63
63
  @code, @pid, @tid = str.unpack("LLL")
64
64
  str.shift 12
65
65
  case @code
66
- when Wrap32::DebugCodes::CREATE_PROCESS
66
+ when Ragweed::Wrap32::DebugCodes::CREATE_PROCESS
67
67
  @file_handle, @process_handle, @thread_handle,
68
68
  @base, @offset,
69
69
  @info_size, @thread_base, @start_address,
70
70
  @image_name, @unicode = str.unpack("LLLLLLLLLH")
71
- when Wrap32::DebugCodes::CREATE_THREAD
71
+ when Ragweed::Wrap32::DebugCodes::CREATE_THREAD
72
72
  @thread_handle, @thread_base, @start_address = str.unpack("LLL")
73
- when Wrap32::DebugCodes::EXCEPTION
73
+ when Ragweed::Wrap32::DebugCodes::EXCEPTION
74
74
  @exception_code, @exception_flags,
75
75
  @exception_record, @exception_address, @parameter_count = str.unpack("LLLLL")
76
76
  str = str[20..-1]
@@ -81,17 +81,17 @@ class Ragweed::Wrap32::DebugEvent
81
81
  str = str[4..-1]
82
82
  rescue;end
83
83
  end
84
- when Wrap32::DebugCodes::EXIT_PROCESS
84
+ when Ragweed::Wrap32::DebugCodes::EXIT_PROCESS
85
85
  @exit_code = str.unpack("L").first
86
- when Wrap32::DebugCodes::EXIT_THREAD
86
+ when Ragweed::Wrap32::DebugCodes::EXIT_THREAD
87
87
  @exit_code = str.unpack("L").first
88
- when Wrap32::DebugCodes::LOAD_DLL
88
+ when Ragweed::Wrap32::DebugCodes::LOAD_DLL
89
89
  @file_handle, @dll_base, @offset,
90
90
  @info_size, @image_name, @unicode = str.unpack("LLLLLH")
91
- when Wrap32::DebugCodes::OUTPUT_DEBUG_STRING
92
- when Wrap32::DebugCodes::RIP
91
+ when Ragweed::Wrap32::DebugCodes::OUTPUT_DEBUG_STRING
92
+ when Ragweed::Wrap32::DebugCodes::RIP
93
93
  @rip_error, @rip_type = str.unpack("LL")
94
- when Wrap32::DebugCodes::UNLOAD_DLL
94
+ when Ragweed::Wrap32::DebugCodes::UNLOAD_DLL
95
95
  @dll_base = str.unpack("L").first
96
96
  else
97
97
  raise WinX.new(:wait_for_debug_event)
@@ -99,11 +99,11 @@ class Ragweed::Wrap32::DebugEvent
99
99
  end
100
100
 
101
101
  def inspect_code(c)
102
- Wrap32::DebugCodes.to_key_hash[c].to_s || c.to_i
102
+ Ragweed::Wrap32::DebugCodes.to_key_hash[c].to_s || c.to_i
103
103
  end
104
104
 
105
105
  def inspect_exception_code(c)
106
- Wrap32::ExceptionCodes.to_key_hash[c].to_s || c.to_i.to_s(16)
106
+ Ragweed::Wrap32::ExceptionCodes.to_key_hash[c].to_s || c.to_i.to_s(16)
107
107
  end
108
108
 
109
109
  def inspect_parameters(p)
@@ -129,7 +129,7 @@ module Ragweed::Wrap32
129
129
  buf = "\x00" * 1024
130
130
  r = CALLS["kernel32!WaitForDebugEvent:PL=L"].call(buf, ms)
131
131
  raise WinX.new(:wait_for_debug_event) if r == 0 and get_last_error != 121
132
- return Wrap32::DebugEvent.new(buf) if r != 0
132
+ return Ragweed::Wrap32::DebugEvent.new(buf) if r != 0
133
133
  return nil
134
134
  end
135
135
 
@@ -3,12 +3,12 @@ module Ragweed
3
3
  def initialize(path, options={})
4
4
  @path = path
5
5
  @options = options
6
- @h = Wrap32::create_file(@path, :flags => Wrap32::FileAttributes::OVERLAPPED|Wrap32::FileAttributes::NORMAL)
6
+ @h = Ragweed::Wrap32::create_file(@path, :flags => Ragweed::Wrap32::FileAttributes::OVERLAPPED|Ragweed::Wrap32::FileAttributes::NORMAL)
7
7
  end
8
8
 
9
9
  def ioctl(code, inbuf, outbuf)
10
10
  overlap(lambda do |o|
11
- Wrap32::device_io_control(@h, code, inbuf, outbuf, o)
11
+ Ragweed::Wrap32::device_io_control(@h, code, inbuf, outbuf, o)
12
12
  end) do |ret, count|
13
13
  outbuf[0..count]
14
14
  end
@@ -16,7 +16,7 @@ module Ragweed
16
16
 
17
17
  def read(sz)
18
18
  overlap(lambda do |o|
19
- Wrap32::read_file(@h, sz, o)
19
+ Ragweed::Wrap32::read_file(@h, sz, o)
20
20
  end) do |ret, count|
21
21
  ret[0..count]
22
22
  end
@@ -24,21 +24,21 @@ module Ragweed
24
24
 
25
25
  def write(buf)
26
26
  overlap(lambda do |o|
27
- Wrap32::write_file(@h, buf, o)
27
+ Ragweed::Wrap32::write_file(@h, buf, o)
28
28
  end) do |ret, count|
29
29
  count
30
30
  end
31
31
  end
32
32
 
33
33
  def release
34
- Wrap32::close_handle(@h)
34
+ Ragweed::Wrap32::close_handle(@h)
35
35
  @h = nil
36
36
  end
37
37
 
38
38
  private
39
39
 
40
40
  def overlap(proc)
41
- o = Wrap32::Overlapped.get
41
+ o = Ragweed::Wrap32::Overlapped.get
42
42
  ret = proc.call(o)
43
43
  count = o.wait(@h)
44
44
  r = yield ret, count
@@ -27,17 +27,17 @@ class Ragweed::Event
27
27
  # Don't return until the event is signalled. Note that you
28
28
  # can't break this with timeouts or CTR-C.
29
29
  def wait
30
- Wrap32::wait_for_single_object @h
30
+ Ragweed::Wrap32::wait_for_single_object @h
31
31
  end
32
32
 
33
33
  # Signal the event; anyone waiting on it is now released.
34
34
  def signal
35
- Wrap32::set_event(@h)
35
+ Ragweed::Wrap32::set_event(@h)
36
36
  end
37
37
 
38
38
  # Force the event back to unsignalled state.
39
39
  def reset
40
- Wrap32::reset_event(@h)
40
+ Ragweed::Wrap32::reset_event(@h)
41
41
  end
42
42
 
43
43
  # A wait loop.
@@ -6,7 +6,7 @@ class Ragweed::Process
6
6
  include Ragweed
7
7
 
8
8
  def self.find_by_regex(name)
9
- Wrap32::all_processes do |p|
9
+ Ragweed::Wrap32::all_processes do |p|
10
10
  if p.szExeFile =~ name
11
11
  return self.new(p.th32ProcessID)
12
12
  end
@@ -23,7 +23,7 @@ class Ragweed::Process
23
23
 
24
24
  # clone a handle from the remote process to here (to here? tf?)
25
25
  def dup_handle(h)
26
- Wrap32::duplicate_handle(@h, h)
26
+ Ragweed::Wrap32::duplicate_handle(@h, h)
27
27
  end
28
28
 
29
29
  # look up a process by its name --- but this is in the local process,
@@ -31,7 +31,7 @@ class Ragweed::Process
31
31
  # but probably never otherwise.
32
32
  def get_proc(name)
33
33
  return Ptr.new(name) if name.kind_of? Numeric or name.kind_of? Ptr
34
- ptr(Wrap32::get_proc_address(name))
34
+ ptr(Ragweed::Wrap32::get_proc_address(name))
35
35
  end
36
36
 
37
37
  def get_proc_remote(name)
@@ -58,14 +58,14 @@ class Ragweed::Process
58
58
  # Just need a PID to get started.
59
59
  def initialize(pid)
60
60
  @pid = pid
61
- @h = Wrap32::open_process(pid)
61
+ @h = Ragweed::Wrap32::open_process(pid)
62
62
  @a = arena()
63
63
  end
64
64
 
65
65
  # Return the EXE name of the process.
66
66
  def image
67
67
  buf = "\x00" * 256
68
- if Wrap32::nt_query_information_process(@h, 27, buf)
68
+ if Ragweed::Wrap32::nt_query_information_process(@h, 27, buf)
69
69
  buf = buf.from_utf16
70
70
  buf = buf[(buf.index("\\"))..-1]
71
71
  return buf.asciiz
@@ -76,9 +76,9 @@ class Ragweed::Process
76
76
  # Return a list of all the threads in the process; relatively
77
77
  # expensive, so cache the result.
78
78
  def threads(full=false, &block)
79
- return Wrap32::threads(@pid, &block) if block_given?
79
+ return Ragweed::Wrap32::threads(@pid, &block) if block_given?
80
80
  ret = []
81
- Wrap32::threads(@pid) {|x| ((full) ? ret << x : ret << x.th32ThreadID) }
81
+ Ragweed::Wrap32::threads(@pid) {|x| ((full) ? ret << x : ret << x.th32ThreadID) }
82
82
  return ret
83
83
  end
84
84
 
@@ -91,26 +91,26 @@ class Ragweed::Process
91
91
 
92
92
  # Suspend a thread by tid. Technically, this doesn't need to be
93
93
  # a method; you can suspend a thread anywhere without a process handle.
94
- def suspend(tid); Wrap32::open_thread(tid) {|x| Wrap32::suspend_thread(x)}; end
94
+ def suspend(tid); Ragweed::Wrap32::open_thread(tid) {|x| Ragweed::Wrap32::suspend_thread(x)}; end
95
95
 
96
96
  # Resume a thread by tid.
97
- def resume(tid); Wrap32::open_thread(tid) {|x| Wrap32::resume_thread(x)}; end
97
+ def resume(tid); Ragweed::Wrap32::open_thread(tid) {|x| Ragweed::Wrap32::resume_thread(x)}; end
98
98
 
99
99
  # List the modules for the process, either yielding a struct for
100
100
  # each to a block, or returning a list.
101
101
  def modules(&block)
102
102
  if block_given?
103
- Wrap32::list_modules(@pid, &block)
103
+ Ragweed::Wrap32::list_modules(@pid, &block)
104
104
  else
105
105
  ret = []
106
- Wrap32::list_modules(@pid) {|x| ret << x}
106
+ Ragweed::Wrap32::list_modules(@pid) {|x| ret << x}
107
107
  return ret
108
108
  end
109
109
  end
110
110
 
111
111
  # Read/write ranges of data or fixnums to/from the process by address.
112
- def read(off, sz=4096); Wrap32::read_process_memory(@h, off, sz); end
113
- def write(off, data); Wrap32::write_process_memory(@h, off, data); end
112
+ def read(off, sz=4096); Ragweed::Wrap32::read_process_memory(@h, off, sz); end
113
+ def write(off, data); Ragweed::Wrap32::write_process_memory(@h, off, data); end
114
114
  def read32(off); read(off, 4).unpack("L").first; end
115
115
  def read16(off); read(off, 2).unpack("v").first; end
116
116
  def read8(off); read(off, 1)[0]; end
@@ -130,11 +130,11 @@ class Ragweed::Process
130
130
  end
131
131
 
132
132
  # Can I write to this address in the process?
133
- def writeable?(off); Wrap32::writeable? @h, off; end
133
+ def writeable?(off); Ragweed::Wrap32::writeable? @h, off; end
134
134
 
135
135
  # Use VirtualAllocEx to grab a block of memory in the process. This
136
136
  # is expensive, the equivalent of mmap()'ing for each allocation.
137
- def syscall_alloc(sz); ptr(Wrap32::virtual_alloc_ex(@h, sz)); end
137
+ def syscall_alloc(sz); ptr(Ragweed::Wrap32::virtual_alloc_ex(@h, sz)); end
138
138
 
139
139
  # Use arenas, when possible, to quickly allocate memory. The upside
140
140
  # is this is very fast. The downside is you can't free the memory
@@ -150,7 +150,7 @@ class Ragweed::Process
150
150
  # Free the return value of syscall_alloc. Do NOT use for the return
151
151
  # value of alloc.
152
152
  def free(off)
153
- Wrap32::virtual_free_ex(@h, off)
153
+ Ragweed::Wrap32::virtual_free_ex(@h, off)
154
154
  end
155
155
 
156
156
  # Convert an address to "module+10h" notation, when possible.
@@ -199,7 +199,7 @@ class Ragweed::Process
199
199
  def list_memory(&block)
200
200
  ret = []
201
201
  i = 0
202
- while (mbi = Wrap32::virtual_query_ex(@h, i))
202
+ while (mbi = Ragweed::Wrap32::virtual_query_ex(@h, i))
203
203
  break if (not ret.empty? and mbi.BaseAddress == 0)
204
204
  if block_given?
205
205
  yield mbi
@@ -250,8 +250,8 @@ class Ragweed::Process
250
250
  # Dump thread context, returning a struct that contains things like
251
251
  # .Eip and .Eax.
252
252
  def thread_context(tid)
253
- Wrap32::open_thread(tid) do |h|
254
- Wrap32::get_thread_context(h)
253
+ Ragweed::Wrap32::open_thread(tid) do |h|
254
+ Ragweed::Wrap32::get_thread_context(h)
255
255
  end
256
256
  end
257
257
 
@@ -457,7 +457,7 @@ class Ragweed::Process
457
457
  # Do something with a thread while its suspended
458
458
  def with_suspended_thread(tid)
459
459
  ret = nil
460
- Wrap32::with_suspended_thread(tid) {|x| ret = yield}
460
+ Ragweed::Wrap32::with_suspended_thread(tid) {|x| ret = yield}
461
461
  return ret
462
462
  end
463
463
 
@@ -21,7 +21,7 @@ module Ragweed::Wrap32
21
21
  end
22
22
 
23
23
  class << self
24
- def open_process_token(h, access=Wrap32::TokenAccess::ADJUST_PRIVILEGES)
24
+ def open_process_token(h, access=Ragweed::Wrap32::TokenAccess::ADJUST_PRIVILEGES)
25
25
  outw = "\x00" * 4
26
26
  r = CALLS["advapi32!OpenProcessToken:LLP=L"].call(h, access, outw)
27
27
  raise WinX.new(:open_process_token) if r == 0
@@ -48,12 +48,12 @@ end
48
48
 
49
49
  class Ragweed::Wrap32::ProcessToken
50
50
  def initialize(p=nil)
51
- p ||= Wrap32::open_process(Wrap32::get_current_process_id)
52
- @h = Wrap32::open_process_token(p)
51
+ p ||= Ragweed::Wrap32::open_process(Ragweed::Wrap32::get_current_process_id)
52
+ @h = Ragweed::Wrap32::open_process_token(p)
53
53
  end
54
54
 
55
55
  def grant(name)
56
- luid = Wrap32::lookup_privilege_value(name)
57
- Wrap32::adjust_token_privileges(@h, 0, [luid, Wrap32::PrivilegeAttribute::ENABLED])
56
+ luid = Ragweed::Wrap32::lookup_privilege_value(name)
57
+ Ragweed::Wrap32::adjust_token_privileges(@h, 0, [luid, Ragweed::Wrap32::PrivilegeAttribute::ENABLED])
58
58
  end
59
59
  end
@@ -81,22 +81,22 @@ class Ragweed::Wrap32::ThreadContext
81
81
  end
82
82
 
83
83
  def self.get(h)
84
- self.new(Wrap32::get_thread_context_raw(h))
84
+ self.new(Ragweed::Wrap32::get_thread_context_raw(h))
85
85
  end
86
86
 
87
87
  def get(h)
88
- refresh(Wrap32::get_thread_context_raw(h))
88
+ refresh(Ragweed::Wrap32::get_thread_context_raw(h))
89
89
  end
90
90
 
91
91
  def set(h)
92
- Wrap32::set_thread_context_raw(h, self.to_s)
92
+ Ragweed::Wrap32::set_thread_context_raw(h, self.to_s)
93
93
  end
94
94
 
95
95
  def inspect
96
96
  body = lambda do
97
97
  FIELDS.map do |f|
98
98
  val = send(f[0])
99
- "#{f[0]}=#{val.to_s(16) rescue val.to_s}"
99
+ "#{f[0]}=#{val.to_s(16) rescue val.to_s.hexify}"
100
100
  end.join(", ")
101
101
  end
102
102
  "#<ThreadContext #{body.call}>"
@@ -119,15 +119,15 @@ CONTEXT:
119
119
  ESI: #{self.esi.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.esi)}
120
120
  EBP: #{self.ebp.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.ebp)}
121
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)}
122
+ EFL: #{self.eflags.to_s(2).rjust(32, "0")} #{Ragweed::Wrap32::EFlags.flag_dump(self.eflags)}
123
123
  EOM
124
124
  end
125
125
 
126
126
  def single_step(v=true)
127
127
  if v
128
- @eflags |= Wrap32::EFlags::TRAP
128
+ @eflags |= Ragweed::Wrap32::EFlags::TRAP
129
129
  else
130
- @eflags &= ~(Wrap32::EFlags::TRAP)
130
+ @eflags &= ~(Ragweed::Wrap32::EFlags::TRAP)
131
131
  end
132
132
  end
133
133
  end
@@ -135,7 +135,7 @@ end
135
135
  module Ragweed::Wrap32
136
136
  class << self
137
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")
138
+ 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")
139
139
  ret = CALLS["kernel32!GetThreadContext:LP=L"].call(h, ctx)
140
140
  if ret != 0
141
141
  return ctx
@@ -194,7 +194,7 @@ module Ragweed::Wrap32
194
194
  # and then resume the thread. Useful (among many other things) to sample
195
195
  # EIP values to see what the code is doing.
196
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")
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
198
  suspend_thread(h)
199
199
  ret = CALLS["kernel32!GetThreadContext:LP=L"].call(h, ctx)
200
200
  resume_thread(h)
@@ -302,9 +302,9 @@ module Ragweed::Wrap32
302
302
  h = CALLS["kernel32!CreateToolhelp32Snapshot:LL=L"].call(0x8, pid)
303
303
  if h != -1
304
304
  mi = [260+256+(8*4),0,0,0,0,0,0,0,"\x00"*256,"\x00"*260].pack("LLLLLLLLa256a260")
305
- if w32("kernel32!Module32First:LP=L").call(h, mi) != 0
305
+ if CALLS["kernel32!Module32First:LP=L"].call(h, mi) != 0
306
306
  yield str2module_info(mi)
307
- while w32("kernel32!Module32Next:LP=L").call(h, mi) != 0
307
+ while CALLS["kernel32!Module32Next:LP=L"].call(h, mi) != 0
308
308
  yield str2module_info(mi)
309
309
  end
310
310
  end
@@ -352,10 +352,10 @@ module Ragweed::Wrap32
352
352
  h = CALLS["kernel32!CreateToolhelp32Snapshot:LL=L"].call(0x4, pid)
353
353
  if h != -1
354
354
  mi = [(7*4),0,0,0,0,0,0].pack("LLLLLLL")
355
- if w32("kernel32!Thread32First:LP=L").call(h, mi) != 0
355
+ if CALLS["kernel32!Thread32First:LP=L"].call(h, mi) != 0
356
356
  ti = str2thread_info(mi)
357
357
  yield str2thread_info(mi) if ti.th32OwnerProcessID == pid
358
- while w32("kernel32!Thread32Next:LP=L").call(h, mi) != 0
358
+ while CALLS["kernel32!Thread32Next:LP=L"].call(h, mi) != 0
359
359
  ti = str2thread_info(mi)
360
360
  yield str2thread_info(mi) if ti.th32OwnerProcessID == pid
361
361
  end
@@ -5,7 +5,7 @@ module Ragweed; end
5
5
  module Ragweed::Wrap32
6
6
 
7
7
  # :stopdoc:
8
- VERSION = '0.1.7'
8
+ VERSION = '0.1.7.1'
9
9
  LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
10
10
  PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
11
11
  # :startdoc:
@@ -59,7 +59,7 @@ module Ragweed::Wraposx::KernelReturn
59
59
  module_function
60
60
  # Much like Signals.list returns a hash of the possible kernel call return values.
61
61
  def list
62
- constants.inject({}){|a, c| a.merge! c => const_get(c)}
62
+ @@list ||= constants.inject({}){|a, c| a.merge! c => const_get(c)}
63
63
  end
64
64
  end
65
65
 
@@ -2,7 +2,7 @@ module Ragweed; end
2
2
  module Ragweed::Wraposx::ThreadInfo
3
3
  class << self
4
4
  #factory method to get a ThreadInfo variant
5
- def self.get(flavor,tid)
5
+ def get(flavor,tid)
6
6
  found = false
7
7
  klass = self.constants.detect{|c| con = self.const_get(c); con.kind_of?(Class) && (flavor == con.const_get(:FLAVOR))}
8
8
  if klass.nil?
@@ -150,6 +150,22 @@ module Ragweed::Wraposx
150
150
  return t.to_a("I", count.to_s(SIZEOFINT).unpack('I_').first)
151
151
  end
152
152
 
153
+ # Decrement the target tasks suspend count
154
+ # kern_return_t task_resume
155
+ # (task_t task);
156
+ def task_resume(task)
157
+ r = CALLC["libc!task_resume:I=I"].call(task).first
158
+ raise KernelCallError.new(r) if r != 0
159
+ end
160
+
161
+ # Increment the target tasks suspend count
162
+ # kern_return_t task_suspend
163
+ # (task_t task);
164
+ def task_suspend(task)
165
+ r = CALLC["libc!task_suspend:I=I"].call(task).first
166
+ raise KernelCallError.new(r) if r != 0
167
+ end
168
+
153
169
  # Sends a signal to a process
154
170
  #
155
171
  # int
@@ -237,6 +253,36 @@ module Ragweed::Wraposx
237
253
  return nil
238
254
  end
239
255
 
256
+
257
+ # Allocates a page in the memory space of the target task.
258
+ #
259
+ # kern_return_t vm_allocate
260
+ # (vm_task_t target_task,
261
+ # vm_address_t address,
262
+ # vm_size_t size,
263
+ # boolean_t anywhere);
264
+ #
265
+ def vm_allocate(task, address, size, anywhere)
266
+ addr = int_to_intptr(address)
267
+ anywhere = anywhere ? 1 : 0
268
+ r = CALLS["libc!vm_allocate:IPII=I"].call(task,addr,size,anywhere).first
269
+ raise KernelCallError.new(r) if r != 0
270
+ addr.ptr
271
+ end
272
+
273
+ # deallocates a page in the memoryspace of target task.
274
+ #
275
+ # kern_return_t vm_deallocate
276
+ # (vm_task_t target_task,
277
+ # vm_address_t address,
278
+ # vm_size_t size);
279
+ #
280
+ def vm_deallocate(task,address,size)
281
+ addr = int_to_intptr(address)
282
+ r = CALLS["libc!vm_deallocate:IPI=I"].call(task, addr, size).first
283
+ raise KernelCallError.new(r) if r != 0
284
+ end
285
+
240
286
  # Resumes a suspended thread by id.
241
287
  #
242
288
  # kern_return_t thread_resume
@@ -334,6 +380,12 @@ module Ragweed::Wraposx
334
380
  raise SystemCallError.new("sysctl", DL.last_error) if (r != 0 and DL.last_error != Errno::ENOMEM::Errno)
335
381
  return [ret,oldlenp.to_str(SIZEOFINT).unpack("I_").first]
336
382
  end
383
+
384
+ # int
385
+ # nlist(const char *filename, struct nlist *nl)
386
+ def nlist(filename)
387
+
388
+ end
337
389
 
338
390
  # Changes execution to file in path with *args as though called from command line.
339
391
  #
@@ -348,6 +400,17 @@ module Ragweed::Wraposx
348
400
  raise SystemCallError.new("execv", DL.last_error) if r == -1
349
401
  return r
350
402
  end
403
+
404
+ def int_to_intptr(i)
405
+ case i
406
+ when Integer
407
+ return [i].pack("I").to_ptr
408
+ when DL::PtrData
409
+ return i
410
+ else
411
+ raise ArgumentError, "Not an Integer"
412
+ end
413
+ end
351
414
  end
352
415
  end
353
416