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,203 +1,680 @@
1
+ # 127 ((x == x86_THREAD_STATE32) || \
2
+ # 128 (x == x86_FLOAT_STATE32) || \
3
+ # 129 (x == x86_EXCEPTION_STATE32) || \
4
+ # 130 (x == x86_DEBUG_STATE32) || \
5
+ # 131 (x == x86_THREAD_STATE64) || \
6
+ # 132 (x == x86_FLOAT_STATE64) || \
7
+ # 133 (x == x86_EXCEPTION_STATE64) || \
8
+ # 134 (x == x86_DEBUG_STATE64) || \
9
+ # 135 (x == x86_THREAD_STATE) || \
10
+ # 136 (x == x86_FLOAT_STATE) || \
11
+ # 137 (x == x86_EXCEPTION_STATE) || \
12
+ # 138 (x == x86_DEBUG_STATE) || \
13
+
1
14
  module Ragweed; end
2
- module Ragweed::Wraposx
3
- module EFlags
4
- CARRY = 0x1
5
- X0 = 0x2
6
- PARITY = 0x4
7
- X1 = 0x8
8
- ADJUST = 0x10
9
- X2 = 0x20
10
- ZERO = 0x40
11
- SIGN = 0x80
12
- TRAP = 0x100
13
- INTERRUPT = 0x200
14
- DIRECTION = 0x400
15
- OVERFLOW = 0x800
16
- IOPL1 = 0x1000
17
- IOPL2 = 0x2000
18
- NESTEDTASK = 0x4000
19
- X3 = 0x8000
20
- RESUME = 0x10000
21
- V86MODE = 0x20000
22
- ALIGNCHECK = 0x40000
23
- VINT = 0x80000
24
- VINTPENDING = 0x100000
25
- CPUID = 0x200000
15
+ module Ragweed::Wraposx::ThreadContext
16
+
17
+ X86_THREAD_STATE32 = 1
18
+ X86_FLOAT_STATE32 = 2
19
+ X86_EXCEPTION_STATE32 = 3
20
+ X86_DEBUG_STATE32 = 10
21
+ X86_THREAD_STATE64 = 4
22
+ X86_FLOAT_STATE64 = 5
23
+ X86_EXCEPTION_STATE64 = 6
24
+ X86_DEBUG_STATE64 = 11
25
+ # factory requests (return 32 or 64 bit structure)
26
+ X86_THREAD_STATE = 7
27
+ X86_FLOAT_STATE = 8
28
+ X86_EXCEPTION_STATE = 9
29
+ X86_DEBUG_STATE = 12
30
+ THREAD_STATE_NONE = 13
31
+
32
+ # depricated request names
33
+ I386_THREAD_STATE = X86_THREAD_STATE32
34
+ I386_FLOAT_STATE = X86_FLOAT_STATE32
35
+ I386_EXCEPTION_STATE = X86_EXCEPTION_STATE32
36
+
37
+ # struct x86_state_hdr {
38
+ # int flavor;
39
+ # int count;
40
+ # };
41
+ class X86StateHdr < FFI::Struct
42
+ include Ragweed::FFIStructInclude
43
+ layout :flavor, :int,
44
+ :count, :int
26
45
  end
27
- end
28
46
 
