25 __in PEXCEPTION_POINTERS ExceptionInfo,
26 __out PBOOLEAN HaveBadAddress,
27 __out PULONG_PTR BadAddress
31 #pragma alloc_text(PAGE, KphCopyVirtualMemory)
32 #pragma alloc_text(PAGE, KpiReadVirtualMemory)
33 #pragma alloc_text(PAGE, KpiWriteVirtualMemory)
34 #pragma alloc_text(PAGE, KpiReadVirtualMemoryUnsafe)
37 #define KPH_STACK_COPY_BYTES 0x200
38 #define KPH_POOL_COPY_BYTES 0x10000
39 #define KPH_MAPPED_COPY_PAGES 14
40 #define KPH_POOL_COPY_THRESHOLD 0x3ff
43 __in PEXCEPTION_POINTERS ExceptionInfo,
44 __out PBOOLEAN HaveBadAddress,
45 __out PULONG_PTR BadAddress
48 PEXCEPTION_RECORD exceptionRecord;
50 *HaveBadAddress =
FALSE;
51 exceptionRecord = ExceptionInfo->ExceptionRecord;
53 if ((exceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION) ||
54 (exceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION) ||
55 (exceptionRecord->ExceptionCode == STATUS_IN_PAGE_ERROR))
57 if (exceptionRecord->NumberParameters > 1)
60 *HaveBadAddress =
TRUE;
61 *BadAddress = exceptionRecord->ExceptionInformation[1];
65 return EXCEPTION_EXECUTE_HANDLER;
81 __in PEPROCESS FromProcess,
82 __in PVOID FromAddress,
83 __in PEPROCESS ToProcess,
85 __in SIZE_T BufferLength,
86 __in KPROCESSOR_MODE AccessMode,
87 __out PSIZE_T ReturnLength
93 PMDL mdl = (PMDL)mdlBuffer;
95 SIZE_T mappedTotalSize;
101 BOOLEAN doMappedCopy;
103 BOOLEAN copyingToTarget =
FALSE;
104 BOOLEAN probing =
FALSE;
105 BOOLEAN mapping =
FALSE;
106 BOOLEAN haveBadAddress;
107 ULONG_PTR badAddress;
111 sourceAddress = FromAddress;
112 targetAddress = ToAddress;
116 buffer = stackBuffer;
120 if (mappedTotalSize > BufferLength)
121 mappedTotalSize = BufferLength;
123 stillToCopy = BufferLength;
124 blockSize = mappedTotalSize;
130 if (blockSize > stillToCopy)
131 blockSize = stillToCopy;
140 doMappedCopy =
FALSE;
144 if (buffer != stackBuffer)
145 ExFreePoolWithTag(buffer,
'ChpK');
147 buffer = stackBuffer;
154 if (buffer == stackBuffer)
160 buffer = ExAllocatePoolWithTag(NonPagedPool, blockSize,
'ChpK');
171 buffer = stackBuffer;
180 mappedAddress = NULL;
182 copyingToTarget =
FALSE;
184 KeStackAttachProcess(FromProcess, &apcState);
189 if (sourceAddress == FromAddress && AccessMode != KernelMode)
192 ProbeForRead(sourceAddress, BufferLength,
sizeof(UCHAR));
199 MmInitializeMdl(mdl, sourceAddress, blockSize);
200 MmProbeAndLockPages(mdl, AccessMode, IoReadAccess);
204 mappedAddress = MmMapLockedPagesSpecifyCache(
217 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
222 memcpy(buffer, sourceAddress, blockSize);
225 KeUnstackDetachProcess(&apcState);
228 KeStackAttachProcess(ToProcess, &apcState);
231 if (targetAddress == ToAddress && AccessMode != KernelMode)
234 ProbeForWrite(targetAddress, BufferLength,
sizeof(UCHAR));
239 copyingToTarget =
TRUE;
242 memcpy(targetAddress, mappedAddress, blockSize);
244 memcpy(targetAddress, buffer, blockSize);
247 GetExceptionInformation(),
252 KeUnstackDetachProcess(&apcState);
256 MmUnmapLockedPages(mappedAddress, mdl);
263 if (buffer != stackBuffer)
264 ExFreePoolWithTag(buffer,
'ChpK');
267 if (probing || mapping)
268 return GetExceptionCode();
271 if (copyingToTarget && haveBadAddress)
273 *ReturnLength = (ULONG)(badAddress - (ULONG_PTR)sourceAddress);
277 *ReturnLength = BufferLength - stillToCopy;
280 return STATUS_PARTIAL_COPY;
283 KeUnstackDetachProcess(&apcState);
287 MmUnmapLockedPages(mappedAddress, mdl);
291 stillToCopy -= blockSize;
292 sourceAddress = (PVOID)((ULONG_PTR)sourceAddress + blockSize);
293 targetAddress = (PVOID)((ULONG_PTR)targetAddress + blockSize);
296 if (buffer != stackBuffer)
297 ExFreePoolWithTag(buffer,
'ChpK');
299 *ReturnLength = BufferLength;
301 return STATUS_SUCCESS;
317 __in HANDLE ProcessHandle,
318 __in PVOID BaseAddress,
319 __out_bcount(BufferSize) PVOID Buffer,
320 __in SIZE_T BufferSize,
321 __out_opt PSIZE_T NumberOfBytesRead,
322 __in KPROCESSOR_MODE AccessMode
327 SIZE_T numberOfBytesRead;
331 if (AccessMode != KernelMode)
334 (ULONG_PTR)BaseAddress + BufferSize < (ULONG_PTR)BaseAddress ||
335 (ULONG_PTR)Buffer + BufferSize < (ULONG_PTR)Buffer ||
336 (ULONG_PTR)BaseAddress + BufferSize > (ULONG_PTR)MmHighestUserAddress ||
337 (ULONG_PTR)Buffer + BufferSize > (ULONG_PTR)MmHighestUserAddress
340 return STATUS_ACCESS_VIOLATION;
343 if (NumberOfBytesRead)
347 ProbeForWrite(NumberOfBytesRead,
sizeof(SIZE_T),
sizeof(SIZE_T));
349 __except (EXCEPTION_EXECUTE_HANDLER)
351 return GetExceptionCode();
358 status = ObReferenceObjectByHandle(
372 PsGetCurrentProcess(),
378 ObDereferenceObject(process);
383 numberOfBytesRead = 0;
384 status = STATUS_SUCCESS;
387 if (NumberOfBytesRead)
389 if (AccessMode != KernelMode)
393 *NumberOfBytesRead = numberOfBytesRead;
395 __except (EXCEPTION_EXECUTE_HANDLER)
403 *NumberOfBytesRead = numberOfBytesRead;
423 __in HANDLE ProcessHandle,
424 __in_opt PVOID BaseAddress,
425 __in_bcount(BufferSize) PVOID Buffer,
426 __in SIZE_T BufferSize,
427 __out_opt PSIZE_T NumberOfBytesWritten,
428 __in KPROCESSOR_MODE AccessMode
433 SIZE_T numberOfBytesWritten;
437 if (AccessMode != KernelMode)
440 (ULONG_PTR)BaseAddress + BufferSize < (ULONG_PTR)BaseAddress ||
441 (ULONG_PTR)Buffer + BufferSize < (ULONG_PTR)Buffer ||
442 (ULONG_PTR)BaseAddress + BufferSize > (ULONG_PTR)MmHighestUserAddress ||
443 (ULONG_PTR)Buffer + BufferSize > (ULONG_PTR)MmHighestUserAddress
446 return STATUS_ACCESS_VIOLATION;
449 if (NumberOfBytesWritten)
453 ProbeForWrite(NumberOfBytesWritten,
sizeof(SIZE_T),
sizeof(SIZE_T));
455 __except (EXCEPTION_EXECUTE_HANDLER)
457 return GetExceptionCode();
464 status = ObReferenceObjectByHandle(
476 PsGetCurrentProcess(),
482 &numberOfBytesWritten
484 ObDereferenceObject(process);
489 numberOfBytesWritten = 0;
490 status = STATUS_SUCCESS;
493 if (NumberOfBytesWritten)
495 if (AccessMode != KernelMode)
499 *NumberOfBytesWritten = numberOfBytesWritten;
501 __except (EXCEPTION_EXECUTE_HANDLER)
509 *NumberOfBytesWritten = numberOfBytesWritten;
530 __in_opt HANDLE ProcessHandle,
531 __in PVOID BaseAddress,
532 __out_bcount(BufferSize) PVOID Buffer,
533 __in SIZE_T BufferSize,
534 __out_opt PSIZE_T NumberOfBytesRead,
535 __in KPROCESSOR_MODE AccessMode
540 SIZE_T numberOfBytesRead;
544 if (AccessMode != KernelMode)
547 (ULONG_PTR)BaseAddress + BufferSize < (ULONG_PTR)BaseAddress ||
548 (ULONG_PTR)Buffer + BufferSize < (ULONG_PTR)Buffer ||
549 (ULONG_PTR)Buffer + BufferSize > (ULONG_PTR)MmHighestUserAddress
552 return STATUS_ACCESS_VIOLATION;
555 if (NumberOfBytesRead)
559 ProbeForWrite(NumberOfBytesRead,
sizeof(SIZE_T),
sizeof(SIZE_T));
561 __except (EXCEPTION_EXECUTE_HANDLER)
563 return GetExceptionCode();
571 if ((ULONG_PTR)BaseAddress + BufferSize > (ULONG_PTR)MmHighestUserAddress)
578 page = (ULONG_PTR)BaseAddress & ~(
PAGE_SIZE - 1);
579 pageEnd = ((ULONG_PTR)BaseAddress + BufferSize - 1) & ~(
PAGE_SIZE - 1);
584 for (; page <= pageEnd; page +=
PAGE_SIZE)
586 if (!MmIsAddressValid((PVOID)page))
587 ExRaiseStatus(STATUS_ACCESS_VIOLATION);
590 memcpy(Buffer, BaseAddress, BufferSize);
592 __except (EXCEPTION_EXECUTE_HANDLER)
594 return GetExceptionCode();
597 numberOfBytesRead = BufferSize;
598 status = STATUS_SUCCESS;
604 status = ObReferenceObjectByHandle(
618 PsGetCurrentProcess(),
624 ObDereferenceObject(process);
630 numberOfBytesRead = 0;
631 status = STATUS_SUCCESS;
634 if (NumberOfBytesRead)
636 if (AccessMode != KernelMode)
640 *NumberOfBytesRead = numberOfBytesRead;
642 __except (EXCEPTION_EXECUTE_HANDLER)
650 *NumberOfBytesRead = numberOfBytesRead;