]> Dogcows Code - chaz/thecheat/blob - VMRegion.m
The Cheat 1.2.3
[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 static __inline__ vm_map_t _VMTaskFromPID( pid_t process )
44 {
45 vm_map_t task;
46
47 if ( task_for_pid( current_task(), process, &task ) == KERN_SUCCESS ) {
48 return task;
49 }
50 return 0;
51 }
52
53 static __inline__ VMRegion _VMMakeRegionWithAttributes( pid_t process, vm_address_t address, vm_size_t size, unsigned attribs )
54 {
55 VMRegion region;
56 region._process = process;
57 region._address = address;
58 region._size = size;
59 region._attributes = attribs;
60 return region;
61 }
62
63 unsigned _VMAttributesFromAddress( pid_t process, vm_address_t address );
64
65
66 const VMRegion VMNullRegion = { 0, 0, 0, 0 };
67
68
69 #pragma mark -
70 #pragma mark VMRegion Functions
71 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
72
73 VMRegion VMMakeRegion( pid_t process, vm_address_t address, vm_size_t size )
74 {
75 VMRegion region;
76 region._process = process;
77 region._address = address;
78 region._size = size;
79 region._attributes = _VMAttributesFromAddress( process, address );
80 return region;
81 }
82
83 BOOL VMRegionSetData( VMRegion region, NSData *data )
84 {
85 // get the size that should be used (to prevent from writing past the region)
86 vm_size_t size = (vm_size_t)[data length];
87 size = (size > region._size)? region._size : size;
88
89 return VMWriteBytes( region._process, region._address, [data bytes], size );
90 }
91
92 NSString *VMStringFromRegion( VMRegion region )
93 {
94 return [NSString stringWithFormat:@"{pid:%i,%p,%u,}", region._process, region._address, region._size];
95 }
96
97
98 #pragma mark -
99 #pragma mark Utility VM Functions
100 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
101
102 unsigned VMCountRegions( pid_t process )
103 {
104 VMRegion region;
105 VMRegion prev = VMNullRegion;
106 unsigned count = 0;
107
108 while ( VMRegionIsNotNull( region = VMNextRegion( process, prev ) ) )
109 {
110 count++;
111 prev = region;
112 }
113
114 return count;
115 }
116
117 unsigned VMCountRegionsWithAttributes( pid_t process, unsigned attribs )
118 {
119 VMRegion region;
120 VMRegion prev = VMNullRegion;
121 unsigned count = 0;
122
123 while ( VMRegionIsNotNull( region = VMNextRegionWithAttributes( process, prev, attribs ) ) )
124 {
125 count++;
126 prev = region;
127 }
128
129 return count;
130 }
131
132
133 VMRegion VMNextRegion( pid_t process, VMRegion previous )
134 {
135 vm_map_t task = _VMTaskFromPID( process );
136 unsigned attribs = 0;
137
138 kern_return_t result;
139
140 vm_address_t address = 0x0;
141 vm_size_t size = 0;
142 vm_region_basic_info_data_t info;
143 mach_msg_type_number_t infoCnt = VM_REGION_BASIC_INFO_COUNT;
144 mach_port_t object_name = 0;
145
146 if ( !VMEqualRegions( previous, VMNullRegion ) ) {
147 address = previous._address + previous._size;
148 }
149
150 // get the next region
151 result = vm_region( task, &address, &size, VM_REGION_BASIC_INFO, (vm_region_info_t)(&info), &infoCnt, &object_name );
152
153 if ( result == KERN_SUCCESS ) {
154 // get the attributes
155 if ( info.protection & VM_PROT_READ ) {
156 attribs |= VMREGION_READABLE;
157 }
158 if ( info.protection & VM_PROT_WRITE ) {
159 attribs |= VMREGION_WRITABLE;
160 }
161 if ( info.protection & VM_PROT_EXECUTE ) {
162 attribs |= VMREGION_EXECUTABLE;
163 }
164 // return the region
165 return _VMMakeRegionWithAttributes( process, address, size, attribs );
166 }
167
168 return VMNullRegion;
169 }
170
171 VMRegion VMNextRegionWithAttributes( pid_t process, VMRegion previous, unsigned attribs )
172 {
173 VMRegion region;
174
175 while ( VMRegionIsNotNull( region = VMNextRegion( process, previous ) ) )
176 {
177 if ( (attribs & region._attributes) == attribs ) {
178 // pass back this region if the attributes match
179 return region;
180 }
181 previous = region;
182 }
183
184 return VMNullRegion;
185 }
186
187
188 NSData *VMReadData( pid_t process, vm_address_t address, vm_size_t size )
189 {
190 vm_map_t task = _VMTaskFromPID( process );
191 kern_return_t result;
192
193 void *buffer;
194 vm_size_t actualSize;
195
196 // create a local block to hold the incoming data
197 buffer = (void *)malloc( (size_t)size );
198 if ( !buffer ) {
199 // no buffer, abort
200 return nil;
201 }
202
203 // perform the read
204 result = vm_read_overwrite( task, address, size, (vm_address_t)buffer, &actualSize );
205 if ( result != KERN_SUCCESS ) {
206 // read error, abort
207 free( buffer );
208 return nil;
209 }
210
211 // everything seems to be peachy, so return the data
212 return [[[NSData alloc] initWithBytesNoCopy:buffer length:actualSize freeWhenDone:YES] autorelease];
213 }
214
215 BOOL VMReadBytes( pid_t process, vm_address_t address, void *bytes, vm_size_t *size )
216 {
217 vm_map_t task = _VMTaskFromPID( process );
218 kern_return_t result;
219 vm_size_t staticsize = *size;
220
221 // perform the read
222 result = vm_read_overwrite( task, address, staticsize, (vm_address_t)bytes, size );
223 if ( result != KERN_SUCCESS ) {
224 return NO;
225 }
226
227 return YES;
228 }
229
230 BOOL VMWriteData( pid_t process, vm_address_t address, NSData *data )
231 {
232 return VMWriteBytes( process, address, [data bytes], [data length] );
233 }
234
235 BOOL VMWriteBytes( pid_t process, vm_address_t address, const void *bytes, vm_size_t size )
236 {
237 vm_map_t task = _VMTaskFromPID( process );
238 kern_return_t result;
239
240 // attempt to write the bytes and return success/failure
241 result = vm_write( task, address, (vm_address_t)bytes, size );
242 return (result == KERN_SUCCESS);
243 }
244
245
246 unsigned _VMAttributesFromAddress( pid_t process, vm_address_t address )
247 {
248 vm_map_t task = _VMTaskFromPID( process );
249 unsigned attribs = 0;
250
251 kern_return_t result;
252
253 vm_size_t size = 0;
254 vm_region_basic_info_data_t info;
255 mach_msg_type_number_t infoCnt = 8;
256 mach_port_t object_name = 0;
257
258 // get the next region
259 result = vm_region( task, &address, &size, VM_REGION_BASIC_INFO, (vm_region_info_t)(&info), &infoCnt, &object_name );
260
261 if ( result == KERN_SUCCESS ) {
262 // get the attributes
263 if ( info.protection & VM_PROT_READ ) {
264 attribs |= VMREGION_READABLE;
265 }
266 if ( info.protection & VM_PROT_WRITE ) {
267 attribs |= VMREGION_WRITABLE;
268 }
269 if ( info.protection & VM_PROT_EXECUTE ) {
270 attribs |= VMREGION_EXECUTABLE;
271 }
272 // return the region attributes
273 return attribs;
274 }
275 return 0;
276 }
277
278
This page took 0.047524 seconds and 4 git commands to generate.