29
- class Ragweed::Wraposx::ThreadContext
30
- include Ragweed
31
- (FIELDS = [ [:eax, "I"],
32
- [:ebx, "I"],
33
- [:ecx, "I"],
34
- [:edx, "I"],
35
- [:edi, "I"],
36
- [:esi, "I"],
37
- [:ebp, "I"],
38
- [:esp, "I"],
39
- [:ss, "I"],
40
- [:eflags, "I"],
41
- [:eip, "I"],
42
- [:cs, "I"],
43
- [:ds, "I"],
44
- [:es, "I"],
45
- [:fs, "I"],
46
- [:gs, "I"]]).each {|x| attr_accessor x[0]}
47
- FIELDTYPES = FIELDS.map {|x| x[1]}.join("")
48
-
49
- def initialize(str=nil)
50
- refresh(str) if str
51
- end
52
-
53
- #(re)loads the data fields from str
54
- def refresh(str)
55
- if str
56
- str.unpack(FIELDTYPES).each_with_index do |val, i|
57
- instance_variable_set "@#{ FIELDS[i][0] }".intern, val
58
- end
47
+ # _STRUCT_X86_THREAD_STATE32
48
+ # {
49
+ # unsigned int eax;
50
+ # unsigned int ebx;
51
+ # unsigned int ecx;
52
+ # unsigned int edx;
53
+ # unsigned int edi;
54
+ # unsigned int esi;
55
+ # unsigned int ebp;
56
+ # unsigned int esp;
57
+ # unsigned int ss;
58
+ # unsigned int eflags;
59
+ # unsigned int eip;
60
+ # unsigned int cs;
61
+ # unsigned int ds;
62
+ # unsigned int es;
63
+ # unsigned int fs;
64
+ # unsigned int gs;
65
+ # };
66
+ class State32 < FFI::Struct
67
+ include Ragweed::FFIStructInclude
68
+ FLAVOR = 1
69
+ layout :eax, :uint,
70
+ :ebx, :uint,
71
+ :ecx, :uint,
72
+ :edx, :uint,
73
+ :edi, :uint,
74
+ :esi, :uint,
75
+ :ebp, :uint,
76
+ :esp, :uint,
77
+ :ss, :uint,
78
+ :eflags, :uint,
79
+ :eip, :uint,
80
+ :cs, :uint,
81
+ :ds, :uint,
82
+ :es, :uint,
83
+ :fs, :uint,
84
+ :gs, :uint
85
+
86
+ module Flags
87
+ CARRY = 0x1
88
+ X0 = 0x2
89
+ PARITY = 0x4
90
+ X1 = 0x8
91
+ ADJUST = 0x10
92
+ X2 = 0x20
93
+ ZERO = 0x40
94
+ SIGN = 0x80
95
+ TRAP = 0x100
96
+ INTERRUPT = 0x200
97
+ DIRECTION = 0x400
98
+ OVERFLOW = 0x800
99
+ IOPL1 = 0x1000
100
+ IOPL2 = 0x2000
101
+ NESTEDTASK = 0x4000
102
+ X3 = 0x8000
103
+ RESUME = 0x10000
104
+ V86MODE = 0x20000
105
+ ALIGNCHECK = 0x40000
106
+ VINT = 0x80000
107
+ VINTPENDING = 0x100000
108
+ CPUID = 0x200000
109
+ end
110
+
111
+ def dump(&block)
112
+ maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
113
+ maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
114
+
115
+ string =<<EOM
116
+ -----------------------------------------------------------------------
117
+ CONTEXT:
118
+ EIP: #{self.eip.to_s(16).rjust(8, "0")} #{maybe_dis.call(self.eip)}
119
+
120
+ EAX: #{self.eax.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.eax)}
121
+ EBX: #{self.ebx.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.ebx)}
122
+ ECX: #{self.ecx.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.ecx)}
123
+ EDX: #{self.edx.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.edx)}
124
+ EDI: #{self.edi.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.edi)}
125
+ ESI: #{self.esi.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.esi)}
126
+ EBP: #{self.ebp.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.ebp)}
127
+ ESP: #{self.esp.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.esp)}
128
+ EFL: #{self.eflags.to_s(2).rjust(32, "0")} #{Flags.flag_dump(self.eflags)}
129
+ EOM
130
+ end
131
+
132
+ # sets/clears the TRAP flag
133
+ def single_step(v=true)
134
+ if v
135
+ self.eflags |= Flags::TRAP
136
+ else
137
+ self.eflags &= ~(Flags::TRAP)
138
+ end
139
+ end
140
+ end
141
+
142
+ # _STRUCT_X86_THREAD_STATE64
143
+ # {
144
+ # __uint64_t rax;
145
+ # __uint64_t rbx;
146
+ # __uint64_t rcx;
147
+ # __uint64_t rdx;
148
+ # __uint64_t rdi;
149
+ # __uint64_t rsi;
150
+ # __uint64_t rbp;
151
+ # __uint64_t rsp;
152
+ # __uint64_t r8;
153
+ # __uint64_t r9;
154
+ # __uint64_t r10;
155
+ # __uint64_t r11;
156
+ # __uint64_t r12;
157
+ # __uint64_t r13;
158
+ # __uint64_t r14;
159
+ # __uint64_t r15;
160
+ # __uint64_t rip;
161
+ # __uint64_t rflags;
162
+ # __uint64_t cs;
163
+ # __uint64_t fs;
164
+ # __uint64_t gs;
165
+ # };
166
+ class State64 < FFI::Struct
167
+ include Ragweed::FFIStructInclude
168
+ FLAVOR = 4
169
+ layout :rax, :uint64,
170
+ :rbx, :uint64,
171
+ :rcx, :uint64,
172
+ :rdx, :uint64,
173
+ :rdi, :uint64,
174
+ :rsi, :uint64,
175
+ :rbp, :uint64,
176
+ :rsp, :uint64,
177
+ :r8, :uint64,
178
+ :r9, :uint64,
179
+ :r10, :uint64,
180
+ :r11, :uint64,
181
+ :r12, :uint64,
182
+ :r13, :uint64,
183
+ :r14, :uint64,
184
+ :r15, :uint64,
185
+ :rip, :uint64,
186
+ :rflags, :uint64,
187
+ :cs, :uint64,
188
+ :fs, :uint64,
189
+ :gs, :uint64,
190
+
191
+ module Flags
192
+ CARRY = 0x1
193
+ X0 = 0x2
194
+ PARITY = 0x4
195
+ X1 = 0x8
196
+ ADJUST = 0x10
197
+ X2 = 0x20
198
+ ZERO = 0x40
199
+ SIGN = 0x80
200
+ TRAP = 0x100
201
+ INTERRUPT = 0x200
202
+ DIRECTION = 0x400
203
+ OVERFLOW = 0x800
204
+ IOPL1 = 0x1000
205
+ IOPL2 = 0x2000
206
+ NESTEDTASK = 0x4000
207
+ X3 = 0x8000
208
+ RESUME = 0x10000
209
+ V86MODE = 0x20000
210
+ ALIGNCHECK = 0x40000
211
+ VINT = 0x80000
212
+ VINTPENDING = 0x100000
213
+ CPUID = 0x200000
214
+ end
215
+
216
+ def dump(&block)
217
+ maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
218
+ maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
219
+
220
+ string =<<EOM
221
+ -----------------------------------------------------------------------
222
+ CONTEXT:
223
+ RIP: #{self.rip.to_s(16).rjust(16, "0")} #{maybe_dis.call(self.eip)}
224
+
225
+ RAX: #{self.rax.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.eax)}
226
+ RBX: #{self.rbx.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.ebx)}
227
+ RCX: #{self.rcx.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.ecx)}
228
+ RDX: #{self.rdx.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.edx)}
229
+ RDI: #{self.rdi.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.edi)}
230
+ RSI: #{self.rsi.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.esi)}
231
+ RBP: #{self.rbp.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.ebp)}
232
+ RSP: #{self.rsp.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.esp)}
233
+ RFL: #{(self.rflags & 0xffffffff).to_s(2).rjust(32, "0")} #{Flags.flag_dump(self.rflags & 0xffffffff)}
234
+ EOM
235
+ end
236
+
237
+ # sets/clears the TRAP flag
238
+ def single_step(v=true)
239
+ if v
240
+ @rflags |= Flags::TRAP
241
+ else
242
+ @rflags &= ~(Flags::TRAP)
243
+ end
59
244
  end
