DWORD FanCtrlRead(PDEVICE_OBJECT pDriverObject, PIRP pIRP) { int i; PCHAR pReadBuffer; UCHAR uTemp[12]; // load structure data ECCtrlRead(TP_OFF_FANMOD, &data.uMode); ECCtrlRead(TP_OFF_FANSPDL, &data.uSpeedL); ECCtrlRead(TP_OFF_FANSPDH, &data.uSpeedH); // load temperature sets for (i = 0; i < 8; i++) ECCtrlRead(TP_OFF_TEMP0 + i, &uTemp[i]); for (i = 0; i < 4; i++) ECCtrlRead(TP_OFF_TEMP1 + i, &uTemp[8 + i]); // store only valid data for (i = 0; i < 12; i++) if (uTemp[i] > 0) data.uTemp[i] = uTemp[i]; // setup read buffer pReadBuffer = (PCHAR)pIRP->AssociatedIrp.SystemBuffer; // setup buffer data RtlCopyBytes(pReadBuffer, &data, sizeof(data)); pIRP->IoStatus.Information = sizeof(data); return STATUS_SUCCESS; }
NTSTATUS Ds4_AddQueryInterfaces(WDFDEVICE Device) { NTSTATUS status; WDF_QUERY_INTERFACE_CONFIG ifaceCfg; INTERFACE devinterfaceHid; devinterfaceHid.Size = sizeof(INTERFACE); devinterfaceHid.Version = 1; devinterfaceHid.Context = (PVOID)Device; devinterfaceHid.InterfaceReference = WdfDeviceInterfaceReferenceNoOp; devinterfaceHid.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp; // Expose GUID_DEVINTERFACE_HID so HIDUSB can initialize WDF_QUERY_INTERFACE_CONFIG_INIT(&ifaceCfg, (PINTERFACE)&devinterfaceHid, &GUID_DEVINTERFACE_HID, NULL); status = WdfDeviceAddQueryInterface(Device, &ifaceCfg); if (!NT_SUCCESS(status)) { KdPrint(("WdfDeviceAddQueryInterface failed status 0x%x\n", status)); return status; } PDS4_DEVICE_DATA ds4Data = Ds4GetData(Device); // Set default HID input report (everything zero`d) UCHAR DefaultHidReport[DS4_HID_REPORT_SIZE] = { 0x01, 0x82, 0x7F, 0x7E, 0x80, 0x08, 0x00, 0x58, 0x00, 0x00, 0xFD, 0x63, 0x06, 0x03, 0x00, 0xFE, 0xFF, 0xFC, 0xFF, 0x79, 0xFD, 0x1B, 0x14, 0xD1, 0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 }; // Initialize HID reports to defaults RtlCopyBytes(ds4Data->HidInputReport, DefaultHidReport, DS4_HID_REPORT_SIZE); RtlZeroMemory(&ds4Data->OutputReport, sizeof(DS4_OUTPUT_REPORT)); // Start pending IRP queue flush timer WdfTimerStart(ds4Data->PendingUsbInRequestsTimer, DS4_QUEUE_FLUSH_PERIOD); return STATUS_SUCCESS; }
NTSTATUS BulkUsb_QueryWmiDataBlock(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN ULONG GuidIndex, IN ULONG InstanceIndex, IN ULONG InstanceCount, IN OUT PULONG InstanceLengthArray, IN ULONG OutBufferSize, OUT PUCHAR Buffer) { PTDeviceExtension deviceExtension; NTSTATUS ntStatus; ULONG size; WCHAR modelName[] = L"Aishverya\0\0"; USHORT modelNameLen; PAGED_CODE(); BulkUsb_DbgPrint(3, ("file bulkwmi: BulkUsb_QueryWmiDataBlock - begins\n")); size = 0; modelNameLen = (wcslen(modelName) + 1) * sizeof(WCHAR); ASSERT((InstanceIndex == 0) && (InstanceCount == 1)); deviceExtension = (PTDeviceExtension) DeviceObject->DeviceExtension; switch (GuidIndex) { case WMI_BULKUSB_DRIVER_INFORMATION: size = sizeof(ULONG) + modelNameLen + sizeof(USHORT); if (OutBufferSize < size ) { BulkUsb_DbgPrint(3, ("file bulkwmi: OutBuffer too small\n")); ntStatus = STATUS_BUFFER_TOO_SMALL; break; } * (PULONG) Buffer = DebugLevel; Buffer += sizeof(ULONG); *((PUSHORT)Buffer) = modelNameLen; Buffer = (PUCHAR)Buffer + sizeof(USHORT); RtlCopyBytes((PVOID)Buffer, (PVOID)modelName, modelNameLen); *InstanceLengthArray = size ; ntStatus = STATUS_SUCCESS; break; default: ntStatus = STATUS_WMI_GUID_NOT_FOUND; break; } ntStatus = WmiCompleteRequest(DeviceObject, Irp, ntStatus, size, IO_NO_INCREMENT); BulkUsb_DbgPrint(3, ("file bulkwmi: BulkUsb_QueryWmiDataBlock - ends\n")); return ntStatus; }
DWORD FanCtrlWrite(PDEVICE_OBJECT pDriverObject, PIRP pIRP) { int i; UCHAR uValue; PCHAR pReadBuffer; // setup read buffer pReadBuffer = (PCHAR)pIRP->AssociatedIrp.SystemBuffer; // setup buffer data RtlCopyBytes(&uValue, pReadBuffer, 1); pIRP->IoStatus.Information = 1; // output the expected fan speed ECCtrlWrite(TP_OFF_FANMOD, &uValue); return STATUS_SUCCESS; }
NTSTATUS DriverDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { NTSTATUS Status = STATUS_UNSUCCESSFUL; PIO_STACK_LOCATION IrpSp; ULONG IOControlCode = 0; ULONG dwBytesWritten = 0; PCHAR pInBuf = NULL, pOutBuf = NULL; unsigned int _cpu_thread_id = 0; unsigned int new_cpu_thread_id = 0; ULONG _num_active_cpus = 0; KAFFINITY _kaffinity = 0; UINT32 core_id = 0; // // Get the current IRP stack location of this request // IrpSp = IoGetCurrentIrpStackLocation (Irp); IOControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode; DbgPrint( "[chipsec] >>>>>>>>>> IOCTL >>>>>>>>>>\n" ); DbgPrint( "[chipsec] DeviceObject = 0x%x IOCTL = 0x%x\n", DeviceObject, IOControlCode ); DbgPrint( "[chipsec] InputBufferLength = 0x%x, OutputBufferLength = 0x%x\n", IrpSp->Parameters.DeviceIoControl.InputBufferLength, IrpSp->Parameters.DeviceIoControl.OutputBufferLength ); // // CPU thread ID // _num_active_cpus = KeQueryActiveProcessorCount( NULL ); _kaffinity = KeQueryActiveProcessors(); _cpu_thread_id = KeGetCurrentProcessorNumber(); DbgPrint( "[chipsec] Active CPU threads : %d (KeNumberProcessors = %d)\n", _num_active_cpus, KeNumberProcessors ); DbgPrint( "[chipsec] Active CPU mask (KAFFINITY): 0x%08X\n", _kaffinity ); DbgPrint( "[chipsec] Current CPU thread : %d\n", _cpu_thread_id ); // // Switch on the IOCTL code that is being requested by the user. If the // operation is a valid one for this device do the needful. // Irp -> IoStatus.Information = 0; switch( IOControlCode ) { case READ_PCI_CFG_REGISTER: { DWORD val; BYTE size = 0; WORD bdf[4]; BYTE bus = 0, dev = 0, fun = 0, off = 0; DbgPrint( "[chipsec] > READ_PCI_CFG_REGISTER\n" ); RtlCopyBytes( bdf,Irp->AssociatedIrp.SystemBuffer, 4*sizeof(WORD) ); RtlCopyBytes( &size, (BYTE*)Irp->AssociatedIrp.SystemBuffer + 4*sizeof(WORD), sizeof(BYTE) ); bus = (UINT8)bdf[0]; dev = (UINT8)bdf[1]; fun = (UINT8)bdf[2]; off = (UINT8)bdf[3]; if( 1 != size && 2 != size && 4 != size) { DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" ); Status = STATUS_INVALID_PARAMETER; break; } val = ReadPCICfg( bus, dev, fun, off, size ); IrpSp->Parameters.Read.Length = size; RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (VOID*)&val, size ); DbgPrint( "[chipsec][READ_PCI_CFG_REGISTER] B/D/F: %#04x/%#04x/%#04x, OFFSET: %#04x, value = %#010x (size = 0x%x)\n", bus, dev, fun, off, val, size ); dwBytesWritten = IrpSp->Parameters.Read.Length; Status = STATUS_SUCCESS; break; } case WRITE_PCI_CFG_REGISTER: { DWORD val = 0; WORD bdf[6]; BYTE bus = 0, dev = 0, fun = 0, off = 0; BYTE size = 0; DbgPrint( "[chipsec] > WRITE_PCI_CFG_REGISTER\n" ); RtlCopyBytes( bdf, Irp->AssociatedIrp.SystemBuffer, 6 * sizeof(WORD) ); bus = (UINT8)bdf[0]; dev = (UINT8)bdf[1]; fun = (UINT8)bdf[2]; off = (UINT8)bdf[3]; RtlCopyBytes( &size, (BYTE*)Irp->AssociatedIrp.SystemBuffer + 6*sizeof(WORD), sizeof(BYTE) ); val = ((DWORD)bdf[5] << 16) | bdf[4]; DbgPrint( "[chipsec][WRITE_PCI_CFG_REGISTER] B/D/F: %#02x/%#02x/%#02x, OFFSET: %#02x, value = %#010x (size = %#02x)\n", bus, dev, fun, off, val, size ); WritePCICfg( bus, dev, fun, off, size, val ); Status = STATUS_SUCCESS; break; } case IOCTL_READ_PHYSMEM: { UINT32 len = 0; PVOID virt_addr; PHYSICAL_ADDRESS phys_addr = { 0x0, 0x0 }; DbgPrint( "[chipsec] > IOCTL_READ_PHYSMEM\n" ); if( !Irp->AssociatedIrp.SystemBuffer || IrpSp->Parameters.DeviceIoControl.InputBufferLength < 3*sizeof(UINT32)) { DbgPrint( "[chipsec][IOCTL_READ_PHYSMEM] ERROR: STATUS_INVALID_PARAMETER\n" ); Status = STATUS_INVALID_PARAMETER; break; } pInBuf = Irp->AssociatedIrp.SystemBuffer; pOutBuf = Irp->AssociatedIrp.SystemBuffer; phys_addr.HighPart = ((UINT32*)pInBuf)[0]; phys_addr.LowPart = ((UINT32*)pInBuf)[1]; len = ((UINT32*)pInBuf)[2]; if( !len ) len = 4; if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength < len ) { DbgPrint( "[chipsec][IOCTL_READ_PHYSMEM] ERROR: STATUS_BUFFER_TOO_SMALL\n" ); Status = STATUS_BUFFER_TOO_SMALL; break; } __try { Status = _read_phys_mem( phys_addr, len, pOutBuf ); } __except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); DbgPrint( "[chipsec][IOCTL_READ_PHYSMEM] ERROR: exception code 0x%X\n", Status ); break; } if( NT_SUCCESS(Status) ) { DbgPrint( "[chipsec][IOCTL_READ_PHYSMEM] Contents:\n" ); _dump_buffer( (unsigned char *)pOutBuf, min(len,0x100) ); dwBytesWritten = len; } break; } case IOCTL_WRITE_PHYSMEM: { UINT32 len = 0; PVOID virt_addr = 0; PHYSICAL_ADDRESS phys_addr = { 0x0, 0x0 }; DbgPrint( "[chipsec] > IOCTL_WRITE_PHYSMEM\n" ); if( Irp->AssociatedIrp.SystemBuffer ) { pInBuf = Irp->AssociatedIrp.SystemBuffer; pOutBuf = Irp->AssociatedIrp.SystemBuffer; if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < 3*sizeof(UINT32) ) { DbgPrint( "[chipsec][IOCTL_WRITE_PHYSMEM] ERROR: STATUS_INVALID_PARAMETER\n" ); Status = STATUS_INVALID_PARAMETER; break; } phys_addr.HighPart = ((UINT32*)pInBuf)[0]; phys_addr.LowPart = ((UINT32*)pInBuf)[1]; len = ((UINT32*)pInBuf)[2]; ((UINT32*)pInBuf) += 3; if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < len + 3*sizeof(UINT32) ) { DbgPrint( "[chipsec][IOCTL_WRITE_PHYSMEM] ERROR: STATUS_INVALID_PARAMETER\n" ); Status = STATUS_INVALID_PARAMETER; break; } DbgPrint( "[chipsec][IOCTL_WRITE_PHYSMEM] Writing contents:\n" ); _dump_buffer( (unsigned char *)pInBuf, min(len,0x100) ); __try { Status = _write_phys_mem( phys_addr, len, pInBuf ); } __except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); DbgPrint( "[chipsec][IOCTL_WRITE_PHYSMEM] ERROR: exception code 0x%X\n", Status ); break; } break; } } case IOCTL_ALLOC_PHYSMEM: { SIZE_T NumberOfBytes = 0; PVOID va = 0; PHYSICAL_ADDRESS HighestAcceptableAddress = { 0xFFFFFFFF, 0xFFFFFFFF }; DbgPrint( "[chipsec] > IOCTL_ALLOC_PHYSMEM\n" ); pInBuf = Irp->AssociatedIrp.SystemBuffer; pOutBuf = Irp->AssociatedIrp.SystemBuffer; if( !pInBuf || IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(UINT64) + sizeof(UINT32)) { DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" ); Status = STATUS_INVALID_PARAMETER; break; } RtlCopyBytes( &HighestAcceptableAddress.QuadPart, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(UINT64) ); RtlCopyBytes( &NumberOfBytes, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(UINT64), sizeof(UINT32) ); DbgPrint( "[chipsec] Allocating: NumberOfBytes = 0x%X, PhysAddr = 0x%I64x", NumberOfBytes, HighestAcceptableAddress.QuadPart ); va = MmAllocateContiguousMemory( NumberOfBytes, HighestAcceptableAddress ); if( !va ) { DbgPrint( "[chipsec] ERROR: STATUS_UNSUCCESSFUL - could not allocate memory\n" ); Status = STATUS_UNSUCCESSFUL; } else if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 2*sizeof(UINT64) ) { DbgPrint( "[chipsec] ERROR: STATUS_BUFFER_TOO_SMALL - should be at least 2*UINT64\n" ); Status = STATUS_BUFFER_TOO_SMALL; } else { PHYSICAL_ADDRESS pa = MmGetPhysicalAddress( va ); DbgPrint( "[chipsec] Allocated Buffer: VirtAddr = 0x%I64x, PhysAddr = 0x%I64x\n", (UINT64)va, pa.QuadPart ); ((UINT64*)pOutBuf)[0] = (UINT64)va; ((UINT64*)pOutBuf)[1] = pa.QuadPart; IrpSp->Parameters.Read.Length = 2*sizeof(UINT64); dwBytesWritten = IrpSp->Parameters.Read.Length; Status = STATUS_SUCCESS; } break; } case IOCTL_FREE_PHYSMEM: { UINT64 va = 0x0; pInBuf = Irp->AssociatedIrp.SystemBuffer; pOutBuf = Irp->AssociatedIrp.SystemBuffer; DbgPrint( "[chipsec] > IOCTL_FREE_PHYSMEM\n" ); if( !Irp->AssociatedIrp.SystemBuffer || IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(UINT64)) { DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" ); Status = STATUS_INVALID_PARAMETER; break; } RtlCopyBytes( &va, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(UINT64) ); DbgPrint( "[chipsec][IOCTL_FREE_PHYSMEM] Virtual address of the memory being freed: 0x%I64X\n", va ); MmFreeContiguousMemory( (PVOID)va ); IrpSp->Parameters.Read.Length = 0; dwBytesWritten = IrpSp->Parameters.Read.Length; Status = STATUS_SUCCESS; break; } case IOCTL_GET_PHYSADDR: { UINT64 va = 0x0; PHYSICAL_ADDRESS pa = { 0x0, 0x0 }; pInBuf = Irp->AssociatedIrp.SystemBuffer; pOutBuf = Irp->AssociatedIrp.SystemBuffer; DbgPrint( "[chipsec] > IOCTL_GET_PHYSADDR\n" ); if( !Irp->AssociatedIrp.SystemBuffer || IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(UINT64)) { DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" ); Status = STATUS_INVALID_PARAMETER; break; } if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(UINT64)) { DbgPrint( "[chipsec] ERROR: STATUS_BUFFER_TOO_SMALL\n" ); Status = STATUS_BUFFER_TOO_SMALL; break; } RtlCopyBytes( &va, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(UINT64) ); pa = MmGetPhysicalAddress( (PVOID)va ); DbgPrint( "[chipsec][IOCTL_GET_PHYSADDR] Traslated virtual address 0x%I64X to physical: 0x%I64X\n", va, pa.QuadPart, pa.LowPart); RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (void*)&pa, sizeof(UINT64) ); IrpSp->Parameters.Read.Length = sizeof(UINT64); dwBytesWritten = IrpSp->Parameters.Read.Length; Status = STATUS_SUCCESS; break; } case IOCTL_MAP_IO_SPACE: { PVOID va = 0x0; PHYSICAL_ADDRESS pa = { 0x0, 0x0 }; unsigned int len = 0; unsigned int cache_type = 0; pInBuf = Irp->AssociatedIrp.SystemBuffer; pOutBuf = Irp->AssociatedIrp.SystemBuffer; DbgPrint( "[chipsec] > IOCTL_MAP_IO_SPACE\n" ); if( !Irp->AssociatedIrp.SystemBuffer || IrpSp->Parameters.DeviceIoControl.InputBufferLength != 3*8) { DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" ); Status = STATUS_INVALID_PARAMETER; break; } if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(UINT64)) { DbgPrint( "[chipsec] ERROR: STATUS_BUFFER_TOO_SMALL\n" ); Status = STATUS_BUFFER_TOO_SMALL; break; } RtlCopyBytes( &pa, (BYTE*)Irp->AssociatedIrp.SystemBuffer + 0x00, 0x8 ); RtlCopyBytes( &len, (BYTE*)Irp->AssociatedIrp.SystemBuffer + 0x08, 0x4 ); RtlCopyBytes( &cache_type, (BYTE*)Irp->AssociatedIrp.SystemBuffer + 0x10, 0x4 ); va = MmMapIoSpace(pa, len, cache_type); DbgPrint( "[chipsec][IOCTL_MAP_IO_SPACE] Mapping physical address 0x%016llX to virtual 0x%016llX\n", pa, va); RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (void*)&va, sizeof(va) ); IrpSp->Parameters.Read.Length = sizeof(va); dwBytesWritten = sizeof(va); Status = STATUS_SUCCESS; break; } case IOCTL_LOAD_UCODE_PATCH: { PVOID ucode_buf = NULL; UINT64 ucode_start = 0; UINT16 ucode_size = 0; UINT32 _eax = 0, _edx = 0; int CPUInfo[4] = {-1}; DbgPrint("[chipsec] > IOCTL_LOAD_UCODE_UPDATE\n" ); if( !Irp->AssociatedIrp.SystemBuffer || IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(BYTE) + sizeof(UINT16) ) { DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER (input buffer size < 3)\n" ); Status = STATUS_INVALID_PARAMETER; break; } RtlCopyBytes( &new_cpu_thread_id, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(BYTE) ); if( new_cpu_thread_id >= _num_active_cpus ) new_cpu_thread_id = 0; KeSetSystemAffinityThread( (KAFFINITY)(1 << new_cpu_thread_id) ); DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] Changed CPU thread to %d\n", KeGetCurrentProcessorNumber() ); RtlCopyBytes( &ucode_size, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(BYTE), sizeof(UINT16) ); DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] Ucode update size = 0x%X\n", ucode_size ); if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < ucode_size + sizeof(BYTE) + sizeof(UINT16) ) { DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER (input buffer size < ucode_size + 3)\n" ); Status = STATUS_INVALID_PARAMETER; break; } ucode_buf = ExAllocatePoolWithTag( NonPagedPool, ucode_size, 0x3184 ); if( !ucode_buf ) { DbgPrint( "[chipsec] ERROR: couldn't allocate pool for ucode binary\n" ); break; } RtlCopyBytes( ucode_buf, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(BYTE) + sizeof(UINT16), ucode_size ); ucode_start = (UINT64)ucode_buf; DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] ucode update address = 0x%p (eax = 0x%08X, edx = 0x%08X)\n", ucode_start, (UINT32)(ucode_start & 0xFFFFFFFF), (UINT32)((ucode_start >> 32) & 0xFFFFFFFF) ); DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] ucode update contents:\n" ); _dump_buffer( (unsigned char *)ucode_buf, min(ucode_size,0x100) ); // -- // -- trigger CPU ucode patch update // -- pInBuf points to the beginning of ucode update binary // -- _wrmsr( MSR_IA32_BIOS_UPDT_TRIG, (UINT32)((ucode_start >> 32) & 0xFFFFFFFF), (UINT32)(ucode_start & 0xFFFFFFFF) ); ExFreePoolWithTag( ucode_buf, 0x3184 ); // -- // -- check if patch was loaded // -- // -- need to clear IA32_BIOS_SIGN_ID MSR first // -- CPUID will deposit an update ID value in 64-bit MSR at address MSR_IA32_BIOS_SIGN_ID // -- read IA32_BIOS_SIGN_ID MSR to check patch ID != 0 // -- DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] checking ucode update was loaded..\n" ); DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] clear IA32_BIOS_SIGN_ID, CPUID EAX=1, read back IA32_BIOS_SIGN_ID\n" ); _wrmsr( MSR_IA32_BIOS_SIGN_ID, 0, 0 ); __cpuid(CPUInfo, 1); _rdmsr( MSR_IA32_BIOS_SIGN_ID, &_eax, &_edx ); DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] RDMSR( IA32_BIOS_SIGN_ID=0x8b ) = 0x%08x%08x\n", _edx, _eax ); if( 0 != _edx ) DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] Microcode update loaded (ID != 0)\n" ); else DbgPrint( "[chipsec] ERROR: Microcode update failed\n" ); Status = STATUS_SUCCESS; break; } case IOCTL_WRMSR: { UINT32 msrData[3]; UINT32 _eax = 0, _edx = 0; unsigned int _msr_addr; DbgPrint("[chipsec] > IOCTL_WRMSR\n"); pInBuf = Irp->AssociatedIrp.SystemBuffer; if( !pInBuf ) { DbgPrint( "[chipsec][IOCTL_WRMSR] ERROR: NO data provided\n" ); Status = STATUS_INVALID_PARAMETER; break; } if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(BYTE) + 3*sizeof(UINT32) ) { DbgPrint( "[chipsec][IOCTL_WRMSR] ERROR: STATUS_INVALID_PARAMETER (input buffer size < sizeof(BYTE) + 3*sizeof(UINT32))\n" ); Status = STATUS_INVALID_PARAMETER; break; } RtlCopyBytes( &new_cpu_thread_id, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(BYTE) ); if( new_cpu_thread_id >= _num_active_cpus ) new_cpu_thread_id = 0; KeSetSystemAffinityThread( (KAFFINITY)(1 << new_cpu_thread_id) ); DbgPrint( "[chipsec][IOCTL_WRMSR] Changed CPU thread to %d\n", KeGetCurrentProcessorNumber() ); RtlCopyBytes( msrData, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(BYTE), 3 * sizeof(UINT32) ); _msr_addr = msrData[0]; _eax = msrData[1]; _edx = msrData[2]; DbgPrint( "[chipsec][IOCTL_WRMSR] WRMSR( 0x%x ) <-- 0x%08x%08x\n", _msr_addr, _edx, _eax ); // -- // -- write MSR // -- __try { _wrmsr( _msr_addr, _edx, _eax ); } __except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); DbgPrint( "[chipsec][IOCTL_WRMSR] ERROR: exception code 0x%X\n", Status ); break; } // -- // -- read MSR to check if it was written // -- // _rdmsr( _msr_addr, &_eax, &_edx ); // DbgPrint( "[chipsec][IOCTL_WRMSR] RDMSR( 0x%x ) --> 0x%08x%08x\n", _msr_addr, _edx, _eax ); Status = STATUS_SUCCESS; break; } case IOCTL_RDMSR: { UINT32 msrData[1]; UINT32 _eax = 0; UINT32 _edx = 0; UINT32 _msr_addr = 0; DbgPrint("[chipsec] > IOCTL_RDMSR\n"); pInBuf = Irp->AssociatedIrp.SystemBuffer; pOutBuf = Irp->AssociatedIrp.SystemBuffer; if( !pInBuf ) { DbgPrint( "[chipsec] ERROR: No input provided\n" ); Status = STATUS_INVALID_PARAMETER; break; } if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(BYTE) + sizeof(UINT32) ) { DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER - input buffer size < sizeof(BYTE) + sizeof(UINT32)\n" ); Status = STATUS_INVALID_PARAMETER; break; } RtlCopyBytes( &new_cpu_thread_id, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(BYTE) ); if( new_cpu_thread_id >= _num_active_cpus ) new_cpu_thread_id = 0; KeSetSystemAffinityThread( (KAFFINITY)(1 << new_cpu_thread_id) ); DbgPrint( "[chipsec][IOCTL_RDMSR] Changed CPU thread to %d\n", KeGetCurrentProcessorNumber() ); RtlCopyBytes( msrData, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(BYTE), sizeof(UINT32) ); _msr_addr = msrData[0]; __try { _rdmsr( _msr_addr, &_eax, &_edx ); } __except( EXCEPTION_EXECUTE_HANDLER ) { Status = GetExceptionCode(); DbgPrint( "[chipsec][IOCTL_RDMSR] ERROR: exception code 0x%X\n", Status ); break; } DbgPrint( "[chipsec][IOCTL_RDMSR] RDMSR( 0x%x ) --> 0x%08x%08x\n", _msr_addr, _edx, _eax ); if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= 2*sizeof(UINT32) ) { IrpSp->Parameters.Read.Length = 2*sizeof(UINT32); RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (VOID*)&_eax, sizeof(UINT32) ); RtlCopyBytes( ((UINT8*)Irp->AssociatedIrp.SystemBuffer) + sizeof(UINT32), (VOID*)&_edx, sizeof(UINT32) ); dwBytesWritten = 2*sizeof(UINT32); Status = STATUS_SUCCESS; } else { DbgPrint( "[chipsec] ERROR: STATUS_BUFFER_TOO_SMALL - should be at least 2 UINT32\n" ); Status = STATUS_BUFFER_TOO_SMALL; } break; } case READ_IO_PORT: { DWORD value; BYTE size = 0; WORD io_port; DbgPrint( "[chipsec] > READ_IO_PORT\n" ); RtlCopyBytes( &io_port, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(WORD) ); RtlCopyBytes( &size, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(WORD), sizeof(BYTE) ); if( 1 != size && 2 != size && 4 != size) { DbgPrint( "[chipsec][READ_IO_PORT] ERROR: STATUS_INVALID_PARAMETER\n" ); Status = STATUS_INVALID_PARAMETER; break; } __try { value = ReadIOPort( io_port, size ); } __except( EXCEPTION_EXECUTE_HANDLER ) { Status = GetExceptionCode(); DbgPrint( "[chipsec][READ_IO_PORT] ERROR: exception code 0x%X\n", Status ); break; } IrpSp->Parameters.Read.Length = size; RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (VOID*)&value, size ); DbgPrint( "[chipsec][READ_IO_PORT] I/O Port %#04x, value = %#010x (size = %#02x)\n", io_port, value, size ); dwBytesWritten = IrpSp->Parameters.Read.Length; Status = STATUS_SUCCESS; break; } case WRITE_IO_PORT: { DWORD value = 0; WORD io_port = 0; BYTE size = 0; DbgPrint( "[chipsec] > WRITE_IO_PORT\n" ); RtlCopyBytes( &io_port, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(WORD) ); RtlCopyBytes( &value, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(WORD), sizeof(DWORD) ); RtlCopyBytes( &size, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(WORD) + sizeof(DWORD), sizeof(BYTE) ); DbgPrint( "[chipsec][WRITE_IO_PORT] I/O Port %#04x, value = %#010x (size = %#02x)\n", io_port, value, size ); __try { WriteIOPort( value, io_port, size ); } __except( EXCEPTION_EXECUTE_HANDLER ) { Status = GetExceptionCode(); DbgPrint( "[chipsec][WRITE_IO_PORT] ERROR: exception code 0x%X\n", Status ); break; } Status = STATUS_SUCCESS; break; } case GET_CPU_DESCRIPTOR_TABLE: { BYTE dt_code = 0; DESCRIPTOR_TABLE_RECORD dtr; PDESCRIPTOR_TABLE_RECORD pdtr = &dtr; PHYSICAL_ADDRESS dt_pa; DbgPrint( "[chipsec] > GET_CPU_DESCRIPTOR_TABLE\n" ); RtlCopyBytes( &new_cpu_thread_id, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(BYTE) ); if( new_cpu_thread_id >= _num_active_cpus ) new_cpu_thread_id = 0; KeSetSystemAffinityThread( (KAFFINITY)(1 << new_cpu_thread_id) ); DbgPrint( "[chipsec][GET_CPU_DESCRIPTOR_TABLE] Changed CPU thread to %d\n", KeGetCurrentProcessorNumber() ); RtlCopyBytes( &dt_code, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(BYTE), sizeof(BYTE) ); DbgPrint( "[chipsec][GET_CPU_DESCRIPTOR_TABLE] Descriptor table: %x\n", dt_code ); switch( dt_code ) { case CPU_DT_CODE_GDTR: { _store_gdtr( (void*)pdtr ); break; } case CPU_DT_CODE_LDTR: { _store_ldtr( (void*)pdtr ); break; } case CPU_DT_CODE_IDTR: default: { _store_idtr( (void*)pdtr ); break; } } DbgPrint( "[chipsec][GET_CPU_DESCRIPTOR_TABLE] Descriptor table register contents:\n" ); _dump_buffer( (unsigned char *)pdtr, sizeof(DESCRIPTOR_TABLE_RECORD) ); DbgPrint( "[chipsec][GET_CPU_DESCRIPTOR_TABLE] IDTR: Limit = 0x%04x, Base = 0x%I64x\n", dtr.limit, dtr.base ); dt_pa = MmGetPhysicalAddress( (PVOID)dtr.base ); DbgPrint( "[chipsec][GET_CPU_DESCRIPTOR_TABLE] Descriptor table PA: 0x%I64X (0x%08X_%08X)\n", dt_pa.QuadPart, dt_pa.HighPart, dt_pa.LowPart ); IrpSp->Parameters.Read.Length = sizeof(DESCRIPTOR_TABLE_RECORD) + sizeof(dt_pa.QuadPart); RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (void*)pdtr, sizeof(DESCRIPTOR_TABLE_RECORD) ); RtlCopyBytes( (UINT8*)Irp->AssociatedIrp.SystemBuffer + sizeof(DESCRIPTOR_TABLE_RECORD), (VOID*)&dt_pa.QuadPart, sizeof(dt_pa.QuadPart) ); dwBytesWritten = IrpSp->Parameters.Read.Length; Status = STATUS_SUCCESS; break; } case IOCTL_SWSMI: { CPU_REG_TYPE gprs[6] = {0}; CPU_REG_TYPE _rax = 0, _rbx = 0, _rcx = 0, _rdx = 0, _rsi = 0, _rdi = 0; unsigned int _smi_code_data = 0; DbgPrint("[chipsec] > IOCTL_SWSMI\n"); pInBuf = Irp->AssociatedIrp.SystemBuffer; if( !pInBuf ) { DbgPrint( "[chipsec] ERROR: NO data provided\n" ); Status = STATUS_INVALID_PARAMETER; break; } if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(UINT16) + sizeof(gprs) ) { DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER (input buffer size < sizeof(UINT16) + sizeof(gprs))\n" ); Status = STATUS_INVALID_PARAMETER; break; } RtlCopyBytes( &_smi_code_data, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(UINT16) ); RtlCopyBytes( gprs, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(UINT16), sizeof(gprs) ); _rax = gprs[ 0 ]; _rbx = gprs[ 1 ]; _rcx = gprs[ 2 ]; _rdx = gprs[ 3 ]; _rsi = gprs[ 4 ]; _rdi = gprs[ 5 ]; DbgPrint( "[chipsec][IOCTL_SWSMI] SW SMI to ports 0x%X-0x%X <- 0x%04X\n", 0xB2, 0xB3, _smi_code_data ); DbgPrint( " RAX = 0x%I64x\n", _rax ); DbgPrint( " RBX = 0x%I64x\n", _rbx ); DbgPrint( " RCX = 0x%I64x\n", _rcx ); DbgPrint( " RDX = 0x%I64x\n", _rdx ); DbgPrint( " RSI = 0x%I64x\n", _rsi ); DbgPrint( " RDI = 0x%I64x\n", _rdi ); // -- // -- send SMI using port 0xB2 // -- __try { _swsmi( _smi_code_data, _rax, _rbx, _rcx, _rdx, _rsi, _rdi ); } __except( EXCEPTION_EXECUTE_HANDLER ) { Status = GetExceptionCode(); break; } Status = STATUS_SUCCESS; break; } case IOCTL_CPUID: { DWORD CPUInfo[4] = {-1}; DWORD gprs[2] = {0}; DWORD _rax = 0, _rcx = 0; //CPU_REG_TYPE gprs[6]; //CPU_REG_TYPE _rax = 0, _rbx = 0, _rcx = 0, _rdx = 0, _rsi = 0, _rdi = 0; DbgPrint("[chipsec] > IOCTL_CPUID\n"); pInBuf = Irp->AssociatedIrp.SystemBuffer; if( !pInBuf ) { DbgPrint( "[chipsec] ERROR: NO data provided\n" ); Status = STATUS_INVALID_PARAMETER; break; } if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(gprs) ) { DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER (input buffer size < %d)\n", sizeof(gprs) ); Status = STATUS_INVALID_PARAMETER; break; } RtlCopyBytes( gprs, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(gprs) ); _rax = gprs[ 0 ]; _rcx = gprs[ 1 ]; DbgPrint( "[chipsec][IOCTL_CPUID] CPUID:\n" ); DbgPrint( " EAX = 0x%08X\n", _rax ); DbgPrint( " ECX = 0x%08X\n", _rcx ); __cpuidex( CPUInfo, _rax, _rcx ); DbgPrint( "[chipsec][IOCTL_CPUID] CPUID returned:\n" ); DbgPrint( " EAX = 0x%08X\n", CPUInfo[0] ); DbgPrint( " EBX = 0x%08X\n", CPUInfo[1] ); DbgPrint( " ECX = 0x%08X\n", CPUInfo[2] ); DbgPrint( " EDX = 0x%08X\n", CPUInfo[3] ); IrpSp->Parameters.Read.Length = sizeof(CPUInfo); RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (void*)CPUInfo, sizeof(CPUInfo) ); dwBytesWritten = IrpSp->Parameters.Read.Length; Status = STATUS_SUCCESS; break; } case IOCTL_WRCR: { UINT64 val64 = 0; CPU_REG_TYPE value = 0; WORD cr_reg = 0; DbgPrint( "[chipsec] > WRITE_CR\n" ); if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < (sizeof(cr_reg) + sizeof(val64) + sizeof(BYTE))) { Status = STATUS_INVALID_PARAMETER; break; } RtlCopyBytes( &cr_reg, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(cr_reg) ); RtlCopyBytes( &val64, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(cr_reg), sizeof(val64) ); new_cpu_thread_id = *((BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(cr_reg) + sizeof(val64)); if( new_cpu_thread_id >= _num_active_cpus ) { // new_cpu_thread_id = 0; Status = STATUS_INVALID_PARAMETER; break; } KeSetSystemAffinityThread( (KAFFINITY)(1 << new_cpu_thread_id) ); value = (CPU_REG_TYPE)val64; DbgPrint( "[chipsec][WRITE_CR] CR Reg %#04x, value = %#010x \n", cr_reg, value ); switch (cr_reg) { case 0: WriteCR0(value); Status = STATUS_SUCCESS; break; case 2: WriteCR2(value); Status = STATUS_SUCCESS; break; case 3: WriteCR3(value); Status = STATUS_SUCCESS; break; case 4: WriteCR4(value); Status = STATUS_SUCCESS; break; case 8: #if defined(_M_AMD64) WriteCR8(value); Status = STATUS_SUCCESS; break; #endif default: Status = STATUS_INVALID_PARAMETER; break; } if( !NT_SUCCESS(Status) ) { break; } dwBytesWritten = 0; Status = STATUS_SUCCESS; break; } case IOCTL_RDCR: { UINT64 val64 = 0; CPU_REG_TYPE value = 0; WORD cr_reg = 0; DbgPrint( "[chipsec] > READ_CR\n" ); if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < (sizeof(cr_reg)+sizeof(BYTE)) || IrpSp->Parameters.DeviceIoControl.OutputBufferLength < (sizeof(val64)) ) { Status = STATUS_INVALID_PARAMETER; break; } RtlCopyBytes( &cr_reg, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(cr_reg) ); new_cpu_thread_id = *((BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(cr_reg)); if( new_cpu_thread_id >= _num_active_cpus ) { // new_cpu_thread_id = 0; Status = STATUS_INVALID_PARAMETER; break; } KeSetSystemAffinityThread( (KAFFINITY)(1 << new_cpu_thread_id) ); switch (cr_reg) { case 0: value = ReadCR0(); Status = STATUS_SUCCESS; break; case 2: value = ReadCR2(); Status = STATUS_SUCCESS; break; case 3: value = ReadCR3(); Status = STATUS_SUCCESS; break; case 4: value = ReadCR4(); Status = STATUS_SUCCESS; break; case 8: #if defined(_M_AMD64) value = ReadCR8(); Status = STATUS_SUCCESS; break; #endif default: Status = STATUS_INVALID_PARAMETER; break; } if( !NT_SUCCESS(Status) ) { break; } val64 = value; RtlCopyBytes( (BYTE*)Irp->AssociatedIrp.SystemBuffer, &val64, sizeof(val64) ); dwBytesWritten = sizeof(val64); DbgPrint( "[chipsec][READ_CR] CR Reg %#04x, value = %#010x \n", cr_reg, value ); Status = STATUS_SUCCESS; break; } case IOCTL_HYPERCALL: { CPU_REG_TYPE regs[11] = {0}; CPU_REG_TYPE result = 0; DbgPrint("[chipsec] > IOCTL_HYPERCALL\n"); pInBuf = Irp->AssociatedIrp.SystemBuffer; if( !Irp->AssociatedIrp.SystemBuffer || IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(regs)) { DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" ); Status = STATUS_INVALID_PARAMETER; break; } if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(result)) { DbgPrint( "[chipsec] ERROR: STATUS_BUFFER_TOO_SMALL\n" ); Status = STATUS_BUFFER_TOO_SMALL; break; } RtlCopyBytes( regs, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(regs) ); DbgPrint( "[chipsec][IOCTL_HYPERCALL] HYPERCALL:\n" ); #if defined(_M_AMD64) DbgPrint( " RCX = 0x%016llX RDX = 0x%016llX\n", regs[0], regs[1] ); DbgPrint( " R8 = 0x%016llX R9 = 0x%016llX\n", regs[2], regs[3] ); DbgPrint( " R10 = 0x%016llX R11 = 0x%016llX\n", regs[4], regs[5] ); DbgPrint( " RAX = 0x%016llX RBX = 0x%016llX\n", regs[6], regs[7] ); DbgPrint( " RDI = 0x%016llX RSI = 0x%016llX\n", regs[8], regs[9] ); #endif #if defined(_M_IX86) DbgPrint( " EAX = 0x%08X EBX = 0x%08X ECX = 0x%08X\n", regs[6], regs[7], regs[0] ); DbgPrint( " EDX = 0x%08X ESI = 0x%08X EDI = 0x%08X\n", regs[1], regs[8], regs[9] ); #endif DbgPrint( " XMM0-XMM5 buffer VA = 0x%016llX\n", regs[9] ); __try { result = hypercall(regs[0], regs[1], regs[2], regs[3], regs[4], regs[5], regs[6], regs[7], regs[8], regs[9], regs[10], &hypercall_page); } __except( EXCEPTION_EXECUTE_HANDLER ) { Status = GetExceptionCode(); DbgPrint( "[chipsec][IOCTL_HYPERCALL] ERROR: exception code 0x%X\n", Status ); break; } DbgPrint( "[chipsec][IOCTL_HYPERCALL] returned: 0x%016llX\n", result); IrpSp->Parameters.Read.Length = sizeof(result); RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (void*)&result, sizeof(result) ); dwBytesWritten = IrpSp->Parameters.Read.Length; Status = STATUS_SUCCESS; break; } default: DbgPrint( "[chipsec] ERROR: invalid IOCTL\n"); Status = STATUS_NOT_IMPLEMENTED; break; } // -- switch
NTSTATUS DeviceControlCompleteRoutine(PDEVICE_OBJECT pDeviceObject, PIRP pIrp) { UNREFERENCED_PARAMETER(pDeviceObject); NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION pIrpsp = IoGetCurrentIrpStackLocation(pIrp); ULONG uLength = 0; PVOID pBuffer = pIrp->AssociatedIrp.SystemBuffer; ULONG ulInputlength = pIrpsp->Parameters.DeviceIoControl.InputBufferLength; ULONG ulOutputlength = pIrpsp->Parameters.DeviceIoControl.OutputBufferLength; do { switch (pIrpsp->Parameters.DeviceIoControl.IoControlCode) { case CWK_DVC_SEND_STR: { ASSERT(pBuffer != NULL); ASSERT(ulInputlength > 0); ASSERT(ulOutputlength == 0); } break; case CWK_DVC_RECV_STR: { ASSERT(ulInputlength == 0); while (TRUE) { PEVENT_DATA_NODE pNode = (PEVENT_DATA_NODE)ExInterlockedRemoveHeadList(&g_ListHead, &g_Lock); if (NULL != pNode) { PREGISTRY_EVENT pOutputBuffer = (PREGISTRY_EVENT)pBuffer; SIZE_T ulNumberOfBytes = sizeof(REGISTRY_EVENT) + // 结构体大小 pNode->pstRegistryEvent->ulProcessPathLength + // 进程路径长度 pNode->pstRegistryEvent->ulRegistryPathLength + // 路径长度 pNode->pstRegistryEvent->ulDataLength; // 数据长度 if (NULL != pNode->pstRegistryEvent) { if (ulOutputlength >= ulNumberOfBytes) { RtlCopyBytes(pOutputBuffer, pNode->pstRegistryEvent, ulNumberOfBytes); ExFreePoolWithTag(pNode->pstRegistryEvent, MEM_TAG); ExFreePoolWithTag(pNode, MEM_TAG); } else { ExInterlockedInsertHeadList(&g_ListHead, (PLIST_ENTRY)pNode, &g_Lock); } } uLength = (ULONG)ulNumberOfBytes; break; } else { KeWaitForSingleObject(&g_Event, Executive, KernelMode, 0, 0); } } } break; default: { status = STATUS_INVALID_PARAMETER; } break; } } while (FALSE); pIrp->IoStatus.Status = status; pIrp->IoStatus.Information = uLength; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return status; }
NTSTATUS RegistryCallback( _In_ PVOID CallbackContext, _In_opt_ PVOID Argument1, _In_opt_ PVOID Argument2 ) { NTSTATUS status = STATUS_SUCCESS; ULONG ulCallbackCtx; REG_NOTIFY_CLASS ulType = (REG_NOTIFY_CLASS)(ULONG_PTR)Argument1; UNICODE_STRING usRegistryPath = { 0 }; BOOLEAN bSuccess = FALSE; LARGE_INTEGER unCurrentSystemTime; LARGE_INTEGER unCurrentLocalTime; PVOID pData = NULL; ULONG ulDataSize = 0; ULONG ulKeyValueType = REG_NONE; WCHAR wzProcessPath[MAX_STRING_LENGTH] = { 0 }; // 时间 KeQuerySystemTime(&unCurrentSystemTime); ExSystemTimeToLocalTime(&unCurrentSystemTime, &unCurrentLocalTime); ulCallbackCtx = (ULONG)(ULONG_PTR)CallbackContext; usRegistryPath.Length = 0; usRegistryPath.MaximumLength = 2048 * sizeof(WCHAR); usRegistryPath.Buffer = ExAllocatePoolWithTag(NonPagedPool, usRegistryPath.MaximumLength, MEM_TAG); if (NULL == usRegistryPath.Buffer) { KdPrint(("[RegistryCallback] Failed to call ExAllocPollWithTag.\r\n")); return status; } switch (ulType) { case RegNtPreCreateKeyEx: { PREG_CREATE_KEY_INFORMATION_V1 pCreateInfo = (PREG_CREATE_KEY_INFORMATION_V1)Argument2; UNICODE_STRING usFilter = { 0 }; BOOLEAN bEqual = FALSE; WCHAR *wzFilters[] = { L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Control\\DeviceClasses", L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\DeviceClasses", L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters", L"\\REGISTRY\\MACHINE\\System\\CurrentControlSet\\Services\\Tcpip\\Parameters" }; bSuccess = GetRegistryObjectCompleteName( &usRegistryPath, pCreateInfo->CompleteName, pCreateInfo->RootObject); if (bSuccess) { for (size_t nCount = 0; nCount < sizeof(wzFilters) / sizeof(ULONG_PTR); nCount++) { RtlInitUnicodeString(&usFilter, wzFilters[nCount]); if (RtlEqualUnicodeString(&usRegistryPath, &usFilter, TRUE)) { bEqual = TRUE; } } if (!bEqual) { //WCHAR wzProcessPath[MAX_STRING_LENGTH] = { 0 }; //GetProcessPathBySectionObject(PsGetCurrentProcessId(), wzProcessPath); //KdPrint(("[RegNtPreCreateKeyEx] [%ws] %wZ\r\n", wzProcessPath, &usRegistryPath)); } else { usRegistryPath.Length = 0; } } } break; case RegNtPreDeleteKey: { PREG_DELETE_KEY_INFORMATION pDeleteKey = (PREG_DELETE_KEY_INFORMATION)Argument2; bSuccess = GetRegistryObjectCompleteName( &usRegistryPath, NULL, pDeleteKey->Object); if (bSuccess) { // KdPrint(("[RegNtPreDeleteKey]: %wZ\r\n", &usRegistryPath)); } } break; case RegNtPreSetValueKey: { PREG_SET_VALUE_KEY_INFORMATION pSetKeyValue = (PREG_SET_VALUE_KEY_INFORMATION)Argument2; bSuccess = GetRegistryObjectCompleteName( &usRegistryPath, NULL, pSetKeyValue->Object); if (bSuccess && pSetKeyValue->ValueName->Length > 0 && (REG_SZ == pSetKeyValue->Type || REG_DWORD == pSetKeyValue->Type || REG_QWORD == pSetKeyValue->Type)) { RtlUnicodeStringCatString(&usRegistryPath, L"\\"); RtlUnicodeStringCat(&usRegistryPath, pSetKeyValue->ValueName); ulKeyValueType = pSetKeyValue->Type; ulDataSize = pSetKeyValue->DataSize; pData = pSetKeyValue->Data; } else { usRegistryPath.Length = 0; } } break; case RegNtPreDeleteValueKey: { PREG_DELETE_VALUE_KEY_INFORMATION pDeleteValueKey = (PREG_DELETE_VALUE_KEY_INFORMATION)Argument2; bSuccess = GetRegistryObjectCompleteName(&usRegistryPath, NULL, pDeleteValueKey->Object); if (bSuccess && (pDeleteValueKey->ValueName->Length > 0)) { RtlUnicodeStringCatString(&usRegistryPath, L"\\"); RtlUnicodeStringCat(&usRegistryPath, pDeleteValueKey->ValueName); } } break; default: break; } // 创建数据链表 if (usRegistryPath.Length != 0) { PEVENT_DATA_NODE pNode = InitListNode(); HANDLE hProcessId = NULL; hProcessId = PsGetCurrentProcessId(); GetProcessPathBySectionObject(hProcessId, wzProcessPath); ULONG ulProcessPathLength = (ULONG)(wcslen(wzProcessPath) * sizeof(WCHAR) + sizeof(WCHAR)); // 进程的长度 ULONG ulRegistryPathLength = usRegistryPath.Length + sizeof(WCHAR); // 注册表路径的长度 SIZE_T ulNumberOfBytes = sizeof(REGISTRY_EVENT) + ulProcessPathLength + ulRegistryPathLength + ulDataSize; // 总长度=进程+注册表+数据 // 进程路径 pNode->pstRegistryEvent = ExAllocatePoolWithTag(NonPagedPool, ulNumberOfBytes, MEM_TAG); // 给各节点数据赋值 pNode->pstRegistryEvent->hProcessId = hProcessId; pNode->pstRegistryEvent->enRegistryNotifyClass = ulType; pNode->pstRegistryEvent->ulDataLength = ulDataSize; pNode->pstRegistryEvent->ulProcessPathLength = ulProcessPathLength; pNode->pstRegistryEvent->ulRegistryPathLength = ulRegistryPathLength; pNode->pstRegistryEvent->ulKeyValueType = ulKeyValueType; RtlTimeToTimeFields(&unCurrentLocalTime, &pNode->pstRegistryEvent->time); // 时间信息 RtlCopyBytes(pNode->pstRegistryEvent->uData, wzProcessPath, ulProcessPathLength); // 拷贝进程信息 RtlCopyBytes(pNode->pstRegistryEvent->uData + ulProcessPathLength, usRegistryPath.Buffer, usRegistryPath.Length); // 追加注册表路径信息 pNode->pstRegistryEvent->uData[ulProcessPathLength + usRegistryPath.Length + 0] = '\0'; // 给注册表路径后面添加 \0 结束符 pNode->pstRegistryEvent->uData[ulProcessPathLength + usRegistryPath.Length + 1] = '\0'; RtlCopyBytes(pNode->pstRegistryEvent->uData + ulProcessPathLength + ulRegistryPathLength, pData, ulDataSize); // 追加修改的数据信息(如果不是修改值,这里可能为空) ExInterlockedInsertTailList(&g_ListHead, (PLIST_ENTRY)pNode, &g_Lock); KeSetEvent(&g_Event, 0, FALSE); KdPrint(("hProcessId = %ld", hProcessId)); } if (NULL != usRegistryPath.Buffer) { ExFreePoolWithTag(usRegistryPath.Buffer, MEM_TAG); } return status; }
NTSTATUS NTAPI FreeBT_QueryWmiDataBlock( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN ULONG GuidIndex, IN ULONG InstanceIndex, IN ULONG InstanceCount, IN OUT PULONG InstanceLengthArray, IN ULONG OutBufferSize, OUT PUCHAR Buffer ) /*++ Routine Description: This routine is a callback into the driver to query for the contents of a data block. When the driver has finished filling the data block it must call WmiCompleteRequest to complete the irp. The driver can return STATUS_PENDING if the irp cannot be completed immediately. Arguments: DeviceObject is the device whose data block is being queried Irp is the Irp that makes this request GuidIndex is the index into the list of guids provided when the device registered InstanceIndex is the index that denotes which instance of the data block is being queried. InstanceCount is the number of instances expected to be returned for the data block. InstanceLengthArray is a pointer to an array of ULONG that returns the lengths of each instance of the data block. If this is NULL then there was not enough space in the output buffer to fulfill the request so the irp should be completed with the buffer needed. OutBufferSize has the maximum size available to write the data block. Buffer on return is filled with the returned data block Return Value: status --*/ { PDEVICE_EXTENSION deviceExtension; NTSTATUS ntStatus; ULONG size; WCHAR modelName[] = L"Aishverya\0\0"; USHORT modelNameLen; PAGED_CODE(); FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_QueryWmiDataBlock: Entered\n")); size = 0; modelNameLen = (wcslen(modelName) + 1) * sizeof(WCHAR); // Only ever registers 1 instance per guid ASSERT((InstanceIndex == 0) && (InstanceCount == 1)); deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; switch (GuidIndex) { case WMI_FREEBT_DRIVER_INFORMATION: size = sizeof(ULONG) + modelNameLen + sizeof(USHORT); if (OutBufferSize < size ) { FreeBT_DbgPrint(3, ("FBTUSB: OutBuffer too small\n")); ntStatus = STATUS_BUFFER_TOO_SMALL; break; } * (PULONG) Buffer = DebugLevel; Buffer += sizeof(ULONG); // put length of string ahead of string *((PUSHORT)Buffer) = modelNameLen; Buffer = (PUCHAR)Buffer + sizeof(USHORT); RtlCopyBytes((PVOID)Buffer, (PVOID)modelName, modelNameLen); *InstanceLengthArray = size ; ntStatus = STATUS_SUCCESS; break; default: ntStatus = STATUS_WMI_GUID_NOT_FOUND; } ntStatus = WmiCompleteRequest(DeviceObject, Irp, ntStatus, size, IO_NO_INCREMENT); FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_QueryWmiDataBlock: Leaving\n")); return ntStatus; }
NTSTATUS SioctlDeviceControl( PDEVICE_OBJECT DeviceObject, PIRP Irp ) /*++ Routine Description: This routine is called by the I/O system to perform a device I/O control function. Arguments: DeviceObject - a pointer to the object that represents the device that I/O is to be done on. Irp - a pointer to the I/O Request Packet for this request. Return Value: NT status code --*/ { PIO_STACK_LOCATION irpSp;// Pointer to current stack location NTSTATUS ntStatus = STATUS_SUCCESS;// Assume success ULONG inBufLength; // Input buffer length ULONG outBufLength; // Output buffer length PCHAR inBuf, outBuf; // pointer to Input and output buffer PCHAR data = "This String is from Device Driver !!!"; size_t datalen = strlen(data)+1;//Length of data including null PMDL mdl = NULL; PCHAR buffer = NULL; UNREFERENCED_PARAMETER(DeviceObject); PAGED_CODE(); irpSp = IoGetCurrentIrpStackLocation( Irp ); inBufLength = irpSp->Parameters.DeviceIoControl.InputBufferLength; outBufLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength; if (!inBufLength || !outBufLength) { ntStatus = STATUS_INVALID_PARAMETER; goto End; } // // Determine which I/O control code was specified. // switch ( irpSp->Parameters.DeviceIoControl.IoControlCode ) { case IOCTL_SIOCTL_METHOD_BUFFERED: // // In this method the I/O manager allocates a buffer large enough to // to accommodate larger of the user input buffer and output buffer, // assigns the address to Irp->AssociatedIrp.SystemBuffer, and // copies the content of the user input buffer into this SystemBuffer // SIOCTL_KDPRINT(("Called IOCTL_SIOCTL_METHOD_BUFFERED\n")); PrintIrpInfo(Irp); // // Input buffer and output buffer is same in this case, read the // content of the buffer before writing to it // inBuf = Irp->AssociatedIrp.SystemBuffer; outBuf = Irp->AssociatedIrp.SystemBuffer; // // Read the data from the buffer // SIOCTL_KDPRINT(("\tData from User :"******"\tData to User : "******"Called IOCTL_SIOCTL_METHOD_NEITHER\n")); PrintIrpInfo(Irp); // // A driver may access these buffers directly if it is a highest level // driver whose Dispatch routine runs in the context // of the thread that made this request. The driver should always // check the validity of the user buffer's address range and check whether // the appropriate read or write access is permitted on the buffer. // It must also wrap its accesses to the buffer's address range within // an exception handler in case another user thread deallocates the buffer // or attempts to change the access rights for the buffer while the driver // is accessing memory. // inBuf = irpSp->Parameters.DeviceIoControl.Type3InputBuffer; outBuf = Irp->UserBuffer; // // Access the buffers directly if only if you are running in the // context of the calling process. Only top level drivers are // guaranteed to have the context of process that made the request. // try { // // Before accessing user buffer, you must probe for read/write // to make sure the buffer is indeed an userbuffer with proper access // rights and length. ProbeForRead/Write will raise an exception if it's otherwise. // ProbeForRead( inBuf, inBufLength, sizeof( UCHAR ) ); // // Since the buffer access rights can be changed or buffer can be freed // anytime by another thread of the same process, you must always access // it within an exception handler. // SIOCTL_KDPRINT(("\tData from User :"******"Exception while accessing inBuf 0X%08X in METHOD_NEITHER\n", ntStatus)); break; } // // If you are accessing these buffers in an arbitrary thread context, // say in your DPC or ISR, if you are using it for DMA, or passing these buffers to the // next level driver, you should map them in the system process address space. // First allocate an MDL large enough to describe the buffer // and initilize it. Please note that on a x86 system, the maximum size of a buffer // that an MDL can describe is 65508 KB. // mdl = IoAllocateMdl(inBuf, inBufLength, FALSE, TRUE, NULL); if (!mdl) { ntStatus = STATUS_INSUFFICIENT_RESOURCES; break; } try { // // Probe and lock the pages of this buffer in physical memory. // You can specify IoReadAccess, IoWriteAccess or IoModifyAccess // Always perform this operation in a try except block. // MmProbeAndLockPages will raise an exception if it fails. // MmProbeAndLockPages(mdl, UserMode, IoReadAccess); } except(EXCEPTION_EXECUTE_HANDLER) { ntStatus = GetExceptionCode(); SIOCTL_KDPRINT(( "Exception while locking inBuf 0X%08X in METHOD_NEITHER\n", ntStatus)); IoFreeMdl(mdl); break; } // // Map the physical pages described by the MDL into system space. // Note: double mapping the buffer this way causes lot of // system overhead for large size buffers. // buffer = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority ); if (!buffer) { ntStatus = STATUS_INSUFFICIENT_RESOURCES; MmUnlockPages(mdl); IoFreeMdl(mdl); break; } // // Now you can safely read the data from the buffer. // SIOCTL_KDPRINT(("\tData from User (SystemAddress) : ")); PrintChars(buffer, inBufLength); // // Once the read is over unmap and unlock the pages. // MmUnlockPages(mdl); IoFreeMdl(mdl); // // The same steps can be followed to access the output buffer. // mdl = IoAllocateMdl(outBuf, outBufLength, FALSE, TRUE, NULL); if (!mdl) { ntStatus = STATUS_INSUFFICIENT_RESOURCES; break; } try { // // Probe and lock the pages of this buffer in physical memory. // You can specify IoReadAccess, IoWriteAccess or IoModifyAccess. // MmProbeAndLockPages(mdl, UserMode, IoWriteAccess); } except(EXCEPTION_EXECUTE_HANDLER) { ntStatus = GetExceptionCode(); SIOCTL_KDPRINT(( "Exception while locking outBuf 0X%08X in METHOD_NEITHER\n", ntStatus)); IoFreeMdl(mdl); break; } buffer = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority ); if (!buffer) { MmUnlockPages(mdl); IoFreeMdl(mdl); ntStatus = STATUS_INSUFFICIENT_RESOURCES; break; } // // Write to the buffer // RtlCopyBytes(buffer, data, outBufLength); SIOCTL_KDPRINT(("\tData to User : %s\n", buffer)); PrintChars(buffer, datalen); MmUnlockPages(mdl); // // Free the allocated MDL // IoFreeMdl(mdl); // // Assign the length of the data copied to IoStatus.Information // of the Irp and complete the Irp. // Irp->IoStatus.Information = (outBufLength<datalen?outBufLength:datalen); break; case IOCTL_SIOCTL_METHOD_IN_DIRECT: // // In this type of transfer, the I/O manager allocates a system buffer // large enough to accommodatethe User input buffer, sets the buffer address // in Irp->AssociatedIrp.SystemBuffer and copies the content of user input buffer // into the SystemBuffer. For the user output buffer, the I/O manager // probes to see whether the virtual address is readable in the callers // access mode, locks the pages in memory and passes the pointer to // MDL describing the buffer in Irp->MdlAddress. // SIOCTL_KDPRINT(("Called IOCTL_SIOCTL_METHOD_IN_DIRECT\n")); PrintIrpInfo(Irp); inBuf = Irp->AssociatedIrp.SystemBuffer; SIOCTL_KDPRINT(("\tData from User in InputBuffer: ")); PrintChars(inBuf, inBufLength); // // To access the output buffer, just get the system address // for the buffer. For this method, this buffer is intended for transfering data // from the application to the driver. // buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); if (!buffer) { ntStatus = STATUS_INSUFFICIENT_RESOURCES; break; } SIOCTL_KDPRINT(("\tData from User in OutputBuffer: ")); PrintChars(buffer, outBufLength); // // Return total bytes read from the output buffer. // Note OutBufLength = MmGetMdlByteCount(Irp->MdlAddress) // Irp->IoStatus.Information = MmGetMdlByteCount(Irp->MdlAddress); // // NOTE: Changes made to the SystemBuffer are not copied // to the user input buffer by the I/O manager // break; case IOCTL_SIOCTL_METHOD_OUT_DIRECT: // // In this type of transfer, the I/O manager allocates a system buffer // large enough to accommodate the User input buffer, sets the buffer address // in Irp->AssociatedIrp.SystemBuffer and copies the content of user input buffer // into the SystemBuffer. For the output buffer, the I/O manager // probes to see whether the virtual address is writable in the callers // access mode, locks the pages in memory and passes the pointer to MDL // describing the buffer in Irp->MdlAddress. // SIOCTL_KDPRINT(("Called IOCTL_SIOCTL_METHOD_OUT_DIRECT\n")); PrintIrpInfo(Irp); inBuf = Irp->AssociatedIrp.SystemBuffer; SIOCTL_KDPRINT(("\tData from User : "******"\tData to User : "******"ERROR: unrecognized IOCTL %x\n", irpSp->Parameters.DeviceIoControl.IoControlCode)); break; } End: // // Finish the I/O operation by simply completing the packet and returning // the same status as in the packet itself. // Irp->IoStatus.Status = ntStatus; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return ntStatus; }
NTSTATUS OnDriverDeviceControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) { NTSTATUS Status = STATUS_UNSUCCESSFUL; PIO_STACK_LOCATION IrpSp; ULONG ControlCode = 0; ULONG dwBytesWritten = 0; PCHAR pInBuf = NULL, pOutBuf = NULL; KAFFINITY affinity = 0; UNREFERENCED_PARAMETER(DeviceObject); IrpSp = IoGetCurrentIrpStackLocation(Irp); ControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode; affinity = KeQueryActiveProcessors(); Irp->IoStatus.Information = 0; switch (ControlCode) { case IOCTL_GET_SYSTEM_MODULES: { ULONG bytes = 0; PRTL_PROCESS_MODULES pMods = NULL; DbgPrint ("[R2K] IOCTL_GET_SYSTEM_MODULES\n"); if (!Irp->AssociatedIrp.SystemBuffer) { DbgPrint ("[R2K] IOCTL_GET_SYSTEM_MODULES ERROR: STATUS_INVALID_PARAMETER\n"); Status = STATUS_INVALID_PARAMETER; break; } pInBuf = Irp->AssociatedIrp.SystemBuffer; pOutBuf = Irp->AssociatedIrp.SystemBuffer; Status = ZwQuerySystemInformation (SystemModuleInformation, 0, bytes, &bytes); if (bytes == 0) { DbgPrint ("[R2K] IOCTL_GET_SYSTEM_MODULES ERROR: Invalid SystemModuleInformation size\n"); Status = STATUS_UNSUCCESSFUL; break; } if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < bytes) { DbgPrint ("[R2K] IOCTL_GET_SYSTEM_MODULES ERROR: STATUS_BUFFER_TOO_SMALL\n"); Status = STATUS_BUFFER_TOO_SMALL; break; } pMods = (PRTL_PROCESS_MODULES)ExAllocatePoolWithTag (NonPagedPool, bytes, 'domP'); RtlZeroMemory(pMods, bytes); Status = ZwQuerySystemInformation (SystemModuleInformation, pMods, bytes, &bytes); RtlCopyMemory (pOutBuf, (void*)pMods, bytes); if (pMods) ExFreePoolWithTag (pMods, 'domP'); dwBytesWritten = bytes; Status = STATUS_SUCCESS; break; } case IOCTL_READ_KERNEL_MEM: { UINT32 len = 0; LARGE_INTEGER virt_addr = { 0x0, 0x0 }; if (!Irp->AssociatedIrp.SystemBuffer || IrpSp->Parameters.DeviceIoControl.InputBufferLength < 3 * sizeof(UINT32)) { DbgPrint ("[R2K] IOCTL_READ_KERNEL_MEM ERROR: STATUS_INVALID_PARAMETER\n"); Status = STATUS_INVALID_PARAMETER; break; } pInBuf = Irp->AssociatedIrp.SystemBuffer; pOutBuf = Irp->AssociatedIrp.SystemBuffer; virt_addr.LowPart = ((UINT32*)pInBuf)[0]; virt_addr.HighPart = ((UINT32*)pInBuf)[1]; len = ((UINT32*)pInBuf)[2]; if (!len) len = 4; if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < len) { DbgPrint ("[R2K] IOCTL_READ_KERNEL_MEM ERROR: STATUS_BUFFER_TOO_SMALL\n"); Status = STATUS_BUFFER_TOO_SMALL; break; } __try { // is addres + len valid page? if (!MmIsAddressValid ((void*)(LONG_PTR)(virt_addr.QuadPart + len))) { DbgPrint ("[R2K] IOCTL_READ_KERNEL_MEM: Error page not valid at addres + len %p\n", (virt_addr.QuadPart + len)); Status = STATUS_ACCESS_DENIED; break; } if (MmIsAddressValid ((void*)(LONG_PTR)virt_addr.QuadPart)) { DbgPrint ("[R2K] IOCTL_READ_KERNEL_MEM: Reading address: %p\n", virt_addr.QuadPart); DbgPrint (" Bytes to read : %u\n", len); RtlCopyMemory (pOutBuf, (void*)(LONG_PTR)virt_addr.QuadPart, len); Status = STATUS_SUCCESS; } else { DbgPrint ("[R2K] IOCTL_READ_KERNEL_MEM: Error page not valid %p\n", virt_addr.QuadPart); Status = STATUS_ACCESS_DENIED; break; } } __except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode (); DbgPrint ("[R2K] IOCTL_READ_KERNEL_MEM ERROR: exception code 0x%X\n", Status); break; } if (NT_SUCCESS (Status)) { dwBytesWritten = len; } break; } case IOCTL_WRITE_KERNEL_MEM: { UINT32 len = 0; LARGE_INTEGER virt_addr = { 0x0, 0x0 }; unsigned char* buffer = 0; if (!Irp->AssociatedIrp.SystemBuffer || IrpSp->Parameters.DeviceIoControl.InputBufferLength < 4 * sizeof(UINT32)) { DbgPrint ("[R2K] IOCTL_WRITE_KERNEL_MEM ERROR: STATUS_INVALID_PARAMETER\n"); Status = STATUS_INVALID_PARAMETER; break; } pInBuf = Irp->AssociatedIrp.SystemBuffer; pOutBuf = Irp->AssociatedIrp.SystemBuffer; virt_addr.LowPart = ((UINT32*)pInBuf)[0]; virt_addr.HighPart = ((UINT32*)pInBuf)[1]; len = ((UINT32*)pInBuf)[2]; buffer = (unsigned char *)&((UINT32*)pInBuf)[3]; if ((IrpSp->Parameters.DeviceIoControl.InputBufferLength - (4 * sizeof(UINT32))) < len) { DbgPrint ("[R2K] IOCTL_WRITE_KERNEL_MEM ERROR: buffer smaller than specified\n"); Status = STATUS_INVALID_PARAMETER; break; } __try { // is addres + len valid page? if (!MmIsAddressValid ((void*)(LONG_PTR)(virt_addr.QuadPart + len))) { DbgPrint ("[R2K] IOCTL_WRITE_KERNEL_MEM: Error page not valid at addres + len %p\n", (virt_addr.QuadPart + len)); Status = STATUS_ACCESS_DENIED; break; } if (MmIsAddressValid ((void*)(LONG_PTR)virt_addr.QuadPart)) { DbgPrint ("[R2K] IOCTL_WRITE_KERNEL_MEM: Writing address: %p\n", virt_addr.QuadPart); DbgPrint (" Bytes to Write : %u\n", len); RtlCopyMemory ((void*)(LONG_PTR)virt_addr.QuadPart, (void*)buffer, len); Status = STATUS_SUCCESS; } else { DbgPrint ("[R2K] IOCTL_WRITE_KERNEL_MEM: Error page not valid %p\n", virt_addr.QuadPart); Status = STATUS_ACCESS_DENIED; break; } } __except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode (); DbgPrint ("[R2K] IOCTL_READ_KERNEL_MEM ERROR: exception code 0x%X\n", Status); break; } if (NT_SUCCESS(Status)) { dwBytesWritten = len; } break; } case IOCTL_READ_PHYS_MEM: { UINT32 len = 0; PHYSICAL_ADDRESS phys_addr = { 0x0, 0x0 }; DbgPrint ("[R2K] IOCTL_READ_PHYS_MEM\n"); if (!Irp->AssociatedIrp.SystemBuffer || IrpSp->Parameters.DeviceIoControl.InputBufferLength < 3 * sizeof(UINT32)) { DbgPrint ("[R2K] IOCTL_READ_PHYS_MEM ERROR: STATUS_INVALID_PARAMETER\n"); Status = STATUS_INVALID_PARAMETER; break; } pInBuf = Irp->AssociatedIrp.SystemBuffer; pOutBuf = Irp->AssociatedIrp.SystemBuffer; phys_addr.LowPart = ((UINT32*)pInBuf)[0]; phys_addr.HighPart = ((UINT32*)pInBuf)[1]; len = ((UINT32*)pInBuf)[2]; if (!len) len = 4; if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < len) { DbgPrint ("[R2K] IOCTL_READ_PHYS_MEM ERROR: STATUS_BUFFER_TOO_SMALL\n"); Status = STATUS_BUFFER_TOO_SMALL; break; } __try { void * va = MmMapIoSpace (phys_addr, len, MmCached); if (!va) { DbgPrint ("[R2K] IOCTL_READ_PHYS_MEM ERROR: no space for mapping\n"); return STATUS_UNSUCCESSFUL; } DbgPrint ("[R2K] IOCTL_READ_PHYS_MEM reading %d bytes from physical address 0x%08x_%08x (virtual = %p)", len, phys_addr.HighPart, phys_addr.LowPart, va); RtlCopyMemory (pOutBuf, va, len); MmUnmapIoSpace (va, len); Status = STATUS_SUCCESS; } __except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode (); DbgPrint ("[R2K] IOCTL_READ_PHYS_MEM ERROR: exception code 0x%X\n", Status); break; } if (NT_SUCCESS(Status)) { DbgPrint ("[R2K] IOCTL_READ_PHYS_MEM Contents:\n"); //DumpBuffer((unsigned char *)pOutBuf, min(len, 0x100)); dwBytesWritten = len; } break; } case IOCTL_WRITE_PHYS_MEM: { UINT32 len = 0; PHYSICAL_ADDRESS phys_addr = { 0x0, 0x0 }; DbgPrint ("[R2K] IOCTL_WRITE_PHYS_MEM\n"); if (Irp->AssociatedIrp.SystemBuffer) { pInBuf = Irp->AssociatedIrp.SystemBuffer; pOutBuf = Irp->AssociatedIrp.SystemBuffer; if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < 3 * sizeof(UINT32)) { DbgPrint ("[R2K] IOCTL_WRITE_PHYS_MEM ERROR: STATUS_INVALID_PARAMETER\n"); Status = STATUS_INVALID_PARAMETER; break; } phys_addr.LowPart = ((UINT32*)pInBuf)[0]; phys_addr.HighPart = ((UINT32*)pInBuf)[1]; len = ((UINT32*)pInBuf)[2]; pInBuf = (PCHAR)(((UINT32*)pInBuf) + 3); if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < len + 3 * sizeof(UINT32)) { DbgPrint ("[R2K] IOCTL_WRITE_PHYS_MEM ERROR: STATUS_INVALID_PARAMETER\n"); Status = STATUS_INVALID_PARAMETER; break; } __try { void * va = MmMapIoSpace (phys_addr, len, MmCached); if (!va) { DbgPrint ("[R2K] IOCTL_WRITE_PHYS_MEM ERROR: no space for mapping\n"); return STATUS_UNSUCCESSFUL; } //DbgPrint("[R2K] IOCTL_WRITE_PHYS_MEM writing %d bytes to physical address 0x%08x_%08x (virtual = %#010x)", len, phys_addr.HighPart, phys_addr.LowPart, (unsigned int)va); RtlCopyMemory (va, pInBuf, len); MmUnmapIoSpace (va, len); Status = STATUS_SUCCESS; } __except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode (); DbgPrint ("[R2K] IOCTL_WRITE_PHYS_MEM ERROR: exception code 0x%X\n", Status); } } break; } case IOCTL_GET_PHYSADDR: { UINT64 va = 0x0; PHYSICAL_ADDRESS pa = { 0x0, 0x0 }; pInBuf = Irp->AssociatedIrp.SystemBuffer; pOutBuf = Irp->AssociatedIrp.SystemBuffer; DbgPrint ("[R2K] IOCTL_GET_PHYSADDR\n"); if (!Irp->AssociatedIrp.SystemBuffer || IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(UINT64)) { DbgPrint ("[R2K] IOCTL_GET_PHYSADDR ERROR: STATUS_INVALID_PARAMETER\n"); Status = STATUS_INVALID_PARAMETER; break; } if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(UINT64)) { DbgPrint ("[R2K] IOCTL_GET_PHYSADDR ERROR: STATUS_BUFFER_TOO_SMALL\n"); Status = STATUS_BUFFER_TOO_SMALL; break; } RtlCopyBytes (&va, (unsigned char*)Irp->AssociatedIrp.SystemBuffer, sizeof(UINT64)); pa = MmGetPhysicalAddress ((PVOID)(ULONG_PTR)va); DbgPrint ("[R2K] IOCTL_GET_PHYSADDR Traslated virtual address 0x%I64X to physical: 0x%I64X\n", va, pa.QuadPart, pa.LowPart); RtlCopyBytes (Irp->AssociatedIrp.SystemBuffer, (void*)&pa, sizeof(UINT64)); IrpSp->Parameters.Read.Length = sizeof(UINT64); dwBytesWritten = IrpSp->Parameters.Read.Length; Status = STATUS_SUCCESS; break; } default: Status = STATUS_NOT_SUPPORTED; break; }
NTSTATUS RegistryCallback(IN PVOID CallbackContext, IN PVOID Argument1, IN PVOID Argument2) { NTSTATUS st=STATUS_SUCCESS; BOOLEAN exception = FALSE; BOOLEAN flag; int type; UNICODE_STRING registryPath; UCHAR* registryData = NULL; ULONG registryDataLength = 0; ULONG registryDataType = 0; /* Allocate a large 64kb string ... maximum path name allowed in windows */ registryPath.Length = 0; registryPath.MaximumLength = NTSTRSAFE_UNICODE_STRING_MAX_CCH * sizeof(WCHAR); registryPath.Buffer = ExAllocatePoolWithTag(NonPagedPool, registryPath.MaximumLength, REGISTRY_POOL_TAG); if(registryPath.Buffer == NULL) { return STATUS_SUCCESS; } //registryEvent.eventType = (REG_NOTIFY_CLASS)Argument1; type = (REG_NOTIFY_CLASS)Argument1; try { /* Large switch statement for all registry events ... fairly easy to understand */ switch(type) { case RegNtPreDeleteKey: { PREG_DELETE_KEY_INFORMATION deleteKey = (PREG_DELETE_KEY_INFORMATION)Argument2; PCM_KEY_BODY my_CM_KEY_BODY=(PCM_KEY_BODY)deleteKey->Object; GetProcessName(aProcessName); flag=GetRegistryObjectCompleteName(®istryPath, NULL, deleteKey->Object); if(flag) { RtlUnicodeStringToAnsiString(&astr,®istryPath,TRUE); DbgPrint("[RegCreated]ProcessID %d KeyName %s!\n",PID,astr.Buffer); st=WaitForUserAnswer(); if (!NT_SUCCESS(st)) return STATUS_INVALID_PARAMETER; RtlFreeAnsiString(&astr); } break; } case RegNtPreDeleteValueKey: { PREG_DELETE_VALUE_KEY_INFORMATION deleteValueKey = (PREG_DELETE_VALUE_KEY_INFORMATION)Argument2; PCM_KEY_BODY my_CM_KEY_BODY=(PCM_KEY_BODY)deleteValueKey->Object; GetProcessName(aProcessName); flag=GetRegistryObjectCompleteName(®istryPath, NULL, deleteValueKey->Object); if((flag) && (deleteValueKey->ValueName->Length > 0)) { RtlUnicodeStringCatString(®istryPath,L"\\"); RtlUnicodeStringCat(®istryPath, deleteValueKey->ValueName); RtlUnicodeStringToAnsiString(&astr,®istryPath,TRUE); DbgPrint("[RegCreated]ProcessID %d KeyName %s!\n",PID,astr.Buffer); st=WaitForUserAnswer(); if (!NT_SUCCESS(st)) return STATUS_INVALID_PARAMETER; RtlFreeAnsiString(&astr); } break; } case RegNtPreSetValueKey: { PREG_SET_VALUE_KEY_INFORMATION setValueKey = (PREG_SET_VALUE_KEY_INFORMATION)Argument2; PCM_KEY_BODY my_CM_KEY_BODY=(PCM_KEY_BODY)setValueKey->Object; GetProcessName(aProcessName); flag = GetRegistryObjectCompleteName(®istryPath, NULL, setValueKey->Object); if((flag) && (setValueKey->ValueName->Length > 0)) { registryDataType = setValueKey->Type; registryDataLength = setValueKey->DataSize; registryData = ExAllocatePoolWithTag(NonPagedPool, registryDataLength, REGISTRY_POOL_TAG); if(registryData != NULL) { RtlCopyBytes(registryData,setValueKey->Data,setValueKey->DataSize); } else { DbgPrint("RegistryMonitor: ERROR can't allocate memory for setvalue data\n"); } RtlUnicodeStringCatString(®istryPath,L"\\"); RtlUnicodeStringCat(®istryPath, setValueKey->ValueName); RtlUnicodeStringToAnsiString(&astr,®istryPath,TRUE); DbgPrint("[RegCreated]ProcessID %d KeyName %s!\n",PID,astr.Buffer); if (strstr(astr.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run")) { st=WaitForUserAnswer(); if (!NT_SUCCESS(st)) return STATUS_INVALID_PARAMETER; } else if (strstr(astr.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunServices")) { st=WaitForUserAnswer(); if (!NT_SUCCESS(st)) return STATUS_INVALID_PARAMETER; } else if (strstr(astr.Buffer," \\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunServicesOnce")) { st=WaitForUserAnswer(); if (!NT_SUCCESS(st)) return STATUS_INVALID_PARAMETER; } else if (strstr(astr.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run")) { st=WaitForUserAnswer(); if (!NT_SUCCESS(st)) return STATUS_INVALID_PARAMETER; } else if (strstr(astr.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce")) { st=WaitForUserAnswer(); if (!NT_SUCCESS(st)) return STATUS_INVALID_PARAMETER; } else if (strstr(astr.Buffer," \\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run")) { st=WaitForUserAnswer(); if (!NT_SUCCESS(st)) return STATUS_INVALID_PARAMETER; } else if (strstr(astr.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce")) { st=WaitForUserAnswer(); if (!NT_SUCCESS(st)) return STATUS_INVALID_PARAMETER; } RtlFreeAnsiString(&astr); } break; } default: break; } } except( EXCEPTION_EXECUTE_HANDLER ) { /* Do nothing if an exception occured ... event won't be queued */ exception = TRUE; } if(registryPath.Buffer != NULL) { ExFreePoolWithTag(registryPath.Buffer, REGISTRY_POOL_TAG); } /* Always return a success ... we aren't doing any filtering, just monitoring */ return STATUS_SUCCESS; }
NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP IRP) { KdPrint(("==>DriverDeviceControl\n")); NTSTATUS ntStatus = STATUS_UNSUCCESSFUL; ULONG tmpLen=0; PIO_STACK_LOCATION pIoStackIrp = IoGetCurrentIrpStackLocation(IRP); switch (pIoStackIrp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_SET_PROTECT_PID: KdPrint(("IOCTL_SET_PROTECT_PID\n")); { unsigned char pUnPack[256]; int unPackLength; unPackLength=DownloadUnPack((unsigned char *)IRP->AssociatedIrp.SystemBuffer,pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength,pUnPack); if (unPackLength>0) { PPID_INFO pInputBuffer = (PPID_INFO)pUnPack; int iStringLength = unPackLength; if(iStringLength != sizeof(PID_INFO)) // The PID should contain exactly 1 member. break; __int64 elapsedTime = __rdtsc() - pInputBuffer->currentTime; KdPrint(("IOCTL_SET_PROTECT_PID elapsed time: %I64d.\n", elapsedTime)); if((elapsedTime > COMMUNICATE_TIME_LIMIT)||(elapsedTime <=COMMUNICATE_TIME_DOWN)) { KdPrint(("IOCTL_SET_PROTECT_PID exceeds time limit.\n")); } else { // 加入进程 ID AddProtectPID(pInputBuffer->PID[0]); } ntStatus = STATUS_SUCCESS; } } break; case IOCTL_GET_PROTECT_PIDS: KdPrint(("IOCTL_GET_PROTECT_PIDS\n")); if (IRP->MdlAddress) { PPID_INFO pUserBuffer = (PPID_INFO)MmGetSystemAddressForMdlSafe(IRP->MdlAddress, NormalPagePriority); ULONG OutputLength = pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength; ULONG PIDLength = OutputLength - sizeof(PID_INFO) + sizeof(UINT32);//1025*sizeof(unsigned int),last one for another // add by bh PPID_INFO tmpBuf=(PPID_INFO)ExAllocatePoolWithTag(PagedPool,OutputLength-sizeof(UINT32),'bnak'); if(!tmpBuf) return ntStatus; ///judge safe KdPrint(("entry check hook safe!\n")); if(checkHookSafe()) { KdPrint((" safe!\n")); tmpBuf->count = GetPIDs(tmpBuf->PID, PIDLength / sizeof(UINT32)); tmpBuf->currentTime = __rdtsc(); ULONG bufLength=sizeof(PID_INFO)+tmpBuf->count*sizeof(UINT32); tmpLen = UploadPack((PUCHAR)tmpBuf , bufLength , (PUCHAR)pUserBuffer); } else { KdPrint( (" unfalse\n")); RtlZeroMemory(tmpBuf,OutputLength-sizeof(UINT32)); tmpLen=0; } /// //pUserBuffer->count = GetPIDs(pUserBuffer->PID, PIDLength / sizeof(UINT32)); //pUserBuffer->currentTime = __rdtsc(); ExFreePoolWithTag(tmpBuf,'bnak'); ///// end ntStatus = STATUS_SUCCESS; } break; case IOCTL_SET_SECU_PATHS: KdPrint(("IOCTL_SET_SECU_PATHS\n")); { /////////////////add by bh if(!g_tmpB) setStartTime(); ////////////////end /*PUCHAR pInputBuffer = (PUCHAR)IRP->AssociatedIrp.SystemBuffer; int iStringLength = pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength; ClearSecurePaths(); ULONG index = 0; while(index < iStringLength) { ULONG length = *(PULONG)((ULONG)pInputBuffer + index); index += 4; if(index + length >= iStringLength) break; AddSecurePath((WCHAR*)((ULONG)pInputBuffer + index), length); index += length * 2 + 2; }*/ ntStatus = STATUS_SUCCESS; } break; case IOCTL_SET_SECU_MD5: KdPrint(("IOCTL_SET_SECU_MD5\n")); { PUCHAR pInputBuffer; int iStringLength = pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength; unsigned char * pUnPack=(UCHAR *)ExAllocatePoolWithTag(PagedPool,iStringLength,'knab'); int unPackLength; unPackLength=DownloadUnPack((unsigned char *)IRP->AssociatedIrp.SystemBuffer,pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength,pUnPack); //add by bh //iStringLength=*((ULONG*)pUnPack ); RtlCopyBytes((PVOID)&iStringLength,(PVOID)pUnPack,sizeof(ULONG) ); pInputBuffer=pUnPack+sizeof(ULONG); //if(!g_globalTime) //g_globalTime=*((__int64 *)(pInputBuffer+iStringLength) ); RtlCopyBytes((PVOID)&g_globalTime,(PVOID)(pInputBuffer+iStringLength),8 ); __int64 elapseTime=__rdtsc()-g_globalTime; if( (elapseTime<COMMUNICATE_TIME_LIMIT) && (elapseTime>=COMMUNICATE_TIME_DOWN) ) { KdPrint( ("entry elapse check! ") ); if (unPackLength>0) {KdPrint( ("entry length check! ") ); ClearHash(); for(int i = 0; i <= iStringLength - HASH_SIZE; i += HASH_SIZE) AddSecureHash(pInputBuffer + i); ntStatus = STATUS_SUCCESS; } } ExFreePoolWithTag(pUnPack,'knab'); // } break; case IOCTL_SET_UP_UNLOAD: KdPrint(("IOCTL_SET_UP_UNLOAD\n")); DeviceObject->DriverObject->DriverUnload = DriverUnload; ntStatus = STATUS_SUCCESS; break; } IRP->IoStatus.Status = 0; IRP->IoStatus.Information = tmpLen ; IoCompleteRequest(IRP, IO_NO_INCREMENT); KdPrint(("<==DriverDeviceControl\n")); return ntStatus; }
NTSTATUS DispatchDeviceIoControl( PDEVICE_OBJECT fdo, PIRP Irp ) { ULONG info; NTSTATUS status = STATUS_SUCCESS; PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); status = IoAcquireRemoveLock( &pdx->RemoveLock, Irp ); if(!NT_SUCCESS(status)) { return CompleteRequest(Irp, status, 0); } info = 0; switch(stack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_MFUSB_PORT_NAME: { if(stack->Parameters.DeviceIoControl.OutputBufferLength < pdx->operationsInterfaceName.Length) { status = STATUS_BUFFER_TOO_SMALL; } else { info = pdx->operationsInterfaceName.Length; if(pdx->operationsInterfaceName.Buffer != NULL) { RtlCopyBytes(Irp->AssociatedIrp.SystemBuffer, pdx->operationsInterfaceName.Buffer, info); } status = STATUS_SUCCESS; } } break; case IOCTL_MFUSB_MANUFACTURER: { if(stack->Parameters.DeviceIoControl.OutputBufferLength < pdx->manufacturer.Length) { status = STATUS_BUFFER_TOO_SMALL; } else { info = pdx->manufacturer.Length; if(pdx->manufacturer.Buffer != NULL) { RtlCopyBytes(Irp->AssociatedIrp.SystemBuffer, pdx->manufacturer.Buffer, info); } status = STATUS_SUCCESS; } } break; case IOCTL_MFUSB_PRODUCT: { if(stack->Parameters.DeviceIoControl.OutputBufferLength < pdx->product.Length) { status = STATUS_BUFFER_TOO_SMALL; } else { info = pdx->product.Length; if(pdx->product.Buffer != NULL) { RtlCopyBytes(Irp->AssociatedIrp.SystemBuffer, pdx->product.Buffer, info); } status = STATUS_SUCCESS; } } break; case IOCTL_MFUSB_SERIAL_NUMBER: { if(stack->Parameters.DeviceIoControl.OutputBufferLength < pdx->serialNumber.Length) { status = STATUS_BUFFER_TOO_SMALL; } else { info = pdx->serialNumber.Length; if(pdx->serialNumber.Buffer != NULL) { RtlCopyBytes(Irp->AssociatedIrp.SystemBuffer, pdx->serialNumber.Buffer, info); } status = STATUS_SUCCESS; } } break; case IOCTL_MFUSB_DISPLAY_NAME: { if(stack->Parameters.DeviceIoControl.OutputBufferLength < pdx->displayName.Length) { status = STATUS_BUFFER_TOO_SMALL; } else { info = pdx->displayName.Length; if(pdx->displayName.Buffer != NULL) { RtlCopyBytes(Irp->AssociatedIrp.SystemBuffer, pdx->displayName.Buffer, info); } status = STATUS_SUCCESS; } } break; case IOCTL_MFUSB_DEVICE_HASH: { if(stack->Parameters.DeviceIoControl.OutputBufferLength < pdx->devHash->bLength) { status = STATUS_BUFFER_TOO_SMALL; } else { info = pdx->devHash->bLength; if(info > 0) { RtlCopyBytes(Irp->AssociatedIrp.SystemBuffer, &pdx->devHash->bString, info); } status = STATUS_SUCCESS; } } break; case IOCTL_MFUSB_READ_AVAILABLE: { ULONG available = FifoAvailable(pdx); if(stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG)) { status = STATUS_BUFFER_TOO_SMALL; } else { info = sizeof(ULONG); RtlCopyBytes(Irp->AssociatedIrp.SystemBuffer, &available, sizeof(ULONG)); status = STATUS_SUCCESS; } } break; case IOCTL_MFUSB_VENDOR_ID: { if(stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(USHORT)) { status = STATUS_BUFFER_TOO_SMALL; } else { info = sizeof(USHORT); RtlCopyBytes(Irp->AssociatedIrp.SystemBuffer, &pdx->dd.idVendor, info); status = STATUS_SUCCESS; } } break; case IOCTL_MFUSB_PRODUCT_ID: { if(stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(USHORT)) { status = STATUS_BUFFER_TOO_SMALL; } else { info = sizeof(USHORT); RtlCopyBytes(Irp->AssociatedIrp.SystemBuffer, &pdx->dd.idProduct, info); status = STATUS_SUCCESS; } } break; default: KdPrint((DRIVERNAME " - Unrecognized IOCTL\n")); status = STATUS_INVALID_PARAMETER; break; } IoReleaseRemoveLock( &pdx->RemoveLock, Irp ); if(!NT_SUCCESS(status)) { info = 0; } return CompleteRequest( Irp, status, info ); }
NTSTATUS PeachDeviceControl( PDEVICE_OBJECT DeviceObject, PIRP Irp ) /*++ Routine Description: This routine is called by the I/O system to perform a device I/O control function. Arguments: DeviceObject - a pointer to the object that represents the device that I/O is to be done on. Irp - a pointer to the I/O Request Packet for this request. Return Value: NT status code --*/ { PIO_STACK_LOCATION irpSp;// Pointer to current stack location NTSTATUS ntStatus = STATUS_SUCCESS;// Assume success ULONG inBufLength; // Input buffer length ULONG outBufLength; // Output buffer length char ret; UNREFERENCED_PARAMETER(DeviceObject); PAGED_CODE(); irpSp = IoGetCurrentIrpStackLocation( Irp ); inBufLength = irpSp->Parameters.DeviceIoControl.InputBufferLength; outBufLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength; if (!inBufLength || !outBufLength) { ntStatus = STATUS_INVALID_PARAMETER; goto End; } // // Determine which I/O control code was specified. // switch ( irpSp->Parameters.DeviceIoControl.IoControlCode ) { /* Sent by Peach to say "Starting iteration" */ case IOCTL_PEACH_METHOD_START: PEACH_KDPRINT(("IOCTL_PEACH_METHOD_START\n")); started = TRUE; // TODO: Put any code here that runs on start. break; /* Sent by Peach to say "Stopping iteration" */ case IOCTL_PEACH_METHOD_STOP: PEACH_KDPRINT(("IOCTL_PEACH_METHOD_STOP\n")); started = FALSE; // TODO: Put any code here that runs on STOP break; /* Sent by Peach to indicate a "call" data is "method name". * This will be followed by one or more DATA ioctls to deliver * each parameter's data. */ case IOCTL_PEACH_METHOD_CALL: if(methodName != NULL) { ExFreePoolWithTag(methodName, TAG); methodName = NULL; } methodName = ExAllocatePoolWithTag(NonPagedPool, inBufLength, TAG); RtlCopyBytes(methodName, Irp->AssociatedIrp.SystemBuffer, inBufLength); PEACH_KDPRINT(("IOCTL_PEACH_METHOD_CALL: [%s]\nh", methodName)); break; /* Sent by Peach to indicate a "property" set, data is "property name". * This will be followed by a single DATA ioctl. */ case IOCTL_PEACH_METHOD_PROPERTY: if(propertyName != NULL) { ExFreePoolWithTag(propertyName, TAG); propertyName = NULL; } propertyName = ExAllocatePoolWithTag(NonPagedPool, inBufLength, TAG); RtlCopyBytes(propertyName, Irp->AssociatedIrp.SystemBuffer, inBufLength); PEACH_KDPRINT(("IOCTL_PEACH_METHOD_PROPERTY: [%s]\n", propertyName)); break; /* Sent by Peach to query if driver is ready for next test. Driver * should send back TRUE (1) or FALSE (0) */ case IOCTL_PEACH_METHOD_NEXT: PEACH_KDPRINT(("IOCTL_PEACH_METHOD_NEXT\n")); // TODO: Change ret based on our status ret = 1; RtlCopyBytes(Irp->AssociatedIrp.SystemBuffer, &ret, 1); Irp->IoStatus.Information = 1; break; /* Sent by Peach to deliver DATA to Kernel */ case IOCTL_PEACH_METHOD_DATA: PEACH_KDPRINT(("IOCTL_PEACH_METHOD_DATA: Length: %d\n", inBufLength)); if(data != NULL) { ExFreePoolWithTag(data, TAG); data = NULL; } data = ExAllocatePoolWithTag(NonPagedPool, inBufLength, TAG); RtlCopyBytes(data, Irp->AssociatedIrp.SystemBuffer, inBufLength); // TODO: Place code here to fuzz something!! break; default: // // The specified I/O control code is unrecognized by this driver. // ntStatus = STATUS_INVALID_DEVICE_REQUEST; PEACH_KDPRINT(("ERROR: unrecognized IOCTL %x\n", irpSp->Parameters.DeviceIoControl.IoControlCode)); break; } End: // // Finish the I/O operation by simply completing the packet and returning // the same status as in the packet itself. // Irp->IoStatus.Status = ntStatus; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return ntStatus; }
/** * 驱动分发函数,相应上层应用的各种操作命令 * */ NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP IRP) { ::KeWaitForSingleObject(&g_DispatchMutex,Executive,KernelMode,FALSE,NULL); NTSTATUS ntStatus = STATUS_UNSUCCESSFUL; ULONG tmpLen = 0; PIO_STACK_LOCATION pIoStackIrp = IoGetCurrentIrpStackLocation(IRP); switch (pIoStackIrp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_SET_PROTECT_PID://设置保护PID KdPrint(("IOCTL_SET_PROTECT_PID\n")); { unsigned char pUnPack[256]; int unPackLength; unPackLength = DownloadUnPack((unsigned char *)IRP->AssociatedIrp.SystemBuffer,pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength,pUnPack); if (unPackLength > 0) { PPID_INFO pInputBuffer = (PPID_INFO)pUnPack; int iStringLength = unPackLength; if(iStringLength != sizeof(PID_INFO)) break; __int64 elapsedTime = __rdtsc() - pInputBuffer->currentTime; KdPrint(("IOCTL_SET_PROTECT_PID elapsed time: %I64d.\n", elapsedTime)); if((elapsedTime > COMMUNICATE_TIME_LIMIT)||(elapsedTime <=COMMUNICATE_TIME_DOWN)) { KdPrint(("IOCTL_SET_PROTECT_PID exceeds time limit.\n")); } else { // 加入进程 ID AddProtectPID(pInputBuffer->PID[0]); } ntStatus = STATUS_SUCCESS; } } break; case IOCTL_GET_PROTECT_PIDS:///判断驱动是否在正常工作 KdPrint(("IOCTL_GET_PROTECT_PIDS\n")); if (IRP->MdlAddress) { PPID_INFO pUserBuffer = (PPID_INFO)MmGetSystemAddressForMdlSafe(IRP->MdlAddress, NormalPagePriority); if(pUserBuffer == NULL) return ntStatus; ULONG OutputLength = pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength; ULONG PIDLength = OutputLength - sizeof(PID_INFO) + sizeof(UINT32); PPID_INFO tmpBuf=(PPID_INFO)ExAllocatePoolWithTag(PagedPool,OutputLength-sizeof(UINT32),'bak'); if(!tmpBuf) return ntStatus; KdPrint(("entry check hook safe!\n")); if(checkHookSafe()) { tmpBuf->count = GetKernelPIDs(tmpBuf->PID, PIDLength / sizeof(UINT32)); tmpBuf->currentTime = __rdtsc(); ULONG bufLength = sizeof(PID_INFO) + tmpBuf->count*sizeof(UINT32); tmpLen = UploadPack((PUCHAR)tmpBuf , bufLength , (PUCHAR)pUserBuffer); } else { RtlZeroMemory(tmpBuf,OutputLength-sizeof(UINT32)); tmpLen = 0; } ExFreePoolWithTag(tmpBuf,'bak'); ntStatus = STATUS_SUCCESS; } break; case IOCTL_SET_SECU_PATHS://无效 KdPrint(("IOCTL_SET_SECU_PATHS\n")); { ntStatus = STATUS_SUCCESS; } break; case IOCTL_SET_SECU_MD5://设置白名单哈希列表 KdPrint(("IOCTL_SET_SECU_MD5\n")); { PUCHAR pInputBuffer; int iStringLength = pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength; unsigned char * pUnPack=(UCHAR *)ExAllocatePoolWithTag(PagedPool,iStringLength,'knab'); int unPackLength; unPackLength = DownloadUnPack((unsigned char *)IRP->AssociatedIrp.SystemBuffer,pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength,pUnPack); RtlCopyBytes((PVOID)&iStringLength,(PVOID)pUnPack,sizeof(ULONG) ); pInputBuffer = pUnPack + sizeof(ULONG); RtlCopyBytes((PVOID)&g_globalTime,(PVOID)(pInputBuffer + iStringLength),8 ); __int64 elapseTime = __rdtsc() - g_globalTime; if( (elapseTime < COMMUNICATE_TIME_LIMIT) && (elapseTime >= COMMUNICATE_TIME_DOWN) ) { if (unPackLength > 0) { for(int i = 0; i <= iStringLength - HASH_SIZE; i += HASH_SIZE) AddSecureHash(pInputBuffer + i); getSecuTable(); ClearHash(); ntStatus = STATUS_SUCCESS; } } ExFreePoolWithTag(pUnPack,'knab'); // } break; ///////////// case IOCTL_SET_BLACK_MD5://设置黑名单哈希列表 KdPrint(("IOCTL_SET_SECU_MD5\n")); { PUCHAR pInputBuffer; int iStringLength = pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength; unsigned char * pUnPack=(UCHAR *)ExAllocatePoolWithTag(PagedPool,iStringLength,'knab'); int unPackLength; unPackLength = DownloadUnPack((unsigned char *)IRP->AssociatedIrp.SystemBuffer,pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength,pUnPack); RtlCopyBytes((PVOID)&iStringLength,(PVOID)pUnPack,sizeof(ULONG) ); pInputBuffer = pUnPack + sizeof(ULONG); RtlCopyBytes((PVOID)&g_globalTime,(PVOID)(pInputBuffer + iStringLength),8 ); __int64 elapseTime = __rdtsc() - g_globalTime; if( (elapseTime < COMMUNICATE_TIME_LIMIT) && (elapseTime >= COMMUNICATE_TIME_DOWN) ) { if (unPackLength > 0) { for(int i = 0; i <= iStringLength - HASH_SIZE; i += HASH_SIZE) AddBlackHash(pInputBuffer + i); getBlackTable(); ClearBlackHash(); ntStatus = STATUS_SUCCESS; } } ExFreePoolWithTag(pUnPack,'knab'); // } break; ///////////// case IOCTL_SET_UP_UNLOAD://设置卸载驱动函数 KdPrint(("IOCTL_SET_UP_UNLOAD\n")); while(g_bBusy) { LARGE_INTEGER interval; interval.QuadPart = -3 * 1000 * 1000;//滞后3秒进行卸载 KeDelayExecutionThread(KernelMode, FALSE, &interval); } DeviceObject->DriverObject->DriverUnload= DDKUnload; ntStatus = STATUS_SUCCESS; break; case IOCTL_GET_DRIVER_STATUS://得到驱动接受白名单状态 { ////////////////////////////////////////////////////// unsigned char pUnPack[256]; int unPackLength; unPackLength = DownloadUnPack((unsigned char *)IRP->AssociatedIrp.SystemBuffer,pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength,pUnPack); if (unPackLength > 0) { MYDRIVERSTATUS type = *(MYDRIVERSTATUS *)pUnPack; PUCHAR pUserBuffer = (PUCHAR)MmGetSystemAddressForMdlSafe(IRP->MdlAddress, NormalPagePriority);// 在虚拟内存紧张时会返回NULL if(pUserBuffer == NULL) return ntStatus; ULONG OutputLength = pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength; ULONG * tmpBuf=(ULONG *)ExAllocatePoolWithTag(PagedPool,4,'bnak'); if(!tmpBuf) return ntStatus; if(type == DRIVER_RECEIVED)//是否接受到白名单 { if(!isRestart()) g_isReceive=false; *tmpBuf = g_isReceive ? 1 : 0; tmpLen = UploadPack((PUCHAR)tmpBuf , 4 , (PUCHAR)pUserBuffer); } ExFreePoolWithTag(tmpBuf,'bnak'); } ntStatus = STATUS_SUCCESS; ////////////////////////////////////////////////////// } break; case IOCTL_SET_HANDLE://得到同步句柄 { if(pEvent) ObDereferenceObject(pEvent); HANDLE hEvent = NULL; int unPackLength; unPackLength=DownloadUnPack((unsigned char *)IRP->AssociatedIrp.SystemBuffer,pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength,(unsigned char *)&hEvent); if (unPackLength>0) { ObReferenceObjectByHandle(hEvent , EVENT_MODIFY_STATE, *ExEventObjectType, KernelMode, (PVOID *)&pEvent, NULL); ntStatus = STATUS_SUCCESS; } } break; case IOCTL_RETURN_DATA://返回灰名单 { if (IRP->MdlAddress) { wchar_t fName[260] = {0}; unsigned char cHash[16] = {0}; getData(fName,cHash); unsigned char dataBuf[260*sizeof(wchar_t) + 16 + 4*4] = {0}; *(DWORD*)(dataBuf) = 1; RtlCopyMemory(dataBuf+4,fName,DATAPATHLEN); *(wchar_t*)(dataBuf + DATAPATHLEN -2) = L'\0'; RtlCopyMemory(dataBuf+4+DATAPATHLEN,cHash,DATAHASHLEN); wchar_t * pUserBuffer = (wchar_t *)MmGetSystemAddressForMdlSafe(IRP->MdlAddress, NormalPagePriority); ULONG OutputLength = pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength; tmpLen = UploadPack((PUCHAR)dataBuf, 260*sizeof(wchar_t) + 16 + 4*4, (PUCHAR)pUserBuffer); } ntStatus = STATUS_SUCCESS; } break; case IOCTL_SET_FILTERRESULT://验证结果 { char rResult; //bool bResult = false; //rResult = (*(unsigned char *)(IRP->AssociatedIrp.SystemBuffer)); WriteSysLog(LOG_TYPE_INFO,L" IOCTL GET"); int unPackLength=DownloadUnPack((unsigned char *)IRP->AssociatedIrp.SystemBuffer,pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength,(unsigned char *)&rResult); //g_bPassFilter = (rResult == 1) ? true : false; if (unPackLength>0) { g_bPassFilter = (rResult == 1) ? true : false; } else { WriteSysLog(LOG_TYPE_INFO,L" IOCTL LError"); g_bPassFilter = false; } WriteSysLog(LOG_TYPE_INFO,L" IOCTL SET"); KeSetEvent(g_pEventFilterGo, IO_NO_INCREMENT, FALSE); ntStatus = STATUS_SUCCESS; } break; } IRP->IoStatus.Status = 0; IRP->IoStatus.Information = tmpLen ; IoCompleteRequest(IRP, IO_NO_INCREMENT); ::KeReleaseMutex(&g_DispatchMutex,FALSE); return ntStatus; }