Господа! Хотелось бы обсудить следующий вопрос: какие существуют правила при использовании (чтение/запись) буфера виртуальной памяти процесса из ядра? Ситуация: драйвер вызывает // IRQL == 0x0 ImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData( Process->SectionBaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ImportSize); // получили виртуальный адрес секции в процессе // далее.. KeStackAttachProcess(&Process->Pcb, &ApcState); RtlCopyMemory(buffer, ImportDescriptor, ImportSize); <----- ИНОГДА! BSOD (KERNEL_MODE_EXCEPTION_NOT_HANDLED_M) Итак, не понятно, вроде PASSIVE_LEVEL.. а exception происходит!!! почему??? следует сделать следующее: __try { RtlCopyMemory(buffer, ImportDescriptor, ImportSize); } __except(EXCEPTION_EXECUTE_HANDLER) { // todo } НО КАК ПРЕДОТВРАТИТЬ EXCEPTION??? НУЖНО ИСПОЛЬЗОВАТЬ MmProbeAndLockPages??? НО почему ведь PASSIVE_LEVEL!! Thanx
******************************************************************************* * * * Bugcheck Analysis * * * ******************************************************************************* KERNEL_MODE_EXCEPTION_NOT_HANDLED_M (1000008e) This is a very common bugcheck. Usually the exception address pinpoints the driver/function that caused the problem. Always note this address as well as the link date of the driver/image that contains this address. Some common problems are exception code 0x80000003. This means a hard coded breakpoint or assertion was hit, but this system was booted /NODEBUG. This is not supposed to happen as developers should never have hardcoded breakpoints in retail code, but ... If this happens, make sure a debugger gets connected, and the system is booted /DEBUG. This will let us see why this breakpoint is happening. Arguments: Arg1: c0000005, The exception code that was not handled Arg2: 804d9a69, The address that the exception occurred at Arg3: af0e0a90, Trap Frame Arg4: 00000000 Debugging Details: ------------------ EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - <Unable to get error code text> FAULTING_IP: nt!memcpy+33 804d9a69 f3a5 rep movs dword ptr es:[edi],dword ptr [esi] TRAP_FRAME: af0e0a90 -- (.trap 0xffffffffaf0e0a90) ErrCode = 00000000 eax=01081b6c ebx=00000000 ecx=00000032 edx=00000000 esi=01081aa4 edi=00090014 eip=804d9a69 esp=af0e0b04 ebp=af0e0b0c iopl=0 nv up ei pl nz ac po nc cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010212 nt!memcpy+0x33: 804d9a69 f3a5 rep movs dword ptr es:[edi],dword ptr [esi] es:0023:00090014=00000000 ds:0023:01081aa4=???????? Resetting default scope DEFAULT_BUCKET_ID: DRIVER_FAULT BUGCHECK_STR: 0x8E PROCESS_NAME: wmiprvse.exe LAST_CONTROL_TRANSFER: from aecaa048 to 804d9a69
Хм, а может KeStackAttachProcess(&Process->Pcb, &ApcState); сделать до RtlImageDirectoryEntryToData...
Код (Text): PVOID RtlImageDirectoryEntryToData ( IN PVOID Base, IN BOOLEAN MappedAsImage, IN USHORT DirectoryEntry, OUT PULONG Size ) /*++ Routine Description: This function locates a Directory Entry within the image header and returns either the virtual address or seek address of the data the Directory describes. Arguments: Base - Supplies the base of the image or data file. MappedAsImage - FALSE if the file is mapped as a data file. - TRUE if the file is mapped as an image. DirectoryEntry - Supplies the directory entry to locate. Size - Return the size of the directory. Return Value: NULL - The file does not contain data for the specified directory entry. NON-NULL - Returns the address of the raw data the directory describes. --*/ { PIMAGE_NT_HEADERS NtHeaders; if (LDR_IS_DATAFILE(Base)) { Base = LDR_DATAFILE_TO_VIEW(Base); MappedAsImage = FALSE; } NtHeaders = RtlImageNtHeader(Base); if (!NtHeaders) return NULL; if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { return (RtlpImageDirectoryEntryToData32(Base, MappedAsImage, DirectoryEntry, Size, (PIMAGE_NT_HEADERS32)NtHeaders)); } else if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { return (RtlpImageDirectoryEntryToData64(Base, MappedAsImage, DirectoryEntry, Size, (PIMAGE_NT_HEADERS64)NtHeaders)); } else { return (NULL); } } Судите сами, до или после звать KeStackAttachProcess. Также не очень понятно зачем так хитро: Код (Text): KeStackAttachProcess(&Process->Pcb, &ApcState); Если Process типа PEPROCESS, тогда можно и так: Код (Text): KeStackAttachProcess(Process, &ApcState); И, кстати, не вижу в коде вызова KeUnstackDetachProcess.