tduehr-ragweed 0.1.6 → 0.1.7
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/History.txt +4 -0
- data/Rakefile +4 -2
- data/examples/tux-example.rb +6 -7
- data/lib/ragweed/blocks.rb +1 -1
- data/lib/ragweed/debugger32.rb +1 -1
- data/lib/ragweed/debuggerosx.rb +3 -3
- data/lib/ragweed/debuggertux.rb +1 -2
- data/lib/ragweed/rasm/isa.rb +77 -52
- data/lib/ragweed/rasm.rb +1 -1
- data/lib/ragweed/utils.rb +26 -0
- data/lib/ragweed/wrap32.rb +1 -1
- data/lib/ragweed/wraposx/constants.rb +23 -2
- data/lib/ragweed/wraposx/region_info.rb +27 -16
- data/lib/ragweed/wraposx/thread_info.rb +4 -2
- data/lib/ragweed/wraposx.rb +2 -2
- data/lib/ragweed/wraptux.rb +1 -1
- data/lib/ragweed.rb +4 -4
- metadata +1 -2
- data/lib/ragweed/rasm/util.rb +0 -26
data/History.txt
CHANGED
data/Rakefile
CHANGED
@@ -19,11 +19,13 @@ require 'ragweed'
|
|
19
19
|
task :default => 'spec:run'
|
20
20
|
|
21
21
|
PROJ.name = 'ragweed'
|
22
|
+
PROJ.ignore_file = '.gitignore'
|
22
23
|
PROJ.authors = 'tduehr, tqbf, struct'
|
23
24
|
PROJ.email = 'td@matasano.com'
|
24
|
-
PROJ.
|
25
|
+
PROJ.description = 'General debugging tool written in Ruby for OSX/Win32/Linux'
|
26
|
+
PROJ.url = 'http://github.com/tduehr/ragweed/tree/master'
|
25
27
|
PROJ.version = Ragweed::VERSION
|
26
|
-
PROJ.rubyforge.name = 'ragweed'
|
28
|
+
# PROJ.rubyforge.name = 'ragweed'
|
27
29
|
|
28
30
|
PROJ.spec.opts << '--color'
|
29
31
|
|
data/examples/tux-example.rb
CHANGED
@@ -4,21 +4,20 @@
|
|
4
4
|
|
5
5
|
require 'pp'
|
6
6
|
require 'ragweed'
|
7
|
-
require 'debuggertux'
|
8
|
-
include Ragweed
|
9
7
|
|
10
8
|
pid = Ragweed::Debuggertux.find_by_regex(/gcalctool/)
|
11
9
|
|
12
|
-
|
10
|
+
begin
|
13
11
|
t = Ragweed::Debuggertux.threads(pid)
|
14
|
-
puts "
|
12
|
+
puts "Available pid/tdpids\n"
|
15
13
|
t.each do |h| puts h end
|
14
|
+
puts "Which thread do you want to attach to?"
|
16
15
|
pid = STDIN.gets.chomp.to_i
|
17
16
|
|
18
17
|
d = Ragweed::Debuggertux.new(pid)
|
19
18
|
d.attach
|
20
19
|
d.continue
|
21
20
|
catch(:throw) { d.loop }
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
rescue
|
22
|
+
puts "Maybe your PID is wrong?"
|
23
|
+
end
|
data/lib/ragweed/blocks.rb
CHANGED
data/lib/ragweed/debugger32.rb
CHANGED
data/lib/ragweed/debuggerosx.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require ::File.join(::File.dirname(__FILE__),'wraposx')
|
2
2
|
|
3
3
|
module Ragweed; end
|
4
4
|
|
@@ -397,10 +397,10 @@ class Ragweed::Debuggerosx
|
|
397
397
|
# Extended and Top info flavors are included in case Apple re implements them
|
398
398
|
when :extended
|
399
399
|
warn "VM Region Extended Info not implemented by Apple. Returning RegionBasicInfo"
|
400
|
-
return Ragweed::Wraposx::
|
400
|
+
return Ragweed::Wraposx::RegionExtendedInfo.get(@task, addr)
|
401
401
|
when :top
|
402
402
|
warn "VM Region Top Info not implemented be Apple. Returning RegionBasicInfo"
|
403
|
-
return Ragweed::Wraposx::
|
403
|
+
return Ragweed::Wraposx::RegionTopInfo.get(@task, addr)
|
404
404
|
else
|
405
405
|
warn "Unknown flavor requested. Returning RegionBasicInfo."
|
406
406
|
return Ragweed::Wraposx::RegionBasicInfo.get(@task, addr)
|
data/lib/ragweed/debuggertux.rb
CHANGED
data/lib/ragweed/rasm/isa.rb
CHANGED
@@ -3,12 +3,13 @@
|
|
3
3
|
# Rasm: a half-assed X86 assembler.
|
4
4
|
#
|
5
5
|
# Rasm implements a small subset of the X86 instruction set, and only in
|
6
|
-
# simple encodings.
|
6
|
+
# simple encodings.
|
7
7
|
#
|
8
8
|
# However, Rasm implements enough X86 to do interesting things. I wrote it
|
9
9
|
# to inject trampoline functions and detours into remote processes. This
|
10
|
-
# is Ruby code; you'd never use it where performance matters. It's not
|
10
|
+
# is Ruby code; you'd never use it where performance matters. It's not
|
11
11
|
# enough to write a decent compiler, but it's enough to fuck up programs.
|
12
|
+
module Ragweed; end
|
12
13
|
module Ragweed::Rasm
|
13
14
|
class NotImp < RuntimeError; end
|
14
15
|
class Insuff < RuntimeError; end
|
@@ -39,6 +40,8 @@ module Ragweed::Rasm
|
|
39
40
|
(rc1 << 8|rc2)
|
40
41
|
end
|
41
42
|
|
43
|
+
def scaled?; @scale and @scale > 0; end
|
44
|
+
def combined?; @combined; end
|
42
45
|
def reg1
|
43
46
|
if combined?
|
44
47
|
self.class.new((code>>8)&0xff)
|
@@ -68,7 +71,7 @@ module Ragweed::Rasm
|
|
68
71
|
elsif x.kind_of? Register
|
69
72
|
ret = clone
|
70
73
|
ret.combined = true
|
71
|
-
ret.indir = 1
|
74
|
+
ret.indir = 1
|
72
75
|
ret.scale = x.scale
|
73
76
|
ret.code = self.class.comb(ret.code, x.code)
|
74
77
|
return ret
|
@@ -101,19 +104,16 @@ module Ragweed::Rasm
|
|
101
104
|
end
|
102
105
|
|
103
106
|
return self
|
104
|
-
end
|
105
|
-
|
106
|
-
def scaled?; @scale and @scale > 0; end
|
107
|
-
def combined?; @combined; end
|
107
|
+
end
|
108
108
|
|
109
|
-
def self.eax(opts={}); Eax.clone.regopts opts; end
|
110
|
-
def self.ecx(opts={}); Ecx.clone.regopts opts; end
|
111
|
-
def self.edx(opts={}); Edx.clone.regopts opts; end
|
112
|
-
def self.ebx(opts={}); Ebx.clone.regopts opts; end
|
113
|
-
def self.esp(opts={}); Esp.clone.regopts opts; end
|
114
|
-
def self.ebp(opts={}); Ebp.clone.regopts opts; end
|
115
|
-
def self.esi(opts={}); Esi.clone.regopts opts; end
|
116
|
-
def self.edi(opts={}); Edi.clone.regopts opts; end
|
109
|
+
def self.eax(opts={}); Eax.clone.regopts opts; end
|
110
|
+
def self.ecx(opts={}); Ecx.clone.regopts opts; end
|
111
|
+
def self.edx(opts={}); Edx.clone.regopts opts; end
|
112
|
+
def self.ebx(opts={}); Ebx.clone.regopts opts; end
|
113
|
+
def self.esp(opts={}); Esp.clone.regopts opts; end
|
114
|
+
def self.ebp(opts={}); Ebp.clone.regopts opts; end
|
115
|
+
def self.esi(opts={}); Esi.clone.regopts opts; end
|
116
|
+
def self.edi(opts={}); Edi.clone.regopts opts; end
|
117
117
|
|
118
118
|
def initialize(code, opts={})
|
119
119
|
@combined = false
|
@@ -132,7 +132,7 @@ module Ragweed::Rasm
|
|
132
132
|
@disp = disp
|
133
133
|
@indir = true
|
134
134
|
end
|
135
|
-
end
|
135
|
+
end
|
136
136
|
|
137
137
|
## ------------------------------------------------------------------------
|
138
138
|
|
@@ -146,7 +146,7 @@ module Ragweed::Rasm
|
|
146
146
|
Esp = Register.new(Register::ESP)
|
147
147
|
Ebp = Register.new(Register::EBP)
|
148
148
|
Esi = Register.new(Register::ESI)
|
149
|
-
Edi = Register.new(Register::EDI)
|
149
|
+
Edi = Register.new(Register::EDI)
|
150
150
|
def eax(opts={}); Register.eax opts; end
|
151
151
|
def ecx(opts={}); Register.ecx opts; end
|
152
152
|
def edx(opts={}); Register.edx opts; end
|
@@ -167,14 +167,14 @@ module Ragweed::Rasm
|
|
167
167
|
## ------------------------------------------------------------------------
|
168
168
|
|
169
169
|
# A code fragment. Push instructions into it. You can push Label
|
170
|
-
# objects to create jump targets.
|
170
|
+
# objects to create jump targets.
|
171
171
|
class Subprogram < Array
|
172
172
|
|
173
173
|
# Patch code offsets into the instructions to replace abstract
|
174
174
|
# labels. Produces raw instruction stream.
|
175
175
|
def assemble
|
176
176
|
patches = {}
|
177
|
-
buf =
|
177
|
+
buf = Sbuf.new
|
178
178
|
|
179
179
|
each do |i|
|
180
180
|
if i.kind_of? Instruction
|
@@ -183,11 +183,11 @@ module Ragweed::Rasm
|
|
183
183
|
else
|
184
184
|
patches[i] = buf.size
|
185
185
|
end
|
186
|
-
end
|
187
|
-
|
186
|
+
end
|
187
|
+
|
188
188
|
select {|i| i.kind_of? Instruction}.each {|i| i.patch(patches)}
|
189
189
|
buf.clear!
|
190
|
-
select {|i| i.kind_of? Instruction}.each {|i|
|
190
|
+
select {|i| i.kind_of? Instruction}.each {|i|
|
191
191
|
buf.straw(i.to_s)
|
192
192
|
}
|
193
193
|
|
@@ -197,12 +197,12 @@ module Ragweed::Rasm
|
|
197
197
|
# Produce an array of insns. This is pretty much broken, because
|
198
198
|
# it doesn't pre-patch the instructions.
|
199
199
|
def disassemble
|
200
|
-
select {|i| i.kind_of? Rasm::
|
200
|
+
select {|i| i.kind_of? Rasm::Instruction}.map {|i| i.decode}
|
201
201
|
end
|
202
202
|
|
203
203
|
def dump_disassembly
|
204
|
-
disassemble.
|
205
|
-
puts "#{
|
204
|
+
disassemble.each_with_index do |insn, i|
|
205
|
+
puts "#{ i } #{ insn.mnem }"
|
206
206
|
end
|
207
207
|
end
|
208
208
|
end
|
@@ -256,21 +256,21 @@ module Ragweed::Rasm
|
|
256
256
|
v = Immed.new(v) if v.number?
|
257
257
|
end
|
258
258
|
v
|
259
|
-
end
|
259
|
+
end
|
260
260
|
|
261
261
|
def src=(v); @src = coerce(v); end
|
262
262
|
def dst=(v); @dst = coerce(v); end
|
263
263
|
|
264
|
-
# Never called directly (see subclasses below)
|
264
|
+
# Never called directly (see subclasses below)
|
265
265
|
def initialize(x=nil, y=nil)
|
266
|
-
@buf =
|
266
|
+
@buf = Sbuf.new
|
267
267
|
self.src = y
|
268
268
|
self.dst = x
|
269
269
|
@loc = nil
|
270
270
|
end
|
271
271
|
|
272
272
|
# Disassemble the instruction (mostly for testing)
|
273
|
-
def decode; Frasm::DistormDecoder.new.decode(self.to_s)[0]; end
|
273
|
+
# def decode; Frasm::DistormDecoder.new.decode(self.to_s)[0]; end
|
274
274
|
|
275
275
|
# What Subprogram#assemble uses to patch instruction locations.
|
276
276
|
# Not user-servicable
|
@@ -287,7 +287,7 @@ module Ragweed::Rasm
|
|
287
287
|
end
|
288
288
|
end
|
289
289
|
end
|
290
|
-
|
290
|
+
|
291
291
|
# Calculate ModR/M bits for the instruction; this is
|
292
292
|
# the source/destination operand encoding.
|
293
293
|
def modrm(op1, op2)
|
@@ -320,7 +320,7 @@ module Ragweed::Rasm
|
|
320
320
|
return 0xc0 + (op2.code << 3) + op1.code
|
321
321
|
end
|
322
322
|
end
|
323
|
-
|
323
|
+
|
324
324
|
def sib(indir, alt, base)
|
325
325
|
modpart = (base+4) + (alt.code << 3)
|
326
326
|
|
@@ -340,7 +340,7 @@ module Ragweed::Rasm
|
|
340
340
|
end
|
341
341
|
|
342
342
|
col = indir.reg1.code
|
343
|
-
|
343
|
+
|
344
344
|
if indir.combined?
|
345
345
|
row = indir.reg2.code
|
346
346
|
else
|
@@ -350,7 +350,7 @@ module Ragweed::Rasm
|
|
350
350
|
pp [col,row,sbase]
|
351
351
|
|
352
352
|
sibpart = sbase + (row << 3) + (col)
|
353
|
-
|
353
|
+
|
354
354
|
return (modpart.chr) + (sibpart.chr)
|
355
355
|
end
|
356
356
|
|
@@ -382,7 +382,7 @@ module Ragweed::Rasm
|
|
382
382
|
end
|
383
383
|
|
384
384
|
## ------------------------------------------------------------------------
|
385
|
-
|
385
|
+
|
386
386
|
# Jump to a relative offset (pos or neg), a register, or an address
|
387
387
|
# in memory. Can take Labels instead of values, let patch figure out
|
388
388
|
# the rest.
|
@@ -393,7 +393,7 @@ module Ragweed::Rasm
|
|
393
393
|
# no far yet
|
394
394
|
|
395
395
|
def initialize(x=nil); super x; end
|
396
|
-
|
396
|
+
|
397
397
|
def to_s
|
398
398
|
raise Insuff if not @dst
|
399
399
|
if dst_imm? or dst_lab?
|
@@ -441,7 +441,7 @@ module Ragweed::Rasm
|
|
441
441
|
|
442
442
|
# Push a register, register-addressed memory location, or immediate
|
443
443
|
# onto the stack.
|
444
|
-
class Push < Instruction
|
444
|
+
class Push < Instruction
|
445
445
|
# ff r/m
|
446
446
|
# 50+ r
|
447
447
|
# 6a imm8
|
@@ -456,7 +456,7 @@ module Ragweed::Rasm
|
|
456
456
|
if @dst.indir
|
457
457
|
add(0xff)
|
458
458
|
add(modrm(@dst, Esi.clone))
|
459
|
-
add(@dst.disp)
|
459
|
+
add(@dst.disp)
|
460
460
|
else
|
461
461
|
add(0x50 + @dst.code)
|
462
462
|
end
|
@@ -485,7 +485,7 @@ module Ragweed::Rasm
|
|
485
485
|
|
486
486
|
def to_s
|
487
487
|
raise Insuff if not @dst
|
488
|
-
|
488
|
+
|
489
489
|
if dst_reg?
|
490
490
|
add(0xff)
|
491
491
|
add(modrm(@dst, Edx.clone))
|
@@ -501,7 +501,7 @@ module Ragweed::Rasm
|
|
501
501
|
|
502
502
|
# Return; provide immediate for stack adjustment if you want.
|
503
503
|
class Ret < Instruction
|
504
|
-
# c3
|
504
|
+
# c3
|
505
505
|
# c2 imm16
|
506
506
|
|
507
507
|
def initialize( dst=nil); super dst; end
|
@@ -543,7 +543,7 @@ module Ragweed::Rasm
|
|
543
543
|
if @src.val < 0x100
|
544
544
|
add(@imp8)
|
545
545
|
add(@src.val)
|
546
|
-
else
|
546
|
+
else
|
547
547
|
add(@imp)
|
548
548
|
add(@src.val)
|
549
549
|
end
|
@@ -587,9 +587,10 @@ module Ragweed::Rasm
|
|
587
587
|
@x = Eax.clone
|
588
588
|
end
|
589
589
|
end
|
590
|
+
Addl = Add
|
590
591
|
|
591
592
|
## ------------------------------------------------------------------------
|
592
|
-
|
593
|
+
|
593
594
|
# SUB
|
594
595
|
class Sub < Arith
|
595
596
|
def initialize(*args)
|
@@ -670,7 +671,7 @@ module Ragweed::Rasm
|
|
670
671
|
|
671
672
|
# CMP is SUB + condition code
|
672
673
|
class Cmp < Instruction
|
673
|
-
# 3c imm8
|
674
|
+
# 3c imm8
|
674
675
|
# 3d imm
|
675
676
|
# 80/7 r/m8, imm8
|
676
677
|
# 81/7 r/m, imm
|
@@ -725,16 +726,16 @@ module Ragweed::Rasm
|
|
725
726
|
|
726
727
|
# Wrapper for INC and DEC, not called directly.
|
727
728
|
class IncDec < Instruction
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
729
|
+
# fe/0 r/m8
|
730
|
+
# ff/0 r/m
|
731
|
+
# 40+ (reg)
|
732
|
+
|
732
733
|
def initialize( dst=nil); super dst; end
|
733
734
|
|
734
735
|
def to_s
|
735
736
|
raise Insuff if not @dst
|
736
737
|
raise(BadArg, "need a register") if not dst_reg?
|
737
|
-
|
738
|
+
|
738
739
|
if @dst.indir
|
739
740
|
add(0xff)
|
740
741
|
add(modrm(@dst, @var))
|
@@ -748,7 +749,7 @@ module Ragweed::Rasm
|
|
748
749
|
## ------------------------------------------------------------------------
|
749
750
|
|
750
751
|
# INC memory or register
|
751
|
-
class Inc < IncDec
|
752
|
+
class Inc < IncDec
|
752
753
|
def initialize(*args)
|
753
754
|
super *args
|
754
755
|
@var = Eax.clone
|
@@ -759,7 +760,7 @@ module Ragweed::Rasm
|
|
759
760
|
## ------------------------------------------------------------------------
|
760
761
|
|
761
762
|
# DEC memory or register
|
762
|
-
class Dec < IncDec
|
763
|
+
class Dec < IncDec
|
763
764
|
def initialize(*args)
|
764
765
|
super *args
|
765
766
|
@var = Ecx.clone
|
@@ -916,7 +917,7 @@ module Ragweed::Rasm
|
|
916
917
|
# Wrapper for conditional jumps, see below
|
917
918
|
class Jcc < Instruction
|
918
919
|
|
919
|
-
def m; [nil,nil]; end
|
920
|
+
def m; [nil,nil]; end
|
920
921
|
def initialize( dst)
|
921
922
|
super dst
|
922
923
|
@short, @near = m()
|
@@ -1012,9 +1013,33 @@ module Ragweed::Rasm
|
|
1012
1013
|
class Js < Jcc; def m; [0x78, 0x88]; end; end
|
1013
1014
|
# Zero
|
1014
1015
|
class Jz < Jcc; def m; [0x74, 0x84]; end; end
|
1015
|
-
|
1016
|
+
|
1017
|
+
## ------------------------------------------------------------------------
|
1018
|
+
|
1019
|
+
class Pushf < Instruction
|
1020
|
+
# 9c pushfd
|
1021
|
+
|
1022
|
+
def initialize; end
|
1023
|
+
def to_s
|
1024
|
+
raise(TooMan, "too many arguments") if @src or @dst
|
1025
|
+
add(0x9c)
|
1026
|
+
end
|
1027
|
+
end
|
1028
|
+
|
1016
1029
|
## ------------------------------------------------------------------------
|
1017
|
-
|
1030
|
+
|
1031
|
+
class Popf < Instruction
|
1032
|
+
# 9d popfd
|
1033
|
+
|
1034
|
+
def initialize; end
|
1035
|
+
def to_s
|
1036
|
+
raise(TooMan, "too many arguments") if @src or @dst
|
1037
|
+
add(0x9d)
|
1038
|
+
end
|
1039
|
+
end
|
1040
|
+
|
1041
|
+
## ------------------------------------------------------------------------
|
1042
|
+
|
1018
1043
|
# INT 3, mostly, but will do INT X
|
1019
1044
|
class Int < Instruction
|
1020
1045
|
## cc int 3
|
data/lib/ragweed/rasm.rb
CHANGED
data/lib/ragweed/utils.rb
CHANGED
@@ -21,6 +21,19 @@ class Object
|
|
21
21
|
def mymethods
|
22
22
|
(self.methods - self.class.superclass.methods).sort
|
23
23
|
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
|
24
37
|
end
|
25
38
|
include ObjectExtensions
|
26
39
|
end
|
@@ -41,6 +54,19 @@ class String
|
|
41
54
|
return self if count == 0
|
42
55
|
slice! 0..(count-1)
|
43
56
|
end
|
57
|
+
|
58
|
+
# Convert a string into hex characters
|
59
|
+
def hexify
|
60
|
+
l = []
|
61
|
+
each_byte{|b| l << "%02x" % b}
|
62
|
+
l.join
|
63
|
+
end
|
64
|
+
|
65
|
+
# Convert a string of raw hex characters (no %'s or anything) into binary
|
66
|
+
def dehexify
|
67
|
+
(ret||="") << (me||=clone).shift(2).to_i(16).chr while not (me||=clone).empty?
|
68
|
+
return ret
|
69
|
+
end
|
44
70
|
end
|
45
71
|
|
46
72
|
class Integer
|
data/lib/ragweed/wrap32.rb
CHANGED
@@ -23,7 +23,9 @@ module Ragweed::Wraposx::Ptrace
|
|
23
23
|
end
|
24
24
|
|
25
25
|
module Ragweed::Wraposx::Signal
|
26
|
-
#the Ruby module Signal also has this information
|
26
|
+
# the Ruby module Signal also has this information.
|
27
|
+
# in reality, that is a better source since it's based on the signals
|
28
|
+
# available at the time ruby was compiled.
|
27
29
|
SIGHUP = 1 # hangup
|
28
30
|
SIGINT = 2 # interrupt
|
29
31
|
SIGQUIT = 3 # quit
|
@@ -77,13 +79,32 @@ end
|
|
77
79
|
|
78
80
|
module Ragweed::Wraposx::Vm; end
|
79
81
|
module Ragweed::Wraposx::Vm::Prot
|
80
|
-
#vm_protect permission flags for memory spaces
|
82
|
+
# vm_protect permission flags for memory spaces
|
81
83
|
READ = 0x1 #read permission
|
82
84
|
WRITE = 0x2 #write permission
|
83
85
|
EXECUTE = 0x4 #execute permission
|
84
86
|
NONE = 0x0 #no rights
|
85
87
|
ALL = 0x7 #all permissions
|
86
88
|
end
|
89
|
+
module Ragweed::Wraposx::Vm::Sm
|
90
|
+
# share mode constants
|
91
|
+
COW = 1
|
92
|
+
PRIVATE = 2
|
93
|
+
EMPTY = 3
|
94
|
+
SHARED = 4
|
95
|
+
TRUESHARED = 5
|
96
|
+
PRIVATE_ALIASED = 6
|
97
|
+
SHARED_ALIASED = 7
|
98
|
+
end
|
99
|
+
|
100
|
+
# this should be moved to an include for all wrappers
|
101
|
+
module Ragweed::Wraposx::SizeOf
|
102
|
+
INT = [1].pack("I_").size
|
103
|
+
SHORT = [1].pack("S_").size
|
104
|
+
LONG = [1].pack("L_").size
|
105
|
+
DOUBLE = [1].pack("D").size
|
106
|
+
FLOAT = [1].pack("F").size
|
107
|
+
end
|
87
108
|
|
88
109
|
module Ragweed::Wraposx::Dl
|
89
110
|
RTLD_LAZY = 0x1
|
@@ -26,9 +26,9 @@ module Ragweed::Wraposx::Vm
|
|
26
26
|
#define VM_REGION_BASIC_INFO_COUNT ((mach_msg_type_number_t) (sizeof(vm_region_basic_info_data_t)/sizeof(int)))
|
27
27
|
#define VM_REGION_EXTENDED_INFO_COUNT ((mach_msg_type_number_t) (sizeof(vm_region_extended_info_data_t)/sizeof(int)))
|
28
28
|
#define VM_REGION_TOP_INFO_COUNT ((mach_msg_type_number_t) (sizeof(vm_region_top_info_data_t)/sizeof(int)))
|
29
|
-
FLAVORS = { REGION_BASIC_INFO => {:size => 30, :count =>
|
30
|
-
REGION_EXTENDED_INFO => {:size => 32, :count =>
|
31
|
-
REGION_TOP_INFO => {:size => 17,:count =>
|
29
|
+
FLAVORS = { REGION_BASIC_INFO => {:size => 30, :count => 8},
|
30
|
+
REGION_EXTENDED_INFO => {:size => 32, :count => 8},
|
31
|
+
REGION_TOP_INFO => {:size => 17,:count => 5}
|
32
32
|
}
|
33
33
|
|
34
34
|
module Pflags
|
@@ -39,8 +39,8 @@ module Ragweed::Wraposx::Vm
|
|
39
39
|
end
|
40
40
|
|
41
41
|
# Memory region info base class.
|
42
|
-
#
|
43
|
-
#
|
42
|
+
#
|
43
|
+
# to change slightly in 0.2.0+
|
44
44
|
#
|
45
45
|
class Ragweed::Wraposx::RegionInfo
|
46
46
|
def initialize(str=nil)
|
@@ -113,7 +113,8 @@ class Ragweed::Wraposx::RegionBasicInfo < Ragweed::Wraposx::RegionInfo
|
|
113
113
|
[:offset, "L"], # The region's offset into the memory object. The region begins at this offset.
|
114
114
|
[:behavior, "i"], # Expected reference pattern for the memory.
|
115
115
|
[:user_wired_count, "S"],
|
116
|
-
[:size, "I"] # size of memory region returned
|
116
|
+
[:size, "I"], # size of memory region returned
|
117
|
+
[:base_address, "L"]
|
117
118
|
]).each {|x| attr_accessor x[0]}
|
118
119
|
|
119
120
|
def dump(&block)
|
@@ -122,7 +123,9 @@ class Ragweed::Wraposx::RegionBasicInfo < Ragweed::Wraposx::RegionInfo
|
|
122
123
|
|
123
124
|
string =<<EOM
|
124
125
|
-----------------------------------------------------------------------
|
125
|
-
INFO:
|
126
|
+
BASIC INFO:
|
127
|
+
base address: #{self.base_address.to_s(16).rjust(8, "0")}
|
128
|
+
|
126
129
|
protection: #{self.protection.to_s(2).rjust(8, "0")} #{Ragweed::Wraposx::Vm::Pflags.flag_dump(self.protection)}
|
127
130
|
max_protection: #{self.max_protection.to_s(2).rjust(8, "0")} #{Ragweed::Wraposx::Vm::Pflags.flag_dump(self.max_protection)}
|
128
131
|
inheritance: #{self.inheritance.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.inheritance)}
|
@@ -153,7 +156,8 @@ class Ragweed::Wraposx::RegionExtendedInfo < Ragweed::Wraposx::RegionInfo
|
|
153
156
|
[:shadow_depth, "S"],
|
154
157
|
[:external_pager, "C"],
|
155
158
|
[:share_mode, "C"],
|
156
|
-
[:size, "I"]
|
159
|
+
[:size, "I"],
|
160
|
+
[:base_address, "I"] ]).each {|x| attr_accessor x[0]}
|
157
161
|
|
158
162
|
def dump(&block)
|
159
163
|
maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
|
@@ -161,7 +165,9 @@ class Ragweed::Wraposx::RegionExtendedInfo < Ragweed::Wraposx::RegionInfo
|
|
161
165
|
|
162
166
|
string =<<EOM
|
163
167
|
-----------------------------------------------------------------------
|
164
|
-
INFO:
|
168
|
+
EXTENDED INFO:
|
169
|
+
base address: #{self.base_address.to_s(16).rjust(8, "0")}
|
170
|
+
|
165
171
|
protection: #{self.protection.to_s(2).rjust(8, "0")} #{Ragweed::Wraposx::Vm::Pflags.flag_dump(self.protection)}
|
166
172
|
user_tag: #{self.user_tag.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.user_tag)}
|
167
173
|
pages_resident: #{self.pages_resident.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.pages_resident)}
|
@@ -190,7 +196,8 @@ class Ragweed::Wraposx::RegionTopInfo < Ragweed::Wraposx::RegionInfo
|
|
190
196
|
[:private_pages_resident, "I"],
|
191
197
|
[:shared_pages_resident, "I"],
|
192
198
|
[:share_mode, "C"],
|
193
|
-
[:size, "I"]
|
199
|
+
[:size, "I"],
|
200
|
+
[:base_address,"I"]]).each {|x| attr_accessor x[0]}
|
194
201
|
|
195
202
|
def dump(&block)
|
196
203
|
maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
|
@@ -198,7 +205,9 @@ class Ragweed::Wraposx::RegionTopInfo < Ragweed::Wraposx::RegionInfo
|
|
198
205
|
|
199
206
|
string =<<EOM
|
200
207
|
-----------------------------------------------------------------------
|
201
|
-
INFO:
|
208
|
+
TOP INFO:
|
209
|
+
base address: #{self.base_address.to_s(16).rjust(8, "0")}
|
210
|
+
|
202
211
|
obj_id: #{self.obj_id.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.obj_id)}
|
203
212
|
ref_count: #{self.ref_count.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.ref_count)}
|
204
213
|
private_pages_resident: #{self.private_pages_resident.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.private_pages_resident)}
|
@@ -218,8 +227,9 @@ module Ragweed::Wraposx
|
|
218
227
|
|
219
228
|
# Returns a string containing the memory region information for task
|
220
229
|
# at address.
|
221
|
-
#
|
222
|
-
#
|
230
|
+
#
|
231
|
+
# The order of the elements in the returned string will change in 0.2.0+
|
232
|
+
# to match the argument order.
|
223
233
|
#
|
224
234
|
# kern_return_t vm_region
|
225
235
|
# (vm_task_t target_task,
|
@@ -230,14 +240,15 @@ module Ragweed::Wraposx
|
|
230
240
|
# mach_msg_type_number_t info_count,
|
231
241
|
# memory_object_name_t object_name);
|
232
242
|
def vm_region_raw(task, address, flavor)
|
233
|
-
info = ("\x00"*
|
243
|
+
info = ("\x00"*Vm::FLAVORS[flavor][:size]).to_ptr
|
234
244
|
count = ([Vm::FLAVORS[flavor][:count]].pack("I_")).to_ptr
|
235
245
|
address = ([address].pack("I_")).to_ptr
|
236
246
|
objn = ([0].pack("I_")).to_ptr
|
237
247
|
sz = ("\x00"*SIZEOFINT).to_ptr
|
238
|
-
r = CALLS["libc!vm_region:IPPIPPP=I"].call(task, address, sz,
|
248
|
+
r = CALLS["libc!vm_region:IPPIPPP=I"].call(task, address, sz, flavor, info, count, objn).first
|
239
249
|
raise KernelCallError.new(:vm_region, r) if r != 0
|
240
|
-
|
250
|
+
# this
|
251
|
+
return "#{info.to_s(Vm::FLAVORS[flavor][:size])}#{sz.to_s(SIZEOFINT)}#{address.to_s(SIZEOFINT)}"
|
241
252
|
end
|
242
253
|
end
|
243
254
|
end
|
@@ -209,17 +209,19 @@ module Ragweed::Wraposx
|
|
209
209
|
class << self
|
210
210
|
|
211
211
|
# Returns the packed string representation of the thread_info_t struct for later parsing.
|
212
|
+
#
|
212
213
|
# kern_return_t thread_info
|
213
214
|
# (thread_act_t target_thread,
|
214
215
|
# thread_flavor_t flavor,
|
215
216
|
# thread_info_t thread_info,
|
216
217
|
# mach_msg_type_number_t thread_info_count);
|
217
218
|
def thread_info_raw(thread, flavor)
|
218
|
-
|
219
|
+
raise KErrno::INVALID_ARGUMENT if ThreadInfo::FLAVORS[flavor].nil?
|
220
|
+
info = ("\x00"*ThreadInfo::FLAVORS[flavor][:size]).to_ptr
|
219
221
|
count = ([Ragweed::Wraposx::ThreadInfo::FLAVORS[flavor][:count]].pack("I_")).to_ptr
|
220
222
|
r = CALLS["libc!thread_info:IIPP=I"].call(thread,flavor,info,Ragweed::Wraposx::ThreadInfo::FLAVORS[flavor][:count]).first
|
221
223
|
raise KernelCallError.new(r) if r != 0
|
222
|
-
return info.to_s(
|
224
|
+
return "#{info.to_s(ThreadInfo::FLAVORS[flavor][:size])}#{count.to_s(SizeOf::INT)}"
|
223
225
|
end
|
224
226
|
end
|
225
227
|
end
|
data/lib/ragweed/wraposx.rb
CHANGED
@@ -5,7 +5,7 @@ module Ragweed; end
|
|
5
5
|
module Ragweed::Wraposx
|
6
6
|
|
7
7
|
# :stopdoc:
|
8
|
-
VERSION = '0.1.
|
8
|
+
VERSION = '0.1.7'
|
9
9
|
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
|
10
10
|
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
|
11
11
|
# :startdoc:
|
@@ -42,7 +42,7 @@ module Ragweed::Wraposx
|
|
42
42
|
search_me = ::File.expand_path(
|
43
43
|
::File.join(::File.dirname(fname), dir, '**', '*.rb'))
|
44
44
|
|
45
|
-
Dir.glob(search_me).sort.each {|rb| require rb}
|
45
|
+
Dir.glob(search_me).reject{|rb| rb =~ /#{__FILE__}/}.sort.each {|rb| require rb}
|
46
46
|
# require File.dirname(File.basename(__FILE__)) + "/#{x}"
|
47
47
|
|
48
48
|
end
|
data/lib/ragweed/wraptux.rb
CHANGED
data/lib/ragweed.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
module Ragweed
|
3
3
|
|
4
4
|
# :stopdoc:
|
5
|
-
VERSION = '0.1.
|
5
|
+
VERSION = '0.1.7'
|
6
6
|
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
|
7
7
|
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
|
8
8
|
# :startdoc:
|
@@ -40,7 +40,7 @@ module Ragweed
|
|
40
40
|
::File.join(::File.dirname(fname), dir, '**', '*.rb'))
|
41
41
|
|
42
42
|
# Don't want to load wrapper or debugger here.
|
43
|
-
Dir.glob(search_me).sort.reject{|rb| rb =~ /(wrap|debugger|rasm[
|
43
|
+
Dir.glob(search_me).sort.reject{|rb| rb =~ /(wrap|debugger|rasm[^\.])/}.each {|rb| require rb}
|
44
44
|
# require File.dirname(File.basename(__FILE__)) + "/#{x}"d
|
45
45
|
end
|
46
46
|
|
@@ -62,8 +62,8 @@ module Ragweed
|
|
62
62
|
end
|
63
63
|
|
64
64
|
if not pkgs.empty?
|
65
|
-
search_me = File.expand_path(File.join(File.dirname(fname), dir,
|
66
|
-
Dir.glob(search_me).sort.each {|rb| require rb}
|
65
|
+
search_me = File.expand_path(File.join(File.dirname(fname), dir, "*#{pkgs}.rb"))
|
66
|
+
Dir.glob(search_me).sort.reverse.each {|rb| require rb}
|
67
67
|
end
|
68
68
|
end
|
69
69
|
end # module Ragweed
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tduehr-ragweed
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- tduehr, tqbf, struct
|
@@ -52,7 +52,6 @@ files:
|
|
52
52
|
- lib/ragweed/ptr.rb
|
53
53
|
- lib/ragweed/rasm.rb
|
54
54
|
- lib/ragweed/rasm/isa.rb
|
55
|
-
- lib/ragweed/rasm/util.rb
|
56
55
|
- lib/ragweed/sbuf.rb
|
57
56
|
- lib/ragweed/trampoline.rb
|
58
57
|
- lib/ragweed/utils.rb
|
data/lib/ragweed/rasm/util.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
# Cheating; monkeypatching Object is evil.
|
2
|
-
class Object
|
3
|
-
# self-evident
|
4
|
-
def callable?; respond_to? :call; end
|
5
|
-
def number?; kind_of? Numeric; end
|
6
|
-
|
7
|
-
# while X remains callable, keep calling it to get its value
|
8
|
-
def derive
|
9
|
-
x = self
|
10
|
-
while x.callable?
|
11
|
-
x = x()
|
12
|
-
end
|
13
|
-
return x
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
# class String
|
18
|
-
# # this is just horrible
|
19
|
-
# def distorm
|
20
|
-
# Frasm::DistormDecoder.new.decode(self)
|
21
|
-
# end
|
22
|
-
#
|
23
|
-
# def disasm
|
24
|
-
# distorm.each {|i| puts i.mnem}
|
25
|
-
# end
|
26
|
-
# end
|