1
2
3
4 package edu.stanford.suif.keepresident;
5
6 import java.util.Iterator;
7 import java.util.LinkedList;
8 import java.util.List;
9 import java.util.NoSuchElementException;
10
11 /***
12 * WindowsHeap
13 *
14 * @author jwhaley
15 * @version $Id: WindowsHeap.java,v 1.6 2004/08/18 21:45:50 jwhaley Exp $
16 */
17 public class WindowsHeap {
18
19 public static final int[] SystemInfo = new int[9];
20
21
22 public static final int dwOemId = 0;
23 public static final int dwPageSize = 1;
24 public static final int lpMinimumApplicationAddress = 2;
25 public static final int lpMaximumApplicationAddress = 3;
26 public static final int dwActiveProcessorMask = 4;
27 public static final int dwNumberOfProcessors = 5;
28 public static final int dwProcessorType = 6;
29 public static final int dwAllocationGranularity = 7;
30 public static final int wProcessorLevelAndRevision = 8;
31
32 public static void initSystemInfo(KernelInterface i) {
33 int p = KernelInterface.GetIntArrayElements(SystemInfo);
34 int result = i.call("GetSystemInfo", p);
35 KernelInterface.ReleaseIntArrayElements(SystemInfo, p);
36 }
37
38 public static int TECHNIQUE = 2;
39
40 public static void main(String[] args) throws Exception {
41 KernelInterface i = new KernelInterface();
42 initSystemInfo(i);
43 WindowsHeap dis = new WindowsHeap(i);
44 int r;
45
46
47 int proc = i.call("GetCurrentProcess");
48 int min = 100000000;
49 int max = 300000000;
50 i.call_nz("SetProcessWorkingSetSize", proc, min, max);
51
52 Thread.sleep(5000);
53 System.out.println("Starting...");
54
55 if (TECHNIQUE == 1) {
56
57 int minSize = 1;
58 long time = System.currentTimeMillis();
59 r = dis.lockAllHeaps(minSize);
60 time = System.currentTimeMillis() - time;
61 System.out.println("HeapWalk: Locked "+r+" bytes in "+time+" ms");
62 } else if (TECHNIQUE == 2) {
63
64 long time = System.currentTimeMillis();
65 int total = dis.lockAllVM();
66 time = System.currentTimeMillis() - time;
67 System.out.println("VirtualQueryEx: Locked "+total+" bytes in "+time+" ms");
68 } else if (TECHNIQUE == 3) {
69 int lowAddress = SystemInfo[lpMinimumApplicationAddress];
70 int highAddress = SystemInfo[lpMaximumApplicationAddress];
71 int step = SystemInfo[dwPageSize];
72
73 long time = System.currentTimeMillis();
74 r = dis.lockAllMemory(lowAddress, highAddress, step);
75 time = System.currentTimeMillis() - time;
76 System.out.println("IsBadReadPtr: Locked "+r+" bytes in "+time+" ms");
77 }
78
79 System.out.println("Sleeping before exit...");
80 Thread.sleep(5000);
81
82 }
83
84 public WindowsHeap(KernelInterface i) {
85 this.i = i;
86 this.locks = new LinkedList();
87 }
88
89 KernelInterface i;
90 List locks;
91
92 /***
93 * Walks over the given range of memory, attempting to lock every piece
94 * that is accessible. Returns the number of bytes successfully locked.
95 *
96 * @param start start address of memory range
97 * @param end end address of memory range
98 * @param step amount to step
99 * @return bytes successfully locked
100 */
101 public int lockAllMemory(int start, int end, int step) {
102 int totalSize = 0;
103 for (int p = start; p < end; p += step) {
104 if (IsBadReadPtr(p, step)) continue;
105 try {
106 VirtualLock(p, step);
107 locks.add(new int[] {p, step});
108 totalSize += step;
109 } catch (KernelException x) {
110
111 }
112 }
113 return totalSize;
114 }
115
116 public void releaseAllLocks() {
117 for (Iterator it = locks.iterator(); it.hasNext(); ) {
118 int[] a = (int[]) it.next();
119 try {
120 VirtualUnlock(a[0], a[1]);
121 } catch (KernelException x) {
122 }
123 it.remove();
124 }
125 }
126
127 public int getLockedBytes() {
128 int total = 0;
129 for (Iterator it = locks.iterator(); it.hasNext(); ) {
130 int[] a = (int[]) it.next();
131 total += a[1];
132 }
133 return total;
134 }
135
136 public boolean IsBadReadPtr(int p, int size) {
137 int r = i.call("IsBadReadPtr", p, size);
138 return r != 0;
139 }
140
141 public int lockAllHeaps(int minSize) {
142 int[] heaps = GetProcessHeaps();
143 int totalBytes = 0;
144 for (int j = 0; j < heaps.length; ++j) {
145 int heap = heaps[j];
146 System.out.println("Heap handle: "+heap);
147 HeapWalk w = new HeapWalk(i, heap);
148 while (w.hasNext()) {
149 int[] result = (int[]) w.next();
150 if (result[1] < minSize) continue;
151 System.out.println(" Memory pointer: 0x"+Integer.toHexString(result[0]));
152 System.out.println(" Memory size: "+result[1]);
153 try {
154 VirtualLock(result[0], result[1]);
155 locks.add(new int[] {result[0], result[1]});
156 totalBytes += result[1];
157 } catch (KernelException x) {
158 System.out.println(" Exception: "+x.getMessage());
159 }
160 }
161 }
162 return totalBytes;
163 }
164
165 public void VirtualLock(int addr, int size) {
166 int r = i.call_nz("VirtualLock", addr, size);
167 }
168
169 public void VirtualUnlock(int addr, int size) {
170 int r = i.call_nz("VirtualUnlock", addr, size);
171 }
172
173 public int[] GetProcessHeaps() {
174 int num = 256;
175 for (;;) {
176 int[] heaps = new int[num];
177 int pHeaps = KernelInterface.GetIntArrayElements(heaps);
178 int result = i.call("GetProcessHeaps", num, pHeaps);
179 KernelInterface.ReleaseIntArrayElements(heaps, pHeaps);
180 if (result > num) {
181 num = result;
182 continue;
183 }
184 int[] res = new int[result];
185 System.arraycopy(heaps, 0, res, 0, result);
186 return res;
187 }
188 }
189
190 public static HeapWalk getHeapWalker(KernelInterface i, int handle) {
191 return new HeapWalk(i, handle);
192 }
193
194 public static class HeapWalk implements Iterator {
195
196 KernelInterface i;
197 int heapHandle;
198 int[] sProcessHeapEntry;
199 boolean more;
200
201 public HeapWalk(KernelInterface i, int handle) {
202 this.i = i;
203 this.heapHandle = handle;
204 this.sProcessHeapEntry = new int[8];
205 gotoNext();
206 }
207
208 private void gotoNext() {
209 int pProcessHeapEntry = KernelInterface.GetIntArrayElements(sProcessHeapEntry);
210 int result = i.call("HeapWalk", heapHandle, pProcessHeapEntry);
211 KernelInterface.ReleaseIntArrayElements(sProcessHeapEntry, pProcessHeapEntry);
212 more = result != 0;
213 }
214
215 public int lpData() {
216 return sProcessHeapEntry[0];
217 }
218
219 public int cbData() {
220 return sProcessHeapEntry[1];
221 }
222
223
224
225
226 public boolean hasNext() {
227 return more;
228 }
229
230
231
232
233 public Object next() {
234 return nextEntry();
235 }
236
237 public int[] nextEntry() {
238 if (!more) throw new NoSuchElementException();
239 int[] result = new int[sProcessHeapEntry.length];
240 System.arraycopy(sProcessHeapEntry, 0, result, 0, result.length);
241 gotoNext();
242 return result;
243 }
244
245
246
247
248 public void remove() {
249 throw new UnsupportedOperationException();
250 }
251
252 }
253
254 public static VMWalker getVMWalker(KernelInterface i, int process) {
255 return new VMWalker(i, process);
256 }
257
258 public int lockAllVM() {
259 int proc = i.call("GetCurrentProcess");
260 int total = 0;
261 VMWalker w = new VMWalker(i, proc);
262 while (w.hasNext()) {
263 int[] a = w.nextEntry();
264 if (a[VMWalker.State] == VMWalker.MEM_COMMIT) {
265 switch (a[VMWalker.Protect]) {
266 case VMWalker.PAGE_READONLY:
267 case VMWalker.PAGE_READWRITE:
268 case VMWalker.PAGE_EXECUTE:
269 case VMWalker.PAGE_EXECUTE_READ:
270 case VMWalker.PAGE_EXECUTE_READWRITE:
271 try {
272 VirtualLock(a[VMWalker.BaseAddress], a[VMWalker.RegionSize]);
273 locks.add(new int[] {a[VMWalker.BaseAddress], a[VMWalker.RegionSize]});
274
275 total += a[VMWalker.RegionSize];
276 } catch (KernelException x) {
277 }
278 break;
279 default:
280 break;
281 }
282 }
283 }
284 return total;
285 }
286
287 public int printAllVM() {
288 int proc = i.call("GetCurrentProcess");
289 int total = 0;
290 VMWalker w = new VMWalker(i, proc);
291 while (w.hasNext()) {
292 int[] a = w.nextEntry();
293 System.out.println("Virtual memory region:");
294 System.out.println(" BaseAddress: 0x"+Integer.toHexString(a[0]));
295 System.out.println(" AllocationBase: 0x"+Integer.toHexString(a[1]));
296 System.out.println(" AllocationProtect: 0x"+Integer.toHexString(a[2]));
297 System.out.println(" RegionSize: 0x"+Integer.toHexString(a[3]));
298 System.out.println(" State: 0x"+Integer.toHexString(a[4]));
299 System.out.println(" Protect: 0x"+Integer.toHexString(a[5]));
300 System.out.println(" Type: 0x"+Integer.toHexString(a[6]));
301 if (a[VMWalker.State] == VMWalker.MEM_COMMIT) {
302 switch (a[VMWalker.Protect]) {
303 case VMWalker.PAGE_READONLY:
304 case VMWalker.PAGE_READWRITE:
305 case VMWalker.PAGE_EXECUTE:
306 case VMWalker.PAGE_EXECUTE_READ:
307 case VMWalker.PAGE_EXECUTE_READWRITE:
308 total += a[VMWalker.RegionSize];
309 break;
310 default:
311 break;
312 }
313 }
314 }
315 return total;
316 }
317
318 public static class VMWalker implements Iterator {
319 KernelInterface i;
320 int maxAppAddress;
321 int processHandle;
322 int lpMem;
323 int[] sMBI;
324
325 public VMWalker(KernelInterface i, int process) {
326 sMBI = new int[7];
327 this.processHandle = process;
328 this.i = i;
329 setMaxAppAddress();
330 gotoNext();
331 }
332
333 private void setMaxAppAddress() {
334 int[] a = new int[256];
335 int p = KernelInterface.GetIntArrayElements(a);
336 int result = i.call("GetSystemInfo", p);
337 KernelInterface.ReleaseIntArrayElements(a, p);
338 maxAppAddress = a[3];
339 }
340
341 public static final int BaseAddress = 0;
342 public static final int AllocationBase = 1;
343 public static final int AllocationProtect = 2;
344 public static final int RegionSize = 3;
345 public static final int State = 4;
346 public static final int Protect = 5;
347 public static final int Type = 6;
348
349
350 public static final int MEM_COMMIT = 0x1000;
351 public static final int MEM_FREE = 0x10000;
352 public static final int MEM_RESERVE = 0x2000;
353
354
355 public static final int PAGE_NOACCESS = 0x0001;
356 public static final int PAGE_READONLY = 0x0002;
357 public static final int PAGE_READWRITE = 0x0004;
358 public static final int PAGE_WRITECOPY = 0x0008;
359 public static final int PAGE_EXECUTE = 0x0010;
360 public static final int PAGE_EXECUTE_READ = 0x0020;
361 public static final int PAGE_EXECUTE_READWRITE = 0x0040;
362 public static final int PAGE_EXECUTE_WRITECOPY = 0x0080;
363 public static final int PAGE_GUARD = 0x0100;
364 public static final int PAGE_NOCACHE = 0x0200;
365
366
367 public static final int MEM_IMAGE = 0x01000000;
368 public static final int MEM_MAPPED = 0x40000;
369 public static final int MEM_PRIVATE = 0x20000;
370
371 private int gotoNext() {
372 int pMBI = KernelInterface.GetIntArrayElements(sMBI);
373 int result = i.call_nz("VirtualQueryEx", processHandle, lpMem, pMBI, sMBI.length*4);
374 KernelInterface.ReleaseIntArrayElements(sMBI, pMBI);
375 lpMem = sMBI[BaseAddress] + sMBI[RegionSize];
376 return result;
377 }
378
379
380
381
382 public boolean hasNext() {
383 return lpMem < maxAppAddress;
384 }
385
386
387
388
389 public Object next() {
390 return nextEntry();
391 }
392
393 public int[] nextEntry() {
394 if (!hasNext()) throw new NoSuchElementException();
395 int[] result = new int[sMBI.length];
396 System.arraycopy(sMBI, 0, result, 0, result.length);
397 gotoNext();
398 return result;
399 }
400
401
402
403
404 public void remove() {
405 throw new UnsupportedOperationException();
406 }
407
408 }
409 }