60
245
  end
61
246
 
62
- def to_s
63
- FIELDS.map {|f| send(f[0])}.pack(FIELDTYPES)
247
+ class UnionThreadState < FFI::Union
248
+ include Ragweed::FFIStructInclude
249
+ layout :ts32, Ragweed::Wraposx::ThreadContext::State32,
250
+ :ts64, Ragweed::Wraposx::ThreadContext::State64
64
251
  end
65
252
 
66
- def self.get(h)
67
- Wraposx::thread_suspend(h)
68
- r = self.new(Wraposx::thread_get_state_raw(h))
69
- Wraposx::thread_resume(h)
70
- return r
253
+ class State < FFI::Struct
254
+ include Ragweed::FFIStructInclude
255
+ FLAVOR = 7
256
+ layout :tsh, Ragweed::Wraposx::ThreadContext::X86StateHdr,
257
+ :uts, Ragweed::Wraposx::ThreadContext::UnionThreadState
71
258
  end
72
259
 
73
- def get(h)
74
- Wraposx::thread_suspend(h)
75
- r = refresh(Wraposx::thread_get_state_raw(h))
76
- Wraposx::thread_resume(h)
77
- return r
260
+ # _STRUCT_X86_DEBUG_STATE32
261
+ # {
262
+ # unsigned int dr0;
263
+ # unsigned int dr1;
264
+ # unsigned int dr2;
265
+ # unsigned int dr3;
266
+ # unsigned int dr4;
267
+ # unsigned int dr5;
268
+ # unsigned int dr6;
269
+ # unsigned int dr7;
270
+ # };
271
+ class Debug32 < FFI::Struct
272
+ include Ragweed::FFIStructInclude
273
+ FLAVOR = 10
274
+ layout :dr0, :uint,
275
+ :dr1, :uint,
276
+ :dr2, :uint,
277
+ :dr3, :uint,
278
+ :dr4, :uint,
279
+ :dr5, :uint,
280
+ :dr6, :uint,
281
+ :dr7, :uint
282
+
283
+ def dump(&block)
284
+ maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
285
+ maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
286
+
287
+ string =<<EOM
288
+ -----------------------------------------------------------------------
289
+ CONTEXT:
290
+ DR0: #{self.dr0.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.dr0)}
291
+ DR1: #{self.dr1.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.dr1)}
292
+ DR2: #{self.dr2.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.dr2)}
293
+ DR3: #{self.dr3.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.dr3)}
294
+ DR4: #{self.dr4.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.dr4)}
295
+ DR5: #{self.dr5.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.dr5)}
296
+ DR6: #{self.dr6.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.dr6)}
297
+ DR7: #{self.dr7.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.dr7)}
298
+ EOM
299
+ end
78
300
  end
79
301
 
