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.
- data/README.rdoc +33 -8
- data/Rakefile +80 -23
- data/VERSION +1 -0
- data/examples/hittracertux.rb +2 -6
- data/examples/hook_notepad.rb +1 -1
- data/examples/tux-example.rb +3 -2
- data/lib/.DS_Store +0 -0
- data/lib/ragweed/debugger32.rb +188 -145
- data/lib/ragweed/debuggerosx.rb +13 -13
- data/lib/ragweed/debuggertux.rb +267 -140
- data/lib/ragweed/rasm.rb +1 -1
- data/lib/ragweed/wrap32/debugging.rb +184 -64
- data/lib/ragweed/wrap32/hooks.rb +27 -11
- data/lib/ragweed/wrap32/process.rb +114 -7
- data/lib/ragweed/wrap32/process_token.rb +23 -7
- data/lib/ragweed/wrap32/thread_context.rb +100 -166
- data/lib/ragweed/wrap32/wrap32.rb +127 -72
- data/lib/ragweed/wrap32.rb +1 -1
- data/lib/ragweed/wraposx/constants.rb +1 -9
- data/lib/ragweed/wraposx/region_info.rb +209 -188
- data/lib/ragweed/wraposx/structs.rb +102 -0
- data/lib/ragweed/wraposx/thread_context.rb +636 -159
- data/lib/ragweed/wraposx/thread_info.rb +40 -107
- data/lib/ragweed/wraposx/thread_info.rb.old +121 -0
- data/lib/ragweed/wraposx/wraposx.rb +154 -231
- data/lib/ragweed/wraposx.rb +2 -1
- data/lib/ragweed/wraptux/constants.rb +46 -22
- data/lib/ragweed/wraptux/struct_helpers.rb +25 -0
- data/lib/ragweed/wraptux/threads.rb +0 -0
- data/lib/ragweed/wraptux/wraptux.rb +58 -62
- data/lib/ragweed/wraptux.rb +3 -4
- data/lib/ragweed.rb +36 -8
- data/ragweed.gemspec +85 -15
- metadata +50 -18
@@ -2,7 +2,8 @@ module Ragweed; end
|
|
2
2
|
module Ragweed::Wraposx; end
|
3
3
|
module Ragweed::Wraposx::Vm
|
4
4
|
# these are flavor arguments for vm_region
|
5
|
-
#
|
5
|
+
# only basic info is supported by apple
|
6
|
+
REGION_BASIC_INFO_64 = 9
|
6
7
|
REGION_BASIC_INFO = 10
|
7
8
|
REGION_EXTENDED_INFO = 11
|
8
9
|
REGION_TOP_INFO = 12
|
@@ -23,232 +24,252 @@ module Ragweed::Wraposx::Vm
|
|
23
24
|
INHERIT_DEFAULT = 1 # VM_INHERIT_COPY
|
24
25
|
INHERIT_LAST_VALID = 2 # VM_INHERIT_NONE
|
25
26
|
|
26
|
-
#define VM_REGION_BASIC_INFO_COUNT ((mach_msg_type_number_t) (sizeof(vm_region_basic_info_data_t)/sizeof(int)))
|
27
|
-
#define VM_REGION_EXTENDED_INFO_COUNT ((mach_msg_type_number_t) (sizeof(vm_region_extended_info_data_t)/sizeof(int)))
|
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 => 8},
|
30
|
-
REGION_EXTENDED_INFO => {:size => 32, :count => 8},
|
31
|
-
REGION_TOP_INFO => {:size => 17,:count => 5}
|
32
|
-
}
|
33
|
-
|
34
27
|
module Pflags
|
35
28
|
READ = 0x1 #read permission
|
36
29
|
WRITE = 0x2 #write permission
|
37
30
|
EXECUTE = 0x4 #execute permission
|
38
31
|
end
|
39
|
-
end
|
40
32
|
|
41
|
-
# Memory region info base class.
|
42
|
-
#
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
refresh(str) if str
|
33
|
+
# Memory region info base class.
|
34
|
+
#
|
35
|
+
class RegionInfo < FFI::Struct
|
36
|
+
include Ragweed::FFIStructInclude
|
37
|
+
attr_accessor :region_size
|
38
|
+
attr_accessor :base_address
|
48
39
|
end
|
49
40
|
|
50
|
-
|
51
|
-
def refresh(str)
|
52
|
-
fields = self.class.const_get :FIELDS
|
53
|
-
if str and not str.empty?
|
54
|
-
str.unpack(fields.map {|x| x[1]}.join("")).each_with_index do |val, i|
|
55
|
-
raise "i is nil" if i.nil?
|
56
|
-
instance_variable_set "@#{ fields[i][0] }".intern, val
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
41
|
+
class RegionBasicInfo < RegionInfo
|
60
42
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
43
|
+
layout :protection, Ragweed::Wraposx::Libc.find_type(:vm_prot_t),
|
44
|
+
:max_protection, Ragweed::Wraposx::Libc.find_type(:vm_prot_t),
|
45
|
+
:inheritance, Ragweed::Wraposx::Libc.find_type(:vm_inherit_t),
|
46
|
+
:shared, Ragweed::Wraposx::Libc.find_type(:boolean_t),
|
47
|
+
:reserved, Ragweed::Wraposx::Libc.find_type(:boolean_t),
|
48
|
+
:offset, :uint32,
|
49
|
+
:behavior, Ragweed::Wraposx::Libc.find_type(:vm_behavior_t),
|
50
|
+
:user_wired_count, :ushort
|
65
51
|
|
66
|
-
def self.get(t, a, flavor)
|
67
|
-
self.new(Ragweed::Wraposx::vm_region_raw(t, a, flavor))
|
68
|
-
end
|
69
52
|
|
70
|
-
|
71
|
-
|
72
|
-
|
53
|
+
def dump(&block)
|
54
|
+
maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
|
55
|
+
maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
|
73
56
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
57
|
+
string =<<EOM
|
58
|
+
-----------------------------------------------------------------------
|
59
|
+
BASIC INFO:
|
60
|
+
base address: #{self.base_address.to_s(16).rjust(8, "0")}
|
61
|
+
|
62
|
+
protection: #{self.protection.to_s(2).rjust(8, "0")} #{Ragweed::Wraposx::Vm::Pflags.flag_dump(self.protection)}
|
63
|
+
max_protection: #{self.max_protection.to_s(2).rjust(8, "0")} #{Ragweed::Wraposx::Vm::Pflags.flag_dump(self.max_protection)}
|
64
|
+
inheritance: #{self.inheritance.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.inheritance)}
|
65
|
+
shared: #{self.shared.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.shared)}
|
66
|
+
reserved: #{self.reserved.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.reserved)}
|
67
|
+
offset: #{self.offset.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.offset)}
|
68
|
+
behavior: #{self.behavior.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.behavior)}
|
69
|
+
user_wired_count: #{self.user_wired_count.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.user_wired_count)}
|
70
|
+
size: #{self.size.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.size)}
|
71
|
+
EOM
|
80
72
|
end
|
81
|
-
"#<#{self.class.name.split("::").last} #{body.call}>"
|
82
73
|
end
|
83
74
|
|
84
|
-
|
85
|
-
maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
|
86
|
-
maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
|
87
|
-
|
88
|
-
string =<<EOM
|
89
|
-
-----------------------------------------------------------------------
|
90
|
-
INFO:
|
91
|
-
protection: #{self.protection.to_s(2).rjust(8, "0")} #{Ragweed::Wraposx::Vm::Pflags.flag_dump(self.protection)}
|
92
|
-
max_protection: #{self.max_protection.to_s(2).rjust(8, "0")} #{Ragweed::Wraposx::Vm::Pflags.flag_dump(self.max_protection)}
|
93
|
-
inheritance: #{self.inheritance.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.inheritance)}
|
94
|
-
shared: #{self.shared.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.shared)}
|
95
|
-
reserved: #{self.reserved.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.reserved)}
|
96
|
-
offset: #{self.offset.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.offset)}
|
97
|
-
behavior: #{self.behavior.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.behavior)}
|
98
|
-
user_wired_count: #{self.user_wired_count.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.user_wired_count)}
|
99
|
-
size: #{self.size.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.size)}
|
100
|
-
EOM
|
101
|
-
end
|
102
|
-
end
|
75
|
+
class RegionBasicInfo64 < RegionInfo
|
103
76
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
[:reserved, "I"], # If true the region is protected from random allocation.
|
113
|
-
[:offset, "L"], # The region's offset into the memory object. The region begins at this offset.
|
114
|
-
[:behavior, "i"], # Expected reference pattern for the memory.
|
115
|
-
[:user_wired_count, "S"],
|
116
|
-
[:size, "I"], # size of memory region returned
|
117
|
-
[:base_address, "L"]
|
118
|
-
]).each {|x| attr_accessor x[0]}
|
119
|
-
|
120
|
-
def dump(&block)
|
121
|
-
maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
|
122
|
-
maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
|
123
|
-
|
124
|
-
string =<<EOM
|
125
|
-
-----------------------------------------------------------------------
|
126
|
-
BASIC INFO:
|
127
|
-
base address: #{self.base_address.to_s(16).rjust(8, "0")}
|
128
|
-
|
129
|
-
protection: #{self.protection.to_s(2).rjust(8, "0")} #{Ragweed::Wraposx::Vm::Pflags.flag_dump(self.protection)}
|
130
|
-
max_protection: #{self.max_protection.to_s(2).rjust(8, "0")} #{Ragweed::Wraposx::Vm::Pflags.flag_dump(self.max_protection)}
|
131
|
-
inheritance: #{self.inheritance.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.inheritance)}
|
132
|
-
shared: #{self.shared.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.shared)}
|
133
|
-
reserved: #{self.reserved.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.reserved)}
|
134
|
-
offset: #{self.offset.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.offset)}
|
135
|
-
behavior: #{self.behavior.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.behavior)}
|
136
|
-
user_wired_count: #{self.user_wired_count.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.user_wired_count)}
|
137
|
-
size: #{self.size.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.size)}
|
138
|
-
EOM
|
139
|
-
end
|
77
|
+
layout :protection, Ragweed::Wraposx::Libc.find_type(:vm_prot_t),
|
78
|
+
:max_protection, Ragweed::Wraposx::Libc.find_type(:vm_prot_t),
|
79
|
+
:inheritance, Ragweed::Wraposx::Libc.find_type(:vm_inherit_t),
|
80
|
+
:shared, Ragweed::Wraposx::Libc.find_type(:boolean_t),
|
81
|
+
:reserved, Ragweed::Wraposx::Libc.find_type(:boolean_t),
|
82
|
+
:offset, Ragweed::Wraposx::Libc.find_type(:memory_object_offset_t),
|
83
|
+
:behavior, Ragweed::Wraposx::Libc.find_type(:vm_behavior_t),
|
84
|
+
:user_wired_count, :ushort
|
140
85
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
end
|
86
|
+
def dump(&block)
|
87
|
+
maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
|
88
|
+
maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
|
145
89
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
[:user_tag, "I"],
|
151
|
-
[:pages_resident, "I"],
|
152
|
-
[:pages_shared_now_private, "I"],
|
153
|
-
[:pages_swapped_out, "I"],
|
154
|
-
[:pages_dirtied, "I"],
|
155
|
-
[:ref_count, "I"],
|
156
|
-
[:shadow_depth, "S"],
|
157
|
-
[:external_pager, "C"],
|
158
|
-
[:share_mode, "C"],
|
159
|
-
[:size, "I"],
|
160
|
-
[:base_address, "I"] ]).each {|x| attr_accessor x[0]}
|
161
|
-
|
162
|
-
def dump(&block)
|
163
|
-
maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
|
164
|
-
maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
|
165
|
-
|
166
|
-
string =<<EOM
|
167
|
-
-----------------------------------------------------------------------
|
168
|
-
EXTENDED INFO:
|
169
|
-
base address: #{self.base_address.to_s(16).rjust(8, "0")}
|
90
|
+
string =<<EOM
|
91
|
+
-----------------------------------------------------------------------
|
92
|
+
BASIC INFO:
|
93
|
+
base address: #{self.base_address.to_s(16).rjust(8, "0")}
|
170
94
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
share_mode: #{self.share_mode.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.share_mode)}
|
181
|
-
size: #{self.size.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.size)}
|
95
|
+
protection: #{self.protection.to_s(2).rjust(8, "0")} #{Ragweed::Wraposx::Vm::Pflags.flag_dump(self.protection)}
|
96
|
+
max_protection: #{self.max_protection.to_s(2).rjust(8, "0")} #{Ragweed::Wraposx::Vm::Pflags.flag_dump(self.max_protection)}
|
97
|
+
inheritance: #{self.inheritance.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.inheritance)}
|
98
|
+
shared: #{self.shared.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.shared)}
|
99
|
+
reserved: #{self.reserved.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.reserved)}
|
100
|
+
offset: #{self.offset.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.offset)}
|
101
|
+
behavior: #{self.behavior.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.behavior)}
|
102
|
+
user_wired_count: #{self.user_wired_count.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.user_wired_count)}
|
103
|
+
size: #{self.size.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.size)}
|
182
104
|
EOM
|
105
|
+
end
|
183
106
|
end
|
184
107
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
108
|
+
# struct vm_region_extended_info {
|
109
|
+
# vm_prot_t protection;
|
110
|
+
# unsigned int user_tag;
|
111
|
+
# unsigned int pages_resident;
|
112
|
+
# unsigned int pages_shared_now_private;
|
113
|
+
# unsigned int pages_swapped_out;
|
114
|
+
# unsigned int pages_dirtied;
|
115
|
+
# unsigned int ref_count;
|
116
|
+
# unsigned short shadow_depth;
|
117
|
+
# unsigned char external_pager;
|
118
|
+
# unsigned char share_mode;
|
119
|
+
# };
|
120
|
+
class RegionExtendedInfo < RegionInfo
|
121
|
+
layout :protection, Ragweed::Wraposx::Libc.find_type(:vm_prot_t),
|
122
|
+
:user_tag, :uint,
|
123
|
+
:pages_resident, :uint,
|
124
|
+
:pages_shared_now_private, :uint,
|
125
|
+
:pages_swapped_out, :uint,
|
126
|
+
:pages_dirtied, :uint,
|
127
|
+
:ref_count, :uint,
|
128
|
+
:shadow_depth, :ushort,
|
129
|
+
:external_pager, :uchar,
|
130
|
+
:share_mode, :uchar
|
189
131
|
|
190
|
-
|
132
|
+
def dump(&block)
|
133
|
+
maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
|
134
|
+
maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
|
191
135
|
|
192
|
-
|
136
|
+
string =<<EOM
|
137
|
+
-----------------------------------------------------------------------
|
138
|
+
EXTENDED INFO:
|
139
|
+
base address: #{self.base_address.to_s(16).rjust(8, "0")}
|
140
|
+
|
141
|
+
protection: #{self.protection.to_s(2).rjust(8, "0")} #{Ragweed::Wraposx::Vm::Pflags.flag_dump(self.protection)}
|
142
|
+
user_tag: #{self.user_tag.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.user_tag)}
|
143
|
+
pages_resident: #{self.pages_resident.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.pages_resident)}
|
144
|
+
pages_shared_now_private: #{self.pages_shared_now_private.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.pages_shared_now_private)}
|
145
|
+
pages_swapped_out: #{self.pages_swapped_out.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.pages_swapped_out)}
|
146
|
+
pages_dirtied: #{self.pages_dirtied.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.pages_dirtied)}
|
147
|
+
ref_count: #{self.ref_count.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.ref_count)}
|
148
|
+
shadow_depth: #{self.shadow_depth.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.shadow_depth)}
|
149
|
+
external_pager: #{self.external_pager.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.external_pager)}
|
150
|
+
share_mode: #{self.share_mode.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.share_mode)}
|
151
|
+
size: #{self.size.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.size)}
|
152
|
+
EOM
|
153
|
+
end
|
154
|
+
end
|
193
155
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
156
|
+
# struct vm_region_top_info {
|
157
|
+
# unsigned int obj_id;
|
158
|
+
# unsigned int ref_count;
|
159
|
+
# unsigned int private_pages_resident;
|
160
|
+
# unsigned int shared_pages_resident;
|
161
|
+
# unsigned char share_mode;
|
162
|
+
# };
|
163
|
+
class RegionTopInfo < RegionInfo
|
164
|
+
layout :obj_id, :uint,
|
165
|
+
:ref_count, :uint,
|
166
|
+
:private_pages_resident, :uint,
|
167
|
+
:shared_pages_resident, :uint,
|
168
|
+
:share_mode, :uchar
|
201
169
|
|
202
|
-
|
203
|
-
|
204
|
-
|
170
|
+
def dump(&block)
|
171
|
+
maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
|
172
|
+
maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
|
205
173
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
174
|
+
string =<<EOM
|
175
|
+
-----------------------------------------------------------------------
|
176
|
+
TOP INFO:
|
177
|
+
base address: #{self.base_address.to_s(16).rjust(8, "0")}
|
210
178
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
179
|
+
obj_id: #{self.obj_id.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.obj_id)}
|
180
|
+
ref_count: #{self.ref_count.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.ref_count)}
|
181
|
+
private_pages_resident: #{self.private_pages_resident.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.private_pages_resident)}
|
182
|
+
shared_pages_resident: #{self.shared_pages_resident.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.shared_pages_resident)}
|
183
|
+
share_mode: #{self.share_mode.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.share_mode)}
|
184
|
+
size: #{self.size.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.size)}
|
217
185
|
EOM
|
186
|
+
end
|
218
187
|
end
|
219
188
|
|
220
|
-
|
221
|
-
|
222
|
-
|
189
|
+
#define VM_REGION_BASIC_INFO_COUNT ((mach_msg_type_number_t) (sizeof(vm_region_basic_info_data_t)/sizeof(int)))
|
190
|
+
#define VM_REGION_BASIC_INFO_COUNT_64 ((mach_msg_type_number_t) (sizeof(vm_region_basic_info_data_64_t)/sizeof(int)))
|
191
|
+
#define VM_REGION_EXTENDED_INFO_COUNT ((mach_msg_type_number_t) (sizeof(vm_region_extended_info_data_t)/sizeof(int)))
|
192
|
+
#define VM_REGION_TOP_INFO_COUNT ((mach_msg_type_number_t) (sizeof(vm_region_top_info_data_t)/sizeof(int)))
|
193
|
+
FLAVORS = { REGION_BASIC_INFO => {:size => 30, :count => 8, :class => RegionBasicInfo},
|
194
|
+
REGION_BASIC_INFO_64 => {:size => 30, :count => 9, :class => RegionBasicInfo64},
|
195
|
+
REGION_EXTENDED_INFO => {:size => 32, :count => 8, :class => RegionExtendedInfo},
|
196
|
+
REGION_TOP_INFO => {:size => 17,:count => 5, :class => RegionTopInfo}
|
197
|
+
}
|
223
198
|
end
|
224
199
|
|
225
200
|
module Ragweed::Wraposx
|
201
|
+
module Libc
|
202
|
+
extend FFI::Library
|
203
|
+
ffi_lib FFI::Library::LIBC
|
204
|
+
|
205
|
+
# determine if a function is defined in the attached libraries
|
206
|
+
def self.find_function func
|
207
|
+
ffi_libraries.detect{|lib| lib.find_function(func)}
|
208
|
+
end
|
209
|
+
|
210
|
+
attach_function :vm_region, [:vm_map_t, :pointer, :pointer, :vm_region_flavor_t, :pointer, :pointer, :pointer], :int if find_function "vm_region"
|
211
|
+
attach_function :vm_region_64, [:vm_map_t, :pointer, :pointer, :vm_region_flavor_t, :pointer, :pointer, :pointer], :int if find_function "vm_region_64"
|
212
|
+
end
|
213
|
+
|
226
214
|
class << self
|
227
215
|
|
228
|
-
# Returns a
|
229
|
-
# at address.
|
216
|
+
# Returns the base address, size, and a pointer to the requested information
|
217
|
+
# about the memory region at address in the target_task.
|
230
218
|
#
|
231
|
-
#
|
232
|
-
#
|
219
|
+
# Currently, only VM_REGION_BASIC_INFO is supported by Apple.
|
220
|
+
# Unless this is being run in 32bits, use vm_region_64 instead.
|
233
221
|
#
|
234
222
|
# kern_return_t vm_region
|
235
|
-
# (
|
236
|
-
# vm_address_t
|
237
|
-
# vm_size_t
|
238
|
-
# vm_region_flavor_t
|
239
|
-
# vm_region_info_t
|
240
|
-
# mach_msg_type_number_t
|
241
|
-
#
|
242
|
-
def
|
243
|
-
info = (
|
244
|
-
count = (
|
245
|
-
address = (
|
246
|
-
|
247
|
-
|
248
|
-
|
223
|
+
# (vm_map_t target_task,
|
224
|
+
# vm_address_t *address,
|
225
|
+
# vm_size_t *size,
|
226
|
+
# vm_region_flavor_t flavor,
|
227
|
+
# vm_region_info_t info,
|
228
|
+
# mach_msg_type_number_t *info_count,
|
229
|
+
# mach_port_t *object_name);
|
230
|
+
def vm_region(task, addr, flavor)
|
231
|
+
info = FFI::MemoryPointer.new(Vm::FLAVORS[flavor][:class], 1)
|
232
|
+
count = FFI::MemoryPointer.new(:int, 1).write_int(Vm::FLAVORS[flavor][:count])
|
233
|
+
address = FFI::MemoryPointer.new(:vm_address_t, 1).write_ulong(addr)
|
234
|
+
sz = FFI::MemoryPointer.new(:vm_size_t, 1)
|
235
|
+
objn = FFI::MemoryPointer.new(:mach_port_t, 1)
|
236
|
+
|
237
|
+
r = Libc.vm_region(task, address, sz, flavor, info, count, objn)
|
249
238
|
raise KernelCallError.new(:vm_region, r) if r != 0
|
250
|
-
|
251
|
-
|
252
|
-
|
239
|
+
ret = Vm::Flavors[flavor][:class].new info
|
240
|
+
ret.region_size = size.read_ulong
|
241
|
+
ret.base_address = address.read_ulong
|
242
|
+
ret
|
243
|
+
end if Libc.find_function "vm_region"
|
244
|
+
|
245
|
+
# Returns the base address, size, and a pointer to the requested information
|
246
|
+
# about the memory region at address in the target_task.
|
247
|
+
#
|
248
|
+
# Currently, only VM_REGION_BASIC_INFO is supported by Apple.
|
249
|
+
#
|
250
|
+
# kern_return_t vm_region
|
251
|
+
# (vm_map_t target_task,
|
252
|
+
# vm_address_t *address,
|
253
|
+
# vm_size_t *size,
|
254
|
+
# vm_region_flavor_t flavor,
|
255
|
+
# vm_region_info_t info,
|
256
|
+
# mach_msg_type_number_t *info_count,
|
257
|
+
# mach_port_t *object_name);
|
258
|
+
def vm_region_64(task, addr, flavor)
|
259
|
+
# OSX does this as well, so we need to do it ourselves
|
260
|
+
flavor = Vm::REGION_BASIC_INFO_64 if flavor == Vm::REGION_BASIC_INFO
|
261
|
+
info = FFI::MemoryPointer.new(:uint8, Vm::FLAVORS[flavor][:size])
|
262
|
+
count = FFI::MemoryPointer.new(Libc.find_type(:mach_msg_type_number_t), 1).write_uint(Vm::FLAVORS[flavor][:count])
|
263
|
+
address = FFI::MemoryPointer.new(Libc.find_type(:vm_address_t), 1).write_ulong(addr)
|
264
|
+
sz = FFI::MemoryPointer.new(Libc.find_type(:vm_size_t), 1)
|
265
|
+
objn = FFI::MemoryPointer.new(Libc.find_type(:mach_port_t), 1)
|
266
|
+
|
267
|
+
r = Libc.vm_region_64(task, address, sz, flavor, info, count, objn)
|
268
|
+
raise KernelCallError.new(:vm_region_64, r) if r != 0
|
269
|
+
ret = Vm::Flavors[flavor][:class].new info
|
270
|
+
ret.region_size = size.read_ulong
|
271
|
+
ret.base_address = address.read_ulong
|
272
|
+
ret
|
273
|
+
end if Libc.find_function "vm_region_64"
|
253
274
|
end
|
254
275
|
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# miscelaneous structs needed for other calls/structures
|
2
|
+
|
3
|
+
module Ragweed; end
|
4
|
+
module Ragweed::Wraposx
|
5
|
+
class FpControl < FFI::Struct
|
6
|
+
layout :value, :ushort
|
7
|
+
|
8
|
+
def invalid
|
9
|
+
self.value >> 15
|
10
|
+
end
|
11
|
+
def denorm
|
12
|
+
(self.value >> 14) & 1
|
13
|
+
end
|
14
|
+
def zdiv
|
15
|
+
(self.value >> 13) & 1
|
16
|
+
end
|
17
|
+
def ovrfl
|
18
|
+
(self.value >> 12) & 1
|
19
|
+
end
|
20
|
+
def undfl
|
21
|
+
(self.value >> 11) & 1
|
22
|
+
end
|
23
|
+
def precis
|
24
|
+
(self.value >> 10) & 1
|
25
|
+
end
|
26
|
+
def res0
|
27
|
+
(self.value >> 8) & 3
|
28
|
+
end
|
29
|
+
def pc
|
30
|
+
(self.value >> 6) & 3
|
31
|
+
end
|
32
|
+
def rc
|
33
|
+
(self.value >> 4) & 3
|
34
|
+
end
|
35
|
+
def res1
|
36
|
+
(self.value >> 3) & 1
|
37
|
+
end
|
38
|
+
def res2
|
39
|
+
self.value & 7
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class FpStatus < FFI::Struct
|
44
|
+
layout :value, :ushort
|
45
|
+
def invalid
|
46
|
+
self.value >> 15
|
47
|
+
end
|
48
|
+
def denorm
|
49
|
+
(self.value >> 14) & 1
|
50
|
+
end
|
51
|
+
def zdiv
|
52
|
+
(self.value >> 13) & 1
|
53
|
+
end
|
54
|
+
def ovrfl
|
55
|
+
(self.value >> 12) & 1
|
56
|
+
end
|
57
|
+
def undfl
|
58
|
+
(self.value >> 11) & 1
|
59
|
+
end
|
60
|
+
def precis
|
61
|
+
(self.value >> 10) & 1
|
62
|
+
end
|
63
|
+
def stkflt
|
64
|
+
(self.value >> 9) & 1
|
65
|
+
end
|
66
|
+
def errsumm
|
67
|
+
(self.value >> 8) & 1
|
68
|
+
end
|
69
|
+
def c0
|
70
|
+
(self.value >> 7) & 1
|
71
|
+
end
|
72
|
+
def c1
|
73
|
+
(self.value >> 6) & 1
|
74
|
+
end
|
75
|
+
def c2
|
76
|
+
(self.value >> 5) & 1
|
77
|
+
end
|
78
|
+
def tos
|
79
|
+
(self.value >> 2) & 7
|
80
|
+
end
|
81
|
+
def c2
|
82
|
+
(self.value >> 1) & 1
|
83
|
+
end
|
84
|
+
def busy
|
85
|
+
self.value & 1
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class MmstReg < FFI::Struct
|
90
|
+
layout :mmst_reg, [:char, 10],
|
91
|
+
:mmst_rsrv, [:char, 6]
|
92
|
+
end
|
93
|
+
|
94
|
+
class XmmReg < FFI::Struct
|
95
|
+
layout :xmm_reg, [:char, 16]
|
96
|
+
end
|
97
|
+
|
98
|
+
class TimeValue < FFI::Struct
|
99
|
+
layout :seconds, :int,
|
100
|
+
:microseconds, :int
|
101
|
+
end
|
102
|
+
end
|