精华内容
下载资源
问答
  • 关键词: windows驱动开发 删除符号链接出错 变量作用域问题RtlInitUnicodeString 摘要:NT式驱动中,在DriverUnload()中尝试删除之前创建的符号链接失败,最后发现原因是变量作用域和RtlInitUnicodeString的问题...

    关键词: windows驱动开发  删除符号链接出错  变量作用域问题 RtlInitUnicodeString

    摘要:NT式驱动中,在DriverUnload()中尝试删除之前创建的符号链接失败,最后发现原因是变量作用域和RtlInitUnicodeString的问题


    原始存在问题的简化代码如下:

    typedef struct _DEVICE_EXTENSION {
        UINT32 magicNum;
    	PDEVICE_OBJECT pDevice;
    	UNICODE_STRING symLinkName;	
    } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
    
    PDEVICE_OBJECT gControlDeviceObject;
    
    DriverEntry()
    {
    	PDEVICE_EXTENSION pDevExt;
    	WCHAR             linkNameBuffer[]  = L"\\DosDevices\\diskFilter";
            UNICODE_STRING          LinkName;
    	
    	IoCreateDevice(..., &gControlDeviceObject);
    	RtlInitUnicodeString (&LinkName, linkNameBuffer );
    	
    	pDevExt->magicNum = 0x4c44;
    	pDevExt->symLinkName = LinkName;
    	
    	DriverObject->DriverUnload = DiskFilterUnload;
    }
    
    DiskFilterUnload (IN PDRIVER_OBJECT pDriverObject) 
    {
    	NTSTATUS status;
    	PDEVICE_EXTENSION pDevExt;
    	
    	pDevExt = (PDEVICE_EXTENSION)gControlDeviceObject->DeviceExtension;
    	KdPrint(("  devObj(0x%x), magicNum(0x%x), SymLinkName(%wZ)\n", gControlDeviceObject, pDevExt->magicNum, &pDevExt->symLinkName));
    	status = IoDeleteSymbolicLink( &pDevExt->ustrSymLinkName );
    }

    上述代码中,从IoDeleteSymbolicLink返回的status是路径不正确,但KdPrint中打印的magicNum是正确的,windbg调试里发现在DiskFilterUnload()中的pDevExt->symLinkName没有包含正确的值,当时真有点百思不得其解啊。


    后来看到linkNameBuffer是局部变量,想到了变量作用域的问题,把WCHAR             linkNameBuffer[]  = L"\\DosDevices\\diskFilter";拿到DriverEntry外做全局变量,

    问题就消失了。当然,更一般的做法应该是在头文件中#define SymbolicLinkName L"\\DosDevices\\diskFilter"。


    现在来看,要产生这个问题,还有一个原因是RtlInitUnicodeString(),它应该没有做内存拷贝(它没有为smLinkName分配内存然后把值拷贝过去,但我认为它这样做了)

    看来下次使用RtlInitUnicodeString()的时候得要注意了。


    转载于:https://www.cnblogs.com/bugchecker/archive/2012/11/06/3041590.html

    展开全文
  • 枚举符号链接: #include #include #include #include // 定义函数返回值 //typedef ULONG NTSTATUS; // 宽字节字符串结构定义 typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; ...

    枚举符号链接:

     

    #include <windows.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <tchar.h>
    
    // 定义函数返回值
    //typedef ULONG NTSTATUS;
    
    // 宽字节字符串结构定义
    typedef struct _UNICODE_STRING {
    	USHORT  Length;
    	USHORT  MaximumLength;
    	PWSTR  Buffer;
    } UNICODE_STRING, *PUNICODE_STRING;
    
    // 对象属性定义
    typedef struct _OBJECT_ATTRIBUTES {
    	ULONG Length;
    	HANDLE RootDirectory;
    	UNICODE_STRING *ObjectName;
    	ULONG Attributes;
    	PSECURITY_DESCRIPTOR SecurityDescriptor;
    	PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
    } OBJECT_ATTRIBUTES,*POBJECT_ATTRIBUTES;
    
    // 基本信息定义
    typedef struct _DIRECTORY_BASIC_INFORMATION {
    	UNICODE_STRING ObjectName;
    	UNICODE_STRING ObjectTypeName;
    } DIRECTORY_BASIC_INFORMATION, *PDIRECTORY_BASIC_INFORMATION;
    
    // 返回值或状态类型定义
    #define OBJ_CASE_INSENSITIVE      0x00000040L
    #define DIRECTORY_QUERY           (0x0001)
    #define STATUS_SUCCESS            ((NTSTATUS)0x00000000L) // ntsubauth
    #define STATUS_MORE_ENTRIES       ((NTSTATUS)0x00000105L)
    #define STATUS_NO_MORE_ENTRIES    ((NTSTATUS)0x8000001AL)
    #define STATUS_BUFFER_TOO_SMALL   ((NTSTATUS)0xC0000023L)
    #define SYMBOLIC_LINK_QUERY       (0x0001)
    #define SYMBOLIC_LINK_ALL_ACCESS  (STANDARD_RIGHTS_REQUIRED | 0x1)
    
    // 初始化对象属性宏定义
    #define InitializeObjectAttributes( p, n, a, r, s ) { \
    	(p)->Length = sizeof( OBJECT_ATTRIBUTES );          \
    	(p)->RootDirectory = r;                             \
    	(p)->Attributes = a;                                \
    	(p)->ObjectName = n;                                \
    	(p)->SecurityDescriptor = s;                        \
    	(p)->SecurityQualityOfService = NULL;               \
    }
    
    // 字符串初始化
    typedef VOID (CALLBACK* RTLINITUNICODESTRING)(PUNICODE_STRING,PCWSTR);
    RTLINITUNICODESTRING RtlInitUnicodeString;
    
    // 字符串比较
    typedef
    BOOLEAN
    (WINAPI *RTLEQUALUNICODESTRING)(
    								const UNICODE_STRING *String1,
    								const UNICODE_STRING *String2,
    								BOOLEAN CaseInSensitive
    								);
    RTLEQUALUNICODESTRING RtlEqualUnicodeString;
    
    // 打开对象
    typedef NTSTATUS (WINAPI *ZWOPENDIRECTORYOBJECT)(
    	OUT PHANDLE DirectoryHandle,
    	IN ACCESS_MASK DesiredAccess,
    	IN POBJECT_ATTRIBUTES ObjectAttributes
    	);
    ZWOPENDIRECTORYOBJECT ZwOpenDirectoryObject;
    
    // 查询对象
    typedef
    NTSTATUS
    (WINAPI *ZWQUERYDIRECTORYOBJECT)(
    								 IN HANDLE DirectoryHandle,
    								 OUT PVOID Buffer,
    								 IN ULONG BufferLength,
    								 IN BOOLEAN ReturnSingleEntry,
    								 IN BOOLEAN RestartScan,
    								 IN OUT PULONG Context,
    								 OUT PULONG ReturnLength OPTIONAL
    								 );
    ZWQUERYDIRECTORYOBJECT ZwQueryDirectoryObject;
    
    // 打开符号链接对象
    typedef
    NTSTATUS
    (WINAPI *ZWOPENSYMBOLICKLINKOBJECT)(
    									OUT PHANDLE SymbolicLinkHandle,
    									IN ACCESS_MASK DesiredAccess,
    									IN POBJECT_ATTRIBUTES ObjectAttributes
    									);
    ZWOPENSYMBOLICKLINKOBJECT ZwOpenSymbolicLinkObject;
    
    // 查询符号链接对象
    typedef
    NTSTATUS
    (WINAPI *ZWQUERYSYMBOLICKLINKOBJECT)(
    									 IN HANDLE SymbolicLinkHandle,
    									 IN OUT PUNICODE_STRING TargetName,
    									 OUT PULONG ReturnLength OPTIONAL
    									 );
    ZWQUERYSYMBOLICKLINKOBJECT ZwQuerySymbolicLinkObject;
    
    // 关闭已经打开的对象
    typedef
    NTSTATUS
    (WINAPI *ZWCLOSE)(
    				  IN HANDLE Handle
    				  );
    ZWCLOSE ZwClose;
    
    
    //
    int main()
    {
    	HMODULE hNtdll = NULL;
    	hNtdll = LoadLibrary(_T("ntdll.dll" ));
    	if ( NULL == hNtdll )
    	{
    		printf("[%s]--Load ntdll.dll failed(%ld).\r\n", __FUNCTION__, GetLastError());
    		goto EXIT;
    	}
    	printf("[%s]--Load ntdll.dll sucess now get proc.\r\n", __FUNCTION__);
    	RtlInitUnicodeString      = (RTLINITUNICODESTRING)GetProcAddress(hNtdll, "RtlInitUnicodeString");
    	RtlEqualUnicodeString     = (RTLEQUALUNICODESTRING)GetProcAddress(hNtdll, "RtlEqualUnicodeString");
    	ZwOpenDirectoryObject     = (ZWOPENDIRECTORYOBJECT)GetProcAddress(hNtdll, "ZwOpenDirectoryObject");
    	ZwQueryDirectoryObject    = (ZWQUERYDIRECTORYOBJECT)GetProcAddress(hNtdll, "ZwQueryDirectoryObject");
    	ZwOpenSymbolicLinkObject  = (ZWOPENSYMBOLICKLINKOBJECT)GetProcAddress(hNtdll, "ZwOpenSymbolicLinkObject");
    	ZwQuerySymbolicLinkObject = (ZWQUERYSYMBOLICKLINKOBJECT)GetProcAddress(hNtdll, "ZwQuerySymbolicLinkObject");
    	ZwClose                   = (ZWCLOSE)GetProcAddress(hNtdll, "ZwClose");
    
    	UNICODE_STRING     strDirName;
    	OBJECT_ATTRIBUTES  oba;
    	NTSTATUS           ntStatus; 
    	HANDLE             hDirectory;
    	RtlInitUnicodeString(&strDirName, _T("\\BaseNamedObjects"));//global??,BaseNamedObjects
    	InitializeObjectAttributes(&oba, &strDirName, OBJ_CASE_INSENSITIVE, NULL, NULL);
    
    	printf("[%s]--Open directory object now.\r\n", __FUNCTION__);
    	ntStatus = ZwOpenDirectoryObject(&hDirectory, DIRECTORY_QUERY, &oba);
    	if ( ntStatus != STATUS_SUCCESS )
    	{
    		printf("[%s]--Open directory object failed(%ld).\r\n", __FUNCTION__, GetLastError());
    		goto EXIT;
    	}
    
    	printf("[%s]--Open directory object success.\r\n", __FUNCTION__);
    	UNICODE_STRING symbolicLink;
    	UNICODE_STRING targetName;
    	BYTE           buffer[2048] = {0};
    	ULONG          ulLength  = 2048;  
    	ULONG          ulContext = 0;
    	ULONG          ulRet     = 0; 
    	RtlInitUnicodeString(&symbolicLink, L"SymbolicLink");
    	targetName.Length = 0;
    	targetName.Buffer = (PWSTR)calloc(2, 1024);
    	if ( targetName.Buffer == NULL )
    	{
    		printf("[%s]--calloc failed(%ld).\r\n", __FUNCTION__, GetLastError());
    		goto EXIT;
    	}
    
    	targetName.MaximumLength = 1024;
    	do
    	{
    		ntStatus = ZwQueryDirectoryObject(hDirectory, buffer, ulLength, TRUE, FALSE, &ulContext, &ulRet);
    		if ( (ntStatus != STATUS_SUCCESS) && (ntStatus != STATUS_NO_MORE_ENTRIES) )
    		{
    			printf("[%s]--ZwQueryDirectoryObject failed(%ld).\r\n", __FUNCTION__, GetLastError());
    			goto EXIT;
    		}
    		else if ( STATUS_NO_MORE_ENTRIES == ntStatus )
    		{
    			printf("[%s]--No more object.\r\n", __FUNCTION__);
    			goto EXIT;
    		}
    
    		PDIRECTORY_BASIC_INFORMATION  directoryInfo = (PDIRECTORY_BASIC_INFORMATION)buffer;
    		printf("ObjectName: [%S]---ObjectTypeName: [%S]\n", 
    			directoryInfo->ObjectName.Buffer, 
    			directoryInfo->ObjectTypeName.Buffer);
    
    		if ( RtlEqualUnicodeString(&directoryInfo->ObjectTypeName, &symbolicLink, TRUE) )
    		{
    			OBJECT_ATTRIBUTES symbolicLinkAttributes;
    			HANDLE            hSymbolicLink;
    			// 初始化符号链接对象属性
    			InitializeObjectAttributes(&symbolicLinkAttributes,
    				&directoryInfo->ObjectName, 
    				OBJ_CASE_INSENSITIVE, 
    				hDirectory, 
    				NULL);
    
    			// 打开符号链接对象
    			ntStatus = ZwOpenSymbolicLinkObject(&hSymbolicLink, SYMBOLIC_LINK_QUERY, &symbolicLinkAttributes);
    			if ( ntStatus != STATUS_SUCCESS )
    			{
    				printf("[%s]--ZwOpenSymbolicLinkObject failed(%ld).\r\n", __FUNCTION__, GetLastError());
    				goto EXIT;
    			}
    
    			// 查询符号链接对象
    			ntStatus = ZwQuerySymbolicLinkObject(hSymbolicLink, &targetName, NULL); 
    			if ( ntStatus != STATUS_SUCCESS )
    			{
    				printf("[%s]--ZwQuerySymbolicLinkObject failed(%ld).\r\n", __FUNCTION__, GetLastError());
    				ZwClose(hSymbolicLink);
    				goto EXIT;
    			}
    			// TODO: 添加针对符号链接的处理代码
    			// 清空targetName
    			memset((LPVOID)targetName.Buffer, 0, targetName.Length*sizeof(WCHAR));
    			// 关闭符号链接句柄
    			ZwClose(hSymbolicLink);
    		}
    	}while(TRUE);
    EXIT:
    	if ( hDirectory != NULL )
    	{
    		ZwClose(hDirectory);
    	}
    	getchar();
    	return 0;
    }

     

    比如说,需要枚举程序A有几个实例在运行,可以根据其 GUID 实现查找:

     

    PDIRECTORY_BASIC_INFORMATION  directoryInfo = (PDIRECTORY_BASIC_INFORMATION)buffer;
    		std::wstring objectName = directoryInfo->ObjectName.Buffer;
    		if ( objectName.find( L"{FED3DBE6-1256-46fc-8DAE-C13360CB46C8}" ) != std::wstring::npos )
    		{
    			++g_nAppClientCount;//
    		}

     

    展开全文
  • 笔者关于Windows驱动开发讲演视频之1.7,以3W的方式介绍什么是符号链接,为什么要有符号连接内核对象,以及如何使用它。最后将内核符号链接对象的结构体show了出来,加深人们的理解。
  • 最近需要实现一个功能,在驱动中创建文件的符号链接。搜了一圈,只能找到 mklink 命令, mklink 命令显然不能在内核调用。 因为大部分的系统调用最终都会调用到内核层的实现,所以整体思路就是搞清楚 mklink 的实现...

    0x00

    最近需要实现一个功能,在驱动中创建文件的符号链接。搜了一圈,只能找到 mklink 命令, mklink 命令显然不能在内核调用。

    因为大部分的系统调用最终都会调用到内核层的实现,所以整体思路就是搞清楚 mklink 的实现,找到对应的内核接口。

    0x01

    简单搜索了下系统目录,发现并没有 mklink 文件,因此怀疑 mklink 是 cmd 的内置命令。验证这个想法很简单,直接把 cmd 拖入 IDA,搜索相关字符串(mklink),果然:
    在这里插入图片描述
    双击条目,找到对应的符号再X下,就能找到相关的引用:
    看到这个,一般的猜想就是 mklink 是命令名,eMkLink 是对应的命令处理函数。
    我们可以验证一把。
    使用 windbg 加载 cmd,根据 _MakeLinkStr 的偏移,也就是图一中的 401be8,计算出加载后的真实地址。对这个地址下一个读断点(windbg:ba r命令;gdb:watch命令),之后 F5。在 cmd 中输入 mklink,回车。我们就会发现断点被断下来了,断下的位置是 wcsicmp,也就是在字符串比较,那么只可能是在比较命令字符串,毕竟 cmd 中内置了很多命令,需要一个一个比较。
    我们可以先 shift+f11 出来,到达 cmd 的领空,之后一直 f10,记得盯着 cmd 的输出,如果 cmd 有新的输出,那么就说明咱们走过了_。最终可以确定,eMkLink 就是 mklink 的命令处理函数。

    0x02

    进入 eMkLink 之后,我们跳过 stub 函数,到达 MakeLink 函数。从函数的实现来看除了验证参数之外,一共有以下的几个实现:
    MakeSymLink
    MakeHardLink
    MakeJunction
    对应着 mklink 的几个功能。因为这次我们要实现的功能是文件的符号链接,所以我们进入 MakeSymLink 函数。函数的实现很简单,调用了 CreateSymbolicLinkW 函数。从 msdn 上或者 windbg 上都能知道,这个函数从 kernel32(win7)中导出(因为家里的工作机是 win8.1,所以函数是从 kernelbase.dll 中导出的)。那么接着我们就需要开撸CreateSymbolicLinkW。
    CreateSymbolicLinkW 的实现也很简单,主要做了路径转换,之后调用 NtCreateFile 与 NtFsControlFile。我们知道 ntdll 中的 Nt* 函数,最终对应 nt 中的 Zw* 函数,nt!Zw* 函数最终执行到 nt!Nt* 函数。
    因此对于我们而言,到目前为止,我们已经知道了创建文件符号链接的整个过程,只要在驱动层调用 ZwCreateFile 与 ZwFsControlFile 即可。唯一需要确定的就是调用这两个函数的参数。
    在这里插入图片描述
    本着大家都要动手实践的原则,具体参数的赋值我就不给出了,只说明下关键的一个参数。
    在 NtCreateFile 中,CreateOptions 包含了 FILE_OPEN_REPARSE_POINT 属性;在 NtFsControlFile 中,其FsControlCode 值为 FSCTL_SET_REPARSE_POINT。
    另外还有一个神坑需要注意:NtFsControlFile 中的 InputBuffer 在末尾不能包含多余的0字节,否则会直接返回 错误。

    0x03

    重解析点的原理比较简单,有兴趣的可以翻阅 Ntfs 的源码,里面有相关的实现。

    另外有部分博客讲的也很好,推荐下面这个博客 NTFS重解析点(Reparse Points)

    展开全文
  • 刚开始驱动编程的时候实现了pDriverObject->MajorFunction中的大部分函数,但是回头重新一步一步开展的时候发现应用层打开驱动层的符号链接的时候报错了,打开文件失败 虽然错误很简单,但还是记录一下 主要原因是...

    刚开始驱动编程的时候实现了pDriverObject->MajorFunction中的大部分函数,但是回头重新一步一步开展的时候发现应用层打开驱动层的符号链接的时候报错了,打开文件失败

    虽然错误很简单,但还是记录一下

    主要原因是,这次写的驱动,忘了实现IRP_MJ_CREATE函数了,虽然驱动只做了一个显示hello world,但是要进行通信还是得有IRP_MJ_CREATE实现才行

    如果驱动层创建的符号链接是L"\\??\\thesymbollinkname"

    应用成打开的设备就得是_T("\\\\.\\thesymbollinkname")

    只是前缀不一样,当初还以为是应用层方法错了,果然还是得注意每一个细节,虽然都是系统规定的

    展开全文
  • 笔者关于Windows驱动开发讲演视频之1.7,以3W的方式介绍什么是符号链接,为什么要有符号连接内核对象,以及如何使用它。最后将内核符号链接对象的结构体show了出来,加深人们的理解。很可惜,CSDN不能内嵌视频。但...
  • NT驱动加载工具DriverMonitor,WDM驱动加载工具EzDriverInstaller,查看符号链接工具SymLinks,无需安装,解压即可以实用。
  • 【我的】Window驱动开发——通过符号链接获取真实设备 作者:zcr214 时间:2016/5/5   我们想要把驱动绑定到指定的盘符,实际是绑定到它对应的真实设备卷,实际上windows用户看到的C盘D盘只是符号链接名,而真实...
  • 驱动开发之符号链接和设备名称

    千次阅读 2014-10-21 16:41:40
    驱动符号链接名是这样写的 L"//??//HelloDDK" --->/??/HelloDDK  L"//DosDevices//HelloDDK"--->/DosDevices/HelloDDK 在应用程序中,符号链接名: L"////.//HelloDDK"-->//./HelloDDK winobj和Device...
  • 符号连接从Vista开始就得到支持,属于NTFS内置的功能,符号链接适用于文件、目录。可以理解为一种超级快捷方式。支持相对路径、绝对路径。假设创建symbolic link时使用了相对路径,保存到NTFS中的就是相对路径,不会...
  • 系统盘(通常为 C盘)空间经常不够用是计算机用户常见的烦恼。造成这种情况的原因很可能是因为硬盘分区是手贱为系统盘分配的空间太小,...我们可以使用符号链接的方法,将该目录“移动”到磁盘的非系统盘分区(D盘、...
  • 这个时候,拔掉键盘,检测到这个拔动作之后,手动调用一次卸载函数(函数中删除了符号链接), 把所有的设备解绑并删除.然后,插入键盘,此时重新创建PDO,符号链接一系列初始化工作,重新附加 到键盘上,我跟踪程序看到这些...
  • 驱动层设备链接名获取DosName很难做到通用,但DosName->DeviceSymblinkName可以做到通用,这样的话就有一种思路: 查询一个设备链接名对应的磁盘盘符的方法: 获取从A到Z的盘的设备链接名,如果有一个和传入的...
  • 概述:链接是将各种代码和数据片段(例如由编译器生成的.o文件)组合成一个单一文件... 先来整理一下编译器驱动程序将一个ASCII的C源文件翻译成机器码的整个流程。 main.c(通过c预处理器[cpp])----中间文件main.i(通过...
  • 1.驱动对象. typedef struct _DRIVER_OBJECT { CSHORT Type; CSHORT Size; // // The following links all of the devices created by a single driver // together on a list, and the Fla
  • 应用程序可以调用DefineDosDevice来创建符号链接,但是创建出来后有时候在session里面。为了创建到Global中,有两种方法,一是将应用程序提升到系统权限,作为system运行,类似于服务的处理;一种是建一个驱动,通过...
  • 我相信用过Linux系统的童鞋都很喜欢挂载文件的操作方式,而Windows系统更多的是通过共享来映射网络驱动器的操作方式,Windows的这种操作方式会带来一个很大的瓶颈就是一旦项目增多,存储容量不够用,我们就不得不...
  • 2. 符号链接(symbolic link) 3. 硬链接(hard link) 快捷链接,就是一个小文件,它的内容包含了一些“指向文件、文件夹、驱动器或者网络设备等文件系统对象”的信息。 快捷链接能让用户更方便的访问到文件、...
  • 看 哪个硬件抽象层 再把硬件抽象层驱动 复制 system32\目录下 link -dump -all \WINDOWS\system32\hal.dll | findstr pdb 如果不成功 需要设置路径 path C:\WRK\tools\x86;%path%教程中是 p...
  • 用于将具有可重用源代码的目录符号链接到项目中的命令行工具。 与语言无关。 带有Python和Flutter特定的扩展。 为什么 重用代码应该很简单。 如果我在本地驱动器上的目录中有所需的代码,我只想将其包含在项目中。 ...
  • 符号链接(symbolic link)3. 硬链接(hard link)快捷链接,就是一个小文件,它的内容包含了一些“指向文件、文件夹、驱动器或者网络设备等文件系统对象”的信息。快捷链接能让用户更方便的访问到文件、文件夹、...
  • 在编写linux驱动程序时,时常会发现链接出错,当时往往不知道错误在哪。现在了解到链接器的工作原理之后,明白当时为什么出错了。对于以后有效率地编写驱动程序有很大帮助。一个C语言程序,经过诸如GCC之类的编译器...
  • 这两天写驱动程序时遇到设备对象打不开的问题,在检查代码无误、WinObj可以找到设备的情况下无法打开设备,最后发现是AddDevice写的有问题。 调用IoCreateDevice创建设备对象时,I/O 管理器在 DEVICE_OBJECT 结构的...
  • 符号文件

    2021-01-19 09:13:00
    链接应用程序、库、驱动程序或操作系统时,创建 .exe 和 .dll 文件的链接器还会创建多个称为符号文件的附加文件。 符号文件保存多个数据,这些数据在运行二进制文件时实际上并不需要,但在调试过程中可能非常有用。...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 452
精华内容 180
关键字:

驱动符号链接