80
- def set(h)
81
- Wraposx::thread_suspend(h)
82
- r = Wraposx::thread_set_state_raw(h, self.to_s)
83
- Wraposx::thread_resume(h)
84
- return
302
+ # _STRUCT_X86_DEBUG_STATE64
303
+ # {
304
+ # __uint64_t dr0;
305
+ # __uint64_t dr1;
306
+ # __uint64_t dr2;
307
+ # __uint64_t dr3;
308
+ # __uint64_t dr4;
309
+ # __uint64_t dr5;
310
+ # __uint64_t dr6;
311
+ # __uint64_t dr7;
312
+ # };
313
+ class Debug64 < FFI::Struct
314
+ include Ragweed::FFIStructInclude
315
+ FLAVOR = 11
316
+ layout :dr0, :uint64,
317
+ :dr1, :uint64,
318
+ :dr2, :uint64,
319
+ :dr3, :uint64,
320
+ :dr4, :uint64,
321
+ :dr5, :uint64,
322
+ :dr6, :uint64,
323
+ :dr7, :uint64
324
+
325
+ def dump(&block)
326
+ maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
327
+ maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
328
+
329
+ string =<<EOM
330
+ -----------------------------------------------------------------------
331
+ CONTEXT:
332
+ DR0: #{self.dr0.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.dr0)}
333
+ DR1: #{self.dr1.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.dr1)}
334
+ DR2: #{self.dr2.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.dr2)}
335
+ DR3: #{self.dr3.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.dr3)}
336
+ DR4: #{self.dr4.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.dr4)}
337
+ DR5: #{self.dr5.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.dr5)}
338
+ DR6: #{self.dr6.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.dr6)}
339
+ DR7: #{self.dr7.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.dr7)}
340
+ EOM
341
+ end
342
+ end
343
+
344
+ class UnionDebugState < FFI::Union
345
+ include Ragweed::FFIStructInclude
346
+ layout :ds32, Ragweed::Wraposx::ThreadContext::Debug32,
347
+ :ds64, Ragweed::Wraposx::ThreadContext::Debug64
348
+ end
349
+
350
+ class Debug < FFI::Struct
351
+ include Ragweed::FFIStructInclude
352
+ FLAVOR = 12
353
+ layout :dsh, Ragweed::Wraposx::ThreadContext::X86StateHdr,
354
+ :uds, Ragweed::Wraposx::ThreadContext::UnionDebugState
355
+ end
356
+
357
+ # _STRUCT_X86_EXCEPTION_STATE32
358
+ # {
359
+ # unsigned int trapno;
360
+ # unsigned int err;
361
+ # unsigned int faultvaddr;
362
+ # };
363
+ class Exception32 < FFI::Struct
364
+ include Ragweed::FFIStructInclude
365
+ FLAVOR = 3
366
+ layout :trapno, :uint,
367
+ :err, :uint,
368
+ :faltvaddr, :uint
369
+
370
+ def dump(&block)
371
+ maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
372
+ maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
373
+
374
+ string =<<EOM
375
+ -----------------------------------------------------------------------
376
+ CONTEXT:
377
+ trapno: #{self.trapno.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.trapno)}
378
+ err: #{self.err.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.err)}
379
+ faultvaddr: #{self.faultvaddr.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.faultvaddr)}
380
+ EOM
381
+ end
85
382
  end
86
383
 
87
- def inspect
88
- body = lambda do
89
- FIELDS.map do |f|
90
- "#{f[0]}=#{send(f[0]).to_s(16)}"
91
- end.join(", ")
384
+ # _STRUCT_X86_EXCEPTION_STATE64
385
+ # {
386
+ # unsigned int trapno;
387
+ # unsigned int err;
388
+ # __uint64_t faultvaddr;
389
+ # };
390
+ class Exception64 < FFI::Struct
391
+ include Ragweed::FFIStructInclude
392
+ FLAVOR = 6
393
+ layout :trapno, :uint,
394
+ :err, :uint,
395
+ :faltvaddr, :uint64
396
+
397
+ def dump(&block)
398
+ maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
399
+ maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
400
+
401
+ string =<<EOM
402
+ -----------------------------------------------------------------------
403
+ CONTEXT:
404
+ trapno: #{self.trapno.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.trapno)}
405
+ err: #{self.err.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.err)}
406
+ faultvaddr: #{self.faultvaddr.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.faultvaddr)}
407
+ EOM
92
408
  end
