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.
@@ -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
- (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
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
- 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(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
- def get(h)
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")} #{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)}
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
- end
100
+ end
125
101
 
126
- def single_step(v=true)
127
- if v
128
- @eflags |= Ragweed::Wrap32::EFlags::TRAP
129
- else
130
- @eflags &= ~(Ragweed::Wrap32::EFlags::TRAP)
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 get_thread_context_raw(h)
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
- ret = CALLS["kernel32!GetThreadContext:LP=L"].call(h, ctx)
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 set_thread_context_raw(h, c)
148
- buf = c.to_s
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