视窗驱动程序IOCTL代码蓝屏/使计算机崩溃
Windows Driver IOCTL Code Bluescreens / Crashes The Computer
我有一个设备驱动程序,我用它来从内核空间读取其他进程虚拟内存,所以我不必使用ReadProcessMemory
或WriteProcessMemory
等函数。
当我使用结构作为媒介通过DeviceIoControl
将参数传递给内核时,这工作正常,但是当我使用无符号长整型等普通变量时,驱动程序会使我的计算机崩溃。
这是一个完美工作代码的示例
(司机):
#define IO_KERNEL_READ_REQUEST CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0701, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
typedef struct _KERNEL_READ_REQUEST
{
ULONG ProcessId;
ULONG Address;
ULONG Response;
ULONG Size;
} KERNEL_READ_REQUEST, *PKERNEL_READ_REQUEST;
if (ControlCode == IO_KERNEL_READ_REQUEST)
{
PKERNEL_READ_REQUEST ReadInput = (PKERNEL_READ_REQUEST)Irp->AssociatedIrp.SystemBuffer;
PKERNEL_READ_REQUEST ReadOutput = (PKERNEL_READ_REQUEST)Irp->AssociatedIrp.SystemBuffer;
PEPROCESS Process;
PsLookupProcessByProcessId(ReadInput->ProcessId, &Process);
KeReadVirtualMemory(Process, ReadInput->Address, &ReadOutput->Response, ReadInput->Size);
DbgPrintEx(0, 0, "Read Params: %lu, %#010x n", ReadInput->ProcessId, ReadInput->Address);
DbgPrintEx(0, 0, "Value: %lu n", ReadOutput->Response);
status = STATUS_SUCCESS;
bytesIO = sizeof(KERNEL_READ_REQUEST);
}
(程序):
template <typename type>
type KernelRead(HANDLE hDriver, ULONG ProcessId, ULONG ReadAddress, SIZE_T ReadSize)
{
if (hDriver == INVALID_HANDLE_VALUE)
return (type)false;
DWORD Return;
DWORD Bytes;
KERNEL_READ_REQUEST ReadRequest;
ReadRequest.ProcessId = ProcessId;
ReadRequest.Address = ReadAddress;
ReadRequest.Size = ReadSize;
if (DeviceIoControl(hDriver, IO_KERNEL_READ_REQUEST, &ReadRequest, sizeof(ReadRequest),
&ReadRequest, sizeof(ReadRequest), &Bytes, NULL)) {
return (type)ReadRequest.Response;
}
else
return (type)false;
}
这就是导致问题的原因
#define IO_KERNEL_GET_ID CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0703, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
else if (ControlCode == IO_KERNEL_GET_ID)
{
// ProcessId is an ULONG initialized at the driver entry
PULONG OutPut = (PULONG)Irp->AssociatedIrp.SystemBuffer;
OutPut = &ProcessId;
DbgPrintEx(0, 0, "Kernel Get Id: %d n", *OutPut);
status = STATUS_SUCCESS;
bytesIO = sizeof(OutPut);
}
DWORD KernelGetProcessId(HANDLE hDriver)
{
if (hDriver == INVALID_HANDLE_VALUE)
return false;
ULONG Id;
if (DeviceIoControl(hDriver, IO_KERNEL_GET_ID, &, sizeof(Id),
&Id, sizeof(Id), 0, NULL))
return Id;
else
return false;
}
调用KernelGetProcessId
会使我的驱动程序和整个计算机崩溃,如何解决此问题?我在这里做错了什么?
检查 DeviceIoControl。如果 lpOverlapped 为 NULL,则 lpBytesReturn 不能为 NULL。即使操作不返回任何输出数据并且 lpOutBuffer 为 NULL,DeviceIoControl 也会使用 lpBytesReturn。经过这样的操作,lpBytesReturn的值是没有意义的。
也许这可能是原因之一。 我看到的其他问题是只传递 &,您应该在其中传递 ULONG 变量。
检查类似的东西
DWORD KernelGetProcessId(HANDLE hDriver)
{
if (hDriver == INVALID_HANDLE_VALUE)
return false;
ULONG Id;
DWORD Bytes;
if (DeviceIoControl(hDriver, IO_KERNEL_GET_ID, &Id, sizeof(Id),
&Id, sizeof(Id), &Bytes, NULL))
return Id;
else
return false;
}
问题:
显然,IOCTL 通过使用两个堆栈来工作 驱动程序和用户程序。据我了解,堆栈 函数调用 DeviceIoControl() 被复制到内核空间 然后使用 DeviceIoControl() 的参数进行剖析 知道我们正在处理哪些堆栈变量和缓冲区是 最后设置为 Irp->AssociatedIrp.SystemBuffer。
在内核端完成 IOCTL 操作后, IoCompleteRequest() 被制作出来,它复制了 内核模块到用户空间,然后再次剖析到 我们想要的形式。
(如果我错了,请纠正我)
解决方案:
崩溃是由内核模块中的以下代码引起的:
PULONG OutPut = (PULONG)Irp->AssociatedIrp.SystemBuffer;
OutPut = &ProcessId;
其中全局变量的地址设置为输出数据的值。 现在,当堆栈被复制时,地址显然不会指向任何地方,因为 "ProcessId" 变量驻留在 64 位内核空间中。这是我对问题的理解。
这解决了以下问题:
PULONG OutPut = (PULONG)Irp->AssociatedIrp.SystemBuffer;
*OutPut = ProcessId;
DbgPrintEx(0, 0, "Kernel Get Id: %d n", *OutPut);
status = STATUS_SUCCESS;
bytesIO = sizeof(OutPut);
- 当回溯以零开始时,如何调试崩溃
- 内联映射初始化的动态atexit析构函数崩溃
- 执行函数时导致崩溃的变量
- 程序崩溃并显示"std::out_of_range"错误
- 为什么使用 P/Invoke 调用 dll 时,某些计算机中的 LoadLibrary 失败?
- CoInitialize()在单独的线程上崩溃而不返回
- EvtExportLogneneneba API正在将远程计算机的事件日志保存到远程PC本身.如何将其保存到主机
- 使用调试/崩溃报告将应用程序部署到客户端
- 为什么所有C++编译器都会崩溃或挂起此代码
- 为什么lambda在clang上崩溃而不是在gcc上崩溃
- 为什么我的多线程作业队列崩溃
- ExtractIconEx:可以工作,但偶尔会崩溃
- 为什么引用传递会导致此崩溃(C++)
- Windows桌面程序保存您的计算机会话 - 基于程序崩溃时的恢复会话
- 视窗驱动程序IOCTL代码蓝屏/使计算机崩溃
- 如何检测终止进程事件、计算机关闭和计算机崩溃
- OpenCV人脸检测使计算机崩溃
- 使用删除会使我的计算机崩溃
- 为什么这行代码会导致计算机崩溃
- 访问计算机指针时发生访问冲突(c系统异常代码:c0000005),导致应用程序崩溃