93
- "#<ThreadContext #{body.call}>"
94
- end
95
-
96
- def dump(&block)
97
- maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
98
- maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
99
-
100
- string =<<EOM
101
- -----------------------------------------------------------------------
102
- CONTEXT:
103
- EIP: #{self.eip.to_s(16).rjust(8, "0")} #{maybe_dis.call(self.eip)}
104
-
105
- EAX: #{self.eax.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.eax)}
106
- EBX: #{self.ebx.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.ebx)}
107
- ECX: #{self.ecx.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.ecx)}
108
- EDX: #{self.edx.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.edx)}
109
- EDI: #{self.edi.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.edi)}
110
- ESI: #{self.esi.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.esi)}
111
- EBP: #{self.ebp.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.ebp)}
112
- ESP: #{self.esp.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.esp)}
113
- EFL: #{self.eflags.to_s(2).rjust(32, "0")} #{Wraposx::EFlags.flag_dump(self.eflags)}
409
+ end
410
+
411
+ class UnionExceptionState < FFI::Union
412
+ include Ragweed::FFIStructInclude
413
+ layout :es32, Ragweed::Wraposx::ThreadContext::Exception32,
414
+ :es64, Ragweed::Wraposx::ThreadContext::Exception64
415
+ end
416
+
417
+ class Exception < FFI::Struct
418
+ include Ragweed::FFIStructInclude
419
+ FLAVOR = 9
420
+ layout :esh, Ragweed::Wraposx::ThreadContext::X86StateHdr,
421
+ :ues, Ragweed::Wraposx::ThreadContext::UnionExceptionState
422
+ end
423
+
424
+ # _STRUCT_X86_FLOAT_STATE32
425
+ # {
426
+ # int fpu_reserved[2];
427
+ # _STRUCT_FP_CONTROL fpu_fcw; /* x87 FPU control word */
428
+ # _STRUCT_FP_STATUS fpu_fsw; /* x87 FPU status word */
429
+ # __uint8_t fpu_ftw; /* x87 FPU tag word */
430
+ # __uint8_t fpu_rsrv1; /* reserved */
431
+ # __uint16_t fpu_fop; /* x87 FPU Opcode */
432
+ # __uint32_t fpu_ip; /* x87 FPU Instruction Pointer offset */
433
+ # __uint16_t fpu_cs; /* x87 FPU Instruction Pointer Selector */
434
+ # __uint16_t fpu_rsrv2; /* reserved */
435
+ # __uint32_t fpu_dp; /* x87 FPU Instruction Operand(Data) Pointer offset */
436
+ # __uint16_t fpu_ds; /* x87 FPU Instruction Operand(Data) Pointer Selector */
437
+ # __uint16_t fpu_rsrv3; /* reserved */
438
+ # __uint32_t fpu_mxcsr; /* MXCSR Register state */
439
+ # __uint32_t fpu_mxcsrmask; /* MXCSR mask */
440
+ # _STRUCT_MMST_REG fpu_stmm0; /* ST0/MM0 */
441
+ # _STRUCT_MMST_REG fpu_stmm1; /* ST1/MM1 */
442
+ # _STRUCT_MMST_REG fpu_stmm2; /* ST2/MM2 */
443
+ # _STRUCT_MMST_REG fpu_stmm3; /* ST3/MM3 */
444
+ # _STRUCT_MMST_REG fpu_stmm4; /* ST4/MM4 */
445
+ # _STRUCT_MMST_REG fpu_stmm5; /* ST5/MM5 */
446
+ # _STRUCT_MMST_REG fpu_stmm6; /* ST6/MM6 */
447
+ # _STRUCT_MMST_REG fpu_stmm7; /* ST7/MM7 */
448
+ # _STRUCT_XMM_REG fpu_xmm0; /* XMM 0 */
449
+ # _STRUCT_XMM_REG fpu_xmm1; /* XMM 1 */
450
+ # _STRUCT_XMM_REG fpu_xmm2; /* XMM 2 */
451
+ # _STRUCT_XMM_REG fpu_xmm3; /* XMM 3 */
452
+ # _STRUCT_XMM_REG fpu_xmm4; /* XMM 4 */
453
+ # _STRUCT_XMM_REG fpu_xmm5; /* XMM 5 */
454
+ # _STRUCT_XMM_REG fpu_xmm6; /* XMM 6 */
455
+ # _STRUCT_XMM_REG fpu_xmm7; /* XMM 7 */
456
+ # char fpu_rsrv4[14*16]; /* reserved */
457
+ # int fpu_reserved1;
458
+ # };
459
+ class Float32 < FFI::Struct
460
+ include Ragweed::FFIStructInclude
461
+ FLAVOR = 2
462
+ layout :fpu_reserved, [:int, 2],
463
+ :fpu_fcw, Ragweed::Wraposx::FpControl,
464
+ :fpu_fsw, Ragweed::Wraposx::FpStatus,
465
+ :fpu_ftw, :uint8,
466
+ :fpu_rsrv1, :uint8,
467
+ :fpu_fop, :uint16,
468
+ :fpu_ip, :uint32,
469
+ :fpu_cs, :uint16,
470
+ :fpu_rsrv2, :uint16,
471
+ :fpu_dp, :uint32,
472
+ :fpu_ds, :uint16,
473
+ :fpu_rsrv3, :uint16,
474
+ :fpu_mxcsr, :uint32,
475
+ :fpu_mxcsrmask, :uint32,
476
+ :fpu_stmm0, Ragweed::Wraposx::MmstReg,
477
+ :fpu_stmm1, Ragweed::Wraposx::MmstReg,
478
+ :fpu_stmm2, Ragweed::Wraposx::MmstReg,
479
+ :fpu_stmm3, Ragweed::Wraposx::MmstReg,
480
+ :fpu_stmm4, Ragweed::Wraposx::MmstReg,
481
+ :fpu_stmm5, Ragweed::Wraposx::MmstReg,
482
+ :fpu_stmm6, Ragweed::Wraposx::MmstReg,
483
+ :fpu_stmm7, Ragweed::Wraposx::MmstReg,
484
+ :fpu_xmm0, Ragweed::Wraposx::XmmReg,
485
+ :fpu_xmm1, Ragweed::Wraposx::XmmReg,
486
+ :fpu_xmm2, Ragweed::Wraposx::XmmReg,
487
+ :fpu_xmm3, Ragweed::Wraposx::XmmReg,
488
+ :fpu_xmm4, Ragweed::Wraposx::XmmReg,
489
+ :fpu_xmm5, Ragweed::Wraposx::XmmReg,
490
+ :fpu_xmm6, Ragweed::Wraposx::XmmReg,
491
+ :fpu_xmm7, Ragweed::Wraposx::XmmReg,
492
+ :fpu_rsrv4, [:char, 14*16],
493
+ :fpu_reserved1, :int
494
+
495
+ def dump(&block)
496
+ maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
497
+ maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
498
+
499
+ string =<<EOM
500
+ -----------------------------------------------------------------------
501
+ CONTEXT:
502
+ trapno: #{self.trapno.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.trapno)}
503
+ err: #{self.err.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.err)}
504
+ faultvaddr: #{self.faultvaddr.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.faultvaddr)}
114
505
  EOM
