]> Dogcows Code - chaz/thecheat/blob - VMRegion.m
The Cheat 1.2
[chaz/thecheat] / VMRegion.m
1
2 //
3 // VMRegion 0.1
4 // Virtual Memory Wrapper
5 //
6 // Copyright (c) 2004, Chaz McGarvey
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without modification, are
10 // permitted provided that the following conditions are met:
11 //
12 // 1. Redistributions of source code must retain the above copyright notice, this list
13 // of conditions and the following disclaimer.
14 //
15 // 2. Redistributions in binary form must reproduce the above copyright notice, this
16 // list of conditions and the following disclaimer in the documentation and/or other
17 // materials provided with the distribution.
18 //
19 // 3. Neither the name of the BrokenZipper nor the names of its contributors may be
20 // used to endorse or promote products derived from this software without specific
21 // prior written permission.
22 //
23 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
24 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
26 // SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
28 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29 // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 // DAMAGE.
33 //
34 // Web: http://www.brokenzipper.com/
35 // Email: chaz@brokenzipper.com
36 //
37
38 #import "VMRegion.h"
39
40 #include <mach/mach_traps.h> // for task_for_pid(3)
41 #include <signal.h> // for stop(2)
42
43
44 static __inline__ vm_map_t _VMTaskFromPID( pid_t process )
45 {
46 vm_map_t task;
47
48 if ( task_for_pid( current_task(), process, &task ) == KERN_SUCCESS ) {
49 return task;
50 }
51 return 0;
52 }
53
54 static __inline__ VMRegion _VMMakeRegionWithAttributes( pid_t process, vm_address_t address, vm_size_t size, unsigned attribs )
55 {
56 VMRegion region;
57 region._process = process;
58 region._address = address;
59 region._size = size;
60 region._attributes = attribs;
61 return region;
62 }
63
64 unsigned _VMAttributesFromAddress( pid_t process, vm_address_t address );
65
66
67 const VMRegion VMNullRegion = { 0, 0, 0, 0 };
68
69
70 #pragma mark -
71 #pragma mark VMRegion Functions
72 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
73
74 VMRegion VMMakeRegion( pid_t process, vm_address_t address, vm_size_t size )
75 {
76 VMRegion region;
77 region._process = process;
78 region._address = address;
79 region._size = size;
80 region._attributes = _VMAttributesFromAddress( process, address );
81 return region;
82 }
83
84 BOOL VMRegionSetData( VMRegion region, NSData *data )
85 {
86 // get the size that should be used (to prevent from writing past the region)
87 vm_size_t size = (vm_size_t)[data length];
88 size = (size > region._size)? region._size : size;
89
90 return VMWriteBytes( region._process, region._address, [data bytes], size );
91 }
92
93 NSString *VMStringFromRegion( VMRegion region )
94 {
95 return [NSString stringWithFormat:@"{pid:%i,%p,%u,}", region._process, region._address, region._size];
96 }
97
98
99 #pragma mark -
100 #pragma mark Utility VM Functions
101 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
102
103 unsigned VMCountRegions( pid_t process )
104 {
105 VMRegion region;
106 VMRegion prev = VMNullRegion;
107 unsigned count = 0;
108
109 while ( VMRegionIsNotNull( region = VMNextRegion( process, prev ) ) )
110 {
111 count++;
112 prev = region;
113 }
114
115 return count;
116 }
117
118 unsigned VMCountRegionsWithAttributes( pid_t process, unsigned attribs )
119 {
120 VMRegion region;
121 VMRegion prev = VMNullRegion;
122 unsigned count = 0;
123
124 while ( VMRegionIsNotNull( region = VMNextRegionWithAttributes( process, prev, attribs ) ) )
125 {
126 count++;
127 prev = region;
128 }
129
130 return count;
131 }
132
133
134 VMRegion VMNextRegion( pid_t process, VMRegion previous )
135 {
136 vm_map_t task = _VMTaskFromPID( process );
137 unsigned attribs = 0;
138
139 kern_return_t result;
140
141 vm_address_t address = 0x0;
142 vm_size_t size = 0;
143 vm_region_basic_info_data_t info;
144 mach_msg_type_number_t infoCnt = VM_REGION_BASIC_INFO_COUNT;
145 mach_port_t object_name = 0;
146
147 if ( !VMEqualRegions( previous, VMNullRegion ) ) {
148 address = previous._address + previous._size;
149 }
150
151 // get the next region
152 result = vm_region( task, &address, &size, VM_REGION_BASIC_INFO, (vm_region_info_t)(&info), &infoCnt, &object_name );
153
154 if ( result == KERN_SUCCESS ) {
155 // get the attributes
156 if ( info.protection & VM_PROT_READ ) {
157 attribs |= VMREGION_READABLE;
158 }
159 if ( info.protection & VM_PROT_WRITE ) {
160 attribs |= VMREGION_WRITABLE;
161 }
162 if ( info.protection & VM_PROT_EXECUTE ) {
163 attribs |= VMREGION_EXECUTABLE;
164 }
165 // return the region
166 return _VMMakeRegionWithAttributes( process, address, size, attribs );
167 }
168
169 return VMNullRegion;
170 }
171
172 VMRegion VMNextRegionWithAttributes( pid_t process, VMRegion previous, unsigned attribs )
173 {
174 VMRegion region;
175
176 while ( VMRegionIsNotNull( region = VMNextRegion( process, previous ) ) )
177 {
178 if ( (attribs & region._attributes) == attribs ) {
179 // pass back this region if the attributes match
180 return region;
181 }
182 previous = region;
183 }
184
185 return VMNullRegion;
186 }
187
188
189 NSData *VMReadData( pid_t process, vm_address_t address, vm_size_t size )
190 {
191 vm_map_t task = _VMTaskFromPID( process );
192 kern_return_t result;
193
194 void *buffer;
195 vm_size_t actualSize;
196
197 // create a local block to hold the incoming data
198 buffer = (void *)malloc( (size_t)size );
199 if ( !buffer ) {
200 // no buffer, abort
201 return nil;
202 }
203
204 // perform the read
205 result = vm_read_overwrite( task, address, size, (vm_address_t)buffer, &actualSize );
206 if ( result != KERN_SUCCESS ) {
207 // read error, abort
208 free( buffer );
209 return nil;
210 }
211
212 // everything seems to be peachy, so return the data
213 return [[[NSData alloc] initWithBytesNoCopy:buffer length:actualSize freeWhenDone:YES] autorelease];
214 }
215
216 BOOL VMReadBytes( pid_t process, vm_address_t address, void *bytes, vm_size_t *size )
217 {
218 vm_map_t task = _VMTaskFromPID( process );
219 kern_return_t result;
220 vm_size_t staticsize = *size;
221
222 // perform the read
223 result = vm_read_overwrite( task, address, staticsize, (vm_address_t)bytes, size );
224 if ( result != KERN_SUCCESS ) {
225 return NO;
226 }
227
228 return YES;
229 }
230
231 BOOL VMWriteData( pid_t process, vm_address_t address, NSData *data )
232 {
233 return VMWriteBytes( process, address, [data bytes], [data length] );
234 }
235
236 BOOL VMWriteBytes( pid_t process, vm_address_t address, const void *bytes, vm_size_t size )
237 {
238 vm_map_t task = _VMTaskFromPID( process );
239 kern_return_t result;
240
241 // attempt to write the bytes and return success/failure
242 result = vm_write( task, address, (vm_address_t)bytes, size );
243 return (result == KERN_SUCCESS);
244 }
245
246
247 unsigned _VMAttributesFromAddress( pid_t process, vm_address_t address )
248 {
249 vm_map_t task = _VMTaskFromPID( process );
250 unsigned attribs = 0;
251
252 kern_return_t result;
253
254 vm_size_t size = 0;
255 vm_region_basic_info_data_t info;
256 mach_msg_type_number_t infoCnt = 8;
257 mach_port_t object_name = 0;
258
259 // get the next region
260 result = vm_region( task, &address, &size, VM_REGION_BASIC_INFO, (vm_region_info_t)(&info), &infoCnt, &object_name );
261
262 if ( result == KERN_SUCCESS ) {
263 // get the attributes
264 if ( info.protection & VM_PROT_READ ) {
265 attribs |= VMREGION_READABLE;
266 }
267 if ( info.protection & VM_PROT_WRITE ) {
268 attribs |= VMREGION_WRITABLE;
269 }
270 if ( info.protection & VM_PROT_EXECUTE ) {
271 attribs |= VMREGION_EXECUTABLE;
272 }
273 // return the region attributes
274 return attribs;
275 }
276 return 0;
277 }
278
279
This page took 0.04637 seconds and 4 git commands to generate.