IoDeleteSymbolicLink遇到的问题
xinali opened this issue · 0 comments
xinali commented
IoDeleteSymbolicLink遇到的问题
遇到问题
在学习NT driver
过程中,遇到了一个比较奇怪的问题,在NTDDKUnload
中,删除符号链接,出现蓝屏
DEVICE_EXTENSION
结构
typedef struct _DEVICE_EXTENSION {
PDEVICE_OBJECT pDevice;
UNICODE_STRING ustrDeviceName;
UNICODE_STRING ustrSymLinkName;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
创建设备和卸载设备代码,其中CreateDevice
属性为INITCODE
,NTDDKUnload
属性为PAGEDCODE
#define PAGEDCODE code_seg("PAGE")
#define LOCKEDCODE code_seg()
#define INITCODE code_seg("INIT")
#define PAGEDDATA data_seg("PAGE")
#define LOCKEDDATA data_seg()
#define INITDATA data_seg("INIT")
#pragma INITCODE
NTSTATUS CreateDevice(
IN PDRIVER_OBJECT pDriverObject)
{
// PAGED_CODE();
NTSTATUS status;
PDEVICE_OBJECT pDevObj;
PDEVICE_EXTENSION pDevExt;
UNICODE_STRING devName;
RtlInitUnicodeString(&devName, L"\\Device\\MyDDKDevice");
status = IoCreateDevice(pDriverObject,
sizeof(DEVICE_EXTENSION),
&devName,
FILE_DEVICE_UNKNOWN,
0, TRUE,
&pDevObj);
if (!NT_SUCCESS(status))
{
DbgPrint("CreateDevice Error...\n");
return status;
}
pDevObj->Flags |= DO_BUFFERED_IO;
pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
pDevExt->pDevice = pDevObj;
pDevExt->ustrDeviceName = devName;
UNICODE_STRING symLinkName;
RtlInitUnicodeString(&symLinkName, DOS_DEVICE_NAME);
pDevExt->ustrSymLinkName = symLinkName;
status = IoCreateSymbolicLink(&symLinkName, &devName);
if (!NT_SUCCESS(status))
{
IoDeleteDevice(pDevObj);
DbgPrint("Create SymbolicLink Error...\n");
return status;
}
DbgPrint("CreateDevice successfully...\n");
return STATUS_SUCCESS;
}
#pragma PAGEDCODE
VOID NTDDKUnload(IN PDRIVER_OBJECT pDriverObject)
{
NTSTATUS status;
PDEVICE_OBJECT pNextObj;
DbgPrint(("Enter DriverUnload\n"));
pNextObj = pDriverObject->DeviceObject;
UNICODE_STRING pLinkName;
while (pNextObj != NULL)
{
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pNextObj->DeviceExtension;
DbgPrint("ustrSymLinkName: %wZ\n", pDevExt->ustrSymLinkName);
pLinkName = pDevExt->ustrSymLinkName;
DbgPrint("Start delete symlinkname %wZ by pLinkName...\n", pLinkName);
DbgPrint("Start delete symlinkname %wZ by ustrSymLinkName...\n", pDevExt->ustrSymLinkName);
status = IoDeleteSymbolicLink(&pLinkName);
// status = IoDeleteSymbolicLink(&(pDevExt->ustrSymLinkName));
if (!NT_SUCCESS(status))
{
DbgPrint("Delete SymbolLink Error\n");
goto finish;
}
pNextObj = pNextObj->NextDevice;
IoDeleteDevice(pDevExt->pDevice);
}
finish:
DbgPrint("Leave DriverUnload\n");
}
这么写卸载设备的代码会出现蓝屏,具体错误
可以看到在调用IoDeleteSymbolicLink(&pLinkName)
出错了。
测试问题
现在设置一个断点,在未发生异常前断下来
继续执行
可以看到edi
存放的是DEVICE_OBJECT
结构,ebx
存放的是DEVICE_EXTENSION
结构,现在来看看UNICODE_STRING
中的数据
可以发现这块内存中的数据是无法访问的,如果用这里的数据去删除符号链接肯定会出错的。
解决问题
经过不断的查询资料和stackoverflow上提问得知是CreateDevice
函数的问题。该函数的内存属性为PAGEDCODE
,在调用完之后就会被释放
/*
* These compiler directives tell the Operating System how to load the
* driver into memory. The "INIT" section is discardable as you only
* need the driver entry upon initialization, then it can be discarded.
*
*/
所以为了解决这个问题,代码这么设置
#pragma PAGECODE
NTSTATUS CreateDevice(
IN PDRIVER_OBJECT pDriverObject)
{
// PAGED_CODE();
NTSTATUS status;
PDEVICE_OBJECT pDevObj;
PDEVICE_EXTENSION pDevExt;
UNICODE_STRING devName;
RtlInitUnicodeString(&devName, L"\\Device\\MyDDKDevice");
status = IoCreateDevice(pDriverObject,
sizeof(DEVICE_EXTENSION),
&devName,
FILE_DEVICE_UNKNOWN,
0, TRUE,
&pDevObj);
if (!NT_SUCCESS(status))
{
DbgPrint("CreateDevice Error...\n");
return status;
}
pDevObj->Flags |= DO_BUFFERED_IO;
pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
pDevExt->pDevice = pDevObj;
pDevExt->ustrDeviceName = devName;
UNICODE_STRING symLinkName;
RtlInitUnicodeString(&symLinkName, DOS_DEVICE_NAME);
pDevExt->ustrSymLinkName = symLinkName;
status = IoCreateSymbolicLink(&symLinkName, &devName);
if (!NT_SUCCESS(status))
{
IoDeleteDevice(pDevObj);
DbgPrint("Create SymbolicLink Error...\n");
return status;
}
DbgPrint("CreateDevice successfully...\n");
return STATUS_SUCCESS;
}
#pragma PAGEDCODE
VOID NTDDKUnload(IN PDRIVER_OBJECT pDriverObject)
{
NTSTATUS status;
PDEVICE_OBJECT pNextObj;
DbgPrint(("Enter DriverUnload\n"));
pNextObj = pDriverObject->DeviceObject;
UNICODE_STRING pLinkName;
while (pNextObj != NULL)
{
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pNextObj->DeviceExtension;
pLinkName = pDevExt->ustrSymLinkName;
DbgPrint("Start delete symlinkname %wZ by pLinkName...\n", &pLinkName);
DbgPrint("Start delete symlinkname %wZ by ustrSymLinkName...\n", &pDevExt->ustrSymLinkName);
status = IoDeleteSymbolicLink(&pLinkName);
// status = IoDeleteSymbolicLink(&(pDevExt->ustrSymLinkName));
if (!NT_SUCCESS(status))
{
DbgPrint("Delete SymbolLink Error\n");
goto finish;
}
pNextObj = pNextObj->NextDevice;
IoDeleteDevice(pDevExt->pDevice);
}
finish:
DbgPrint("Leave DriverUnload\n");
}
全部设置成PAGEDCODE
正常执行