506
+ end
115
507
  end
116
508
 
117
- # sets/clears the TRAP flag
118
- def single_step(v=true)
119
- if v
120
- @eflags |= Wraposx::EFlags::TRAP
121
- else
122
- @eflags &= ~(Wraposx::EFlags::TRAP)
509
+ # _STRUCT_X86_FLOAT_STATE64
510
+ # {
511
+ # int fpu_reserved[2];
512
+ # _STRUCT_FP_CONTROL fpu_fcw; /* x87 FPU control word */
513
+ # _STRUCT_FP_STATUS fpu_fsw; /* x87 FPU status word */
514
+ # __uint8_t fpu_ftw; /* x87 FPU tag word */
515
+ # __uint8_t fpu_rsrv1; /* reserved */
516
+ # __uint16_t fpu_fop; /* x87 FPU Opcode */
517
+ # /* x87 FPU Instruction Pointer */
518
+ # __uint32_t fpu_ip; /* offset */
519
+ # __uint16_t fpu_cs; /* Selector */
520
+ # __uint16_t fpu_rsrv2; /* reserved */
521
+ # /* x87 FPU Instruction Operand(Data) Pointer */
522
+ # __uint32_t fpu_dp; /* offset */
523
+ # __uint16_t fpu_ds; /* Selector */
524
+ # __uint16_t fpu_rsrv3; /* reserved */
525
+ # __uint32_t fpu_mxcsr; /* MXCSR Register state */
526
+ # __uint32_t fpu_mxcsrmask; /* MXCSR mask */
527
+ # _STRUCT_MMST_REG fpu_stmm0; /* ST0/MM0 */
528
+ # _STRUCT_MMST_REG fpu_stmm1; /* ST1/MM1 */
529
+ # _STRUCT_MMST_REG fpu_stmm2; /* ST2/MM2 */
530
+ # _STRUCT_MMST_REG fpu_stmm3; /* ST3/MM3 */
531
+ # _STRUCT_MMST_REG fpu_stmm4; /* ST4/MM4 */
532
+ # _STRUCT_MMST_REG fpu_stmm5; /* ST5/MM5 */
533
+ # _STRUCT_MMST_REG fpu_stmm6; /* ST6/MM6 */
534
+ # _STRUCT_MMST_REG fpu_stmm7; /* ST7/MM7 */
535
+ # _STRUCT_XMM_REG fpu_xmm0; /* XMM 0 */
536
+ # _STRUCT_XMM_REG fpu_xmm1; /* XMM 1 */
537
+ # _STRUCT_XMM_REG fpu_xmm2; /* XMM 2 */
538
+ # _STRUCT_XMM_REG fpu_xmm3; /* XMM 3 */
539
+ # _STRUCT_XMM_REG fpu_xmm4; /* XMM 4 */
540
+ # _STRUCT_XMM_REG fpu_xmm5; /* XMM 5 */
541
+ # _STRUCT_XMM_REG fpu_xmm6; /* XMM 6 */
542
+ # _STRUCT_XMM_REG fpu_xmm7; /* XMM 7 */
543
+ # _STRUCT_XMM_REG fpu_xmm8; /* XMM 8 */
544
+ # _STRUCT_XMM_REG fpu_xmm9; /* XMM 9 */
545
+ # _STRUCT_XMM_REG fpu_xmm10; /* XMM 10 */
546
+ # _STRUCT_XMM_REG fpu_xmm11; /* XMM 11 */
547
+ # _STRUCT_XMM_REG fpu_xmm12; /* XMM 12 */
548
+ # _STRUCT_XMM_REG fpu_xmm13; /* XMM 13 */
549
+ # _STRUCT_XMM_REG fpu_xmm14; /* XMM 14 */
550
+ # _STRUCT_XMM_REG fpu_xmm15; /* XMM 15 */
551
+ # char fpu_rsrv4[6*16]; /* reserved */
552
+ # int fpu_reserved1;
553
+ # };
554
+ class Float64 < FFI::Struct
555
+ include Ragweed::FFIStructInclude
556
+ FLAVOR = 5
557
+ layout :fpu_reserved, [:int, 2],
558
+ :fpu_fcw, Ragweed::Wraposx::FpControl,
559
+ :fpu_fsw, Ragweed::Wraposx::FpStatus,
560
+ :fpu_ftw, :uint8,
561
+ :fpu_rsrv1, :uint8,
562
+ :fpu_fop, :uint16,
563
+ :fpu_ip, :uint32,
564
+ :fpu_cs, :uint16,
565
+ :fpu_rsrv2, :uint16,
566
+ :fpu_dp, :uint32,
567
+ :fpu_ds, :uint16,
568
+ :fpu_rsrv3, :uint16,
569
+ :fpu_mxcsr, :uint32,
570
+ :fpu_mxcsrmask, :uint32,
571
+ :fpu_stmm0, Ragweed::Wraposx::MmstReg,
572
+ :fpu_stmm1, Ragweed::Wraposx::MmstReg,
573
+ :fpu_stmm2, Ragweed::Wraposx::MmstReg,
574
+ :fpu_stmm3, Ragweed::Wraposx::MmstReg,
575
+ :fpu_stmm4, Ragweed::Wraposx::MmstReg,
576
+ :fpu_stmm5, Ragweed::Wraposx::MmstReg,
577
+ :fpu_stmm6, Ragweed::Wraposx::MmstReg,
578
+ :fpu_stmm7, Ragweed::Wraposx::MmstReg,
579
+ :fpu_xmm0, Ragweed::Wraposx::XmmReg,
580
+ :fpu_xmm1, Ragweed::Wraposx::XmmReg,
581
+ :fpu_xmm2, Ragweed::Wraposx::XmmReg,
582
+ :fpu_xmm3, Ragweed::Wraposx::XmmReg,
583
+ :fpu_xmm4, Ragweed::Wraposx::XmmReg,
584
+ :fpu_xmm5, Ragweed::Wraposx::XmmReg,
585
+ :fpu_xmm6, Ragweed::Wraposx::XmmReg,
586
+ :fpu_xmm7, Ragweed::Wraposx::XmmReg,
587
+ :fpu_xmm8, Ragweed::Wraposx::XmmReg,
588
+ :fpu_xmm9, Ragweed::Wraposx::XmmReg,
589
+ :fpu_xmm10, Ragweed::Wraposx::XmmReg,
590
+ :fpu_xmm11, Ragweed::Wraposx::XmmReg,
591
+ :fpu_xmm12, Ragweed::Wraposx::XmmReg,
592
+ :fpu_xmm13, Ragweed::Wraposx::XmmReg,
593
+ :fpu_xmm14, Ragweed::Wraposx::XmmReg,
594
+ :fpu_xmm15, Ragweed::Wraposx::XmmReg,
595
+ :fpu_rsrv4, [:char, 6*16],
596
+ :fpu_reserved1, :int
597
+
598
+
599
+ def dump(&block)
600
+ maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
601
+ maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
602
+
603
+ string =<<EOM
604
+ -----------------------------------------------------------------------
605
+ CONTEXT:
606
+ trapno: #{self.trapno.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.trapno)}
607
+ err: #{self.err.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.err)}
608
+ faultvaddr: #{self.faultvaddr.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.faultvaddr)}
609
+ EOM
123
610
  end
124
611
  end
612
+
613
+ class UnionFloatState < FFI::Union
614
+ include Ragweed::FFIStructInclude
615
+ layout :fs32, Ragweed::Wraposx::ThreadContext::Float32,
616
+ :fs64, Ragweed::Wraposx::ThreadContext::Float64
617
+ end
618
+
619
+ class Float < FFI::Struct
620
+ include Ragweed::FFIStructInclude
621
+ FLAVOR = 8
622
+ layout :fsh, Ragweed::Wraposx::ThreadContext::X86StateHdr,
623
+ :ufs, Ragweed::Wraposx::ThreadContext::UnionFloatState
624
+ end
625
+
626
+ FLAVORS = {
627
+ X86_THREAD_STATE32 => {:size => 64, :count =>16, :class => State32},
628
+ X86_FLOAT_STATE32 => {:size => 64, :count =>16, :class => Float32},
629
+ X86_EXCEPTION_STATE32 => {:size => 12, :count =>3, :class => Exception32},
630
+ X86_DEBUG_STATE32 => {:size => 64, :count =>8, :class => Debug32},
631
+ X86_THREAD_STATE64 => {:size => 168, :count =>42, :class => State64},
632
+ X86_FLOAT_STATE64 => {:size => 64, :count =>16, :class => Float64},
633
+ X86_EXCEPTION_STATE64 => {:size => 16, :count =>4, :class => Exception64},
634
+ X86_DEBUG_STATE64 => {:size => 128, :count =>16, :class => Debug64},
635
+ X86_THREAD_STATE => {:size => 176, :count =>44, :class => State},
636
+ X86_FLOAT_STATE => {:size => 64, :count =>16, :class => Float},
637
+ X86_EXCEPTION_STATE => {:size => 24, :count =>6, :class => Exception},
638
+ X86_DEBUG_STATE => {:size => 136, :count =>18, :class => Debug}
639
+ }
125
640
  end
126
641
 
127
642
  module Ragweed::Wraposx
128
643
 
129
- # FIXME - constants need to be in separate sub modules
130
- # TODO - move to class based implementation a la region_info
131
- # define i386_THREAD_STATE_COUNT ((mach_msg_type_number_t)( sizeof (i386_thread_state_t) / sizeof (int) ))
132
- # i386_thread_state_t is a struct w/ 16 uint
133
- I386_THREAD_STATE_COUNT = 16
134
- I386_THREAD_STATE = 1
135
- REGISTER_SYMS = [:eax,:ebx,:ecx,:edx,:edi,:esi,:ebp,:esp,:ss,:eflags,:eip,:cs,:ds,:es,:fs,:gs]
644
+ module Libc
645
+ extend FFI::Library
646
+ ffi_lib FFI::Library::LIBC
647
+ attach_function :thread_get_state, [:thread_act_t, :thread_state_flavor_t, :pointer, :mach_msg_type_number_t], :kern_return_t
648
+ attach_function :thread_set_state, [:thread_act_t, :thread_state_flavor_t, :pointer, :mach_msg_type_number_t], :kern_return_t
649
+ end
136
650
 
137
651
  class << self
138
-
139
- # Returns a Hash of the thread's registers given a thread id.
652
+ # Returns a thread's registers for given a thread id
140
653
  #
141
654
  # kern_return_t thread_get_state
142
655
  # (thread_act_t target_thread,
143
656
  # thread_state_flavor_t flavor,
144
657
  # thread_state_t old_state,
145
658
  # mach_msg_type_number_t old_state_count);
146
- def thread_get_state(thread)
147
- state_arr = ("\x00"*SIZEOFINT*I386_THREAD_STATE_COUNT).to_ptr
148
- count = ([I386_THREAD_STATE_COUNT].pack("I_")).to_ptr
149
- r = CALLS["libc!thread_get_state:IIPP=I"].call(thread, I386_THREAD_STATE, state_arr, count).first
659
+ def thread_get_state(thread,flavor)
660
+ state = FFI::MemoryPointer.new Ragweed::Wraposx::ThreadContext::FLAVOR[flavor][:class], 1
661
+ count = FFI::MemoryPointer.new(:int, 1).write_int Ragweed::Wraposx::ThreadContext::FLAVOR[flavor][:count]
662
+ r = Libc.thread_get_state(thread, flavor, state, count)
150
663
  raise KernelCallError.new(:thread_get_state, r) if r != 0
151
- r = state_arr.to_s(I386_THREAD_STATE_COUNT*SIZEOFINT).unpack("I_"*I386_THREAD_STATE_COUNT)
152
- regs = Hash.new
153
- I386_THREAD_STATE_COUNT.times do |i|
154
- regs[REGISTER_SYMS[i]] = r[i]
155
- end
156
- return regs
157
- end
158
-
159
- # Returns string representation of a thread's registers for unpacking given a thread id
160
- #
161
- # kern_return_t thread_get_state
162
- # (thread_act_t target_thread,
163
- # thread_state_flavor_t flavor,
164
- # thread_state_t old_state,
165
- # mach_msg_type_number_t old_state_count);
166
- def thread_get_state_raw(thread)
167
- state_arr = ("\x00"*SIZEOFINT*I386_THREAD_STATE_COUNT).to_ptr
168
- count = ([I386_THREAD_STATE_COUNT].pack("I_")).to_ptr
169
- r = CALLS["libc!thread_get_state:IIPP=I"].call(thread, I386_THREAD_STATE, state_arr, count).first
170
- raise KernelCallError.new(:thread_get_state, r) if r != 0
171
- return state_arr.to_s(I386_THREAD_STATE_COUNT*SIZEOFINT)
172
- end
173
-
174
- # Sets the register state of thread from a Hash containing it's values.
175
- #
176
- # kern_return_t thread_set_state
177
- # (thread_act_t target_thread,
178
- # thread_state_flavor_t flavor,
179
- # thread_state_t new_state,
180
- # target_thread new_state_count);
181
- def thread_set_state(thread, state)
182
- s = Array.new
183
- I386_THREAD_STATE_COUNT.times do |i|
184
- s << state[REGISTER_SYMS[i]]
185
- end
186
- s = s.pack("I_"*I386_THREAD_STATE_COUNT).to_ptr
187
- r = CALLS["libc!thread_set_state:IIPI=I"].call(thread, I386_THREAD_STATE, s, I386_THREAD_STATE_COUNT).first
188
- raise KernelCallError.new(:thread_set_state, r) if r!= 0
664
+ Ragweed::Wraposx::ThreadContext::FLAVOR[flavor][:class].new state
189
665
  end
190
666
 
191
- # Sets the register state of thread from a packed string containing it's values.
667
+ # Sets the register state of thread.
192
668
  #
193
669
  # kern_return_t thread_set_state
194
670
  # (thread_act_t target_thread,
195
671
  # thread_state_flavor_t flavor,
196
672
  # thread_state_t new_state,
197
- # target_thread new_state_count);
198
- def thread_set_state_raw(thread, state)
199
- r = CALLS["libc!thread_set_state:IIPI=I"].call(thread, I386_THREAD_STATE, state.to_ptr, I386_THREAD_STATE_COUNT).first
673
+ # mach_msg_number_t new_state_count);
674
+ def thread_set_state(thread, flavor, state)
675
+ r = Libc.thread_set_state(thread, flavor, state.to_ptr, ThreadContext::FLAVORS[flavor][:count])
200
676
  raise KernelCallError.new(:thread_set_state, r) if r!= 0
677
+ Ragweed::Wraposx::ThreadContext::FLAVOR[flavor][:class].new state
201
678
  end
202
679
  end
203
680
  end