UNC路径转本地路径

    xiaoxiao2025-03-13  66

     

    UNC应用(Universal Naming Convention)通用命名规则,比如网络访问文件UNC路径就是

    \\servername\sharename\directory\filename比如就是\\\\192.168.0.1\\mydocs\\x.txt对应本地路径D:\\tete\\x.txt,这个就是在注册表

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServe\Shares里有映射关系。mydocs映射着本地路径D:\\tete,通俗就是一个文件夹被共享。一般在安全软件下规则在本地路径,所以要把UNC路径转换成本地路径。

    思路

    在第三个和第四个"\"之间的就是share的valuekey名字,然后把期求出,然后遍历判断多字符串是否是path

    开头,然后拼接起来,找到。那把注册表中的数据读入到一个buffer,解析这个buffer可以用一个指针指向buffer,可以用

    for(p=multistrz;*p==L'\0';p=p+wcslen(p)+1)  

    下面是代码,自己给自己挖的坑一个是找子串时候MaximumLength没设置导致找不到path,其次是unicode_string拼接函数记错,还有就是代码unicodeString找子串和找字符位置参考了大佬们的代码

    /* \\servername\sharename\directory\filename比如就是 \\\\192.168.0.1\\mydocs\\x.txt->D:\\tete\\x.txt,这个就是在注册表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServe\Shares里有映射关系。mydocs映射着本地路径。一般在安全软件下规则在本地路径,所以要把UNC路径转换成本地路径。 --------------------- 作者:kernweak 来源: 原文:https://blog.csdn.net/youyou519/article/details/90523662 版权声明:本文为博主原创文章,转载请附上博文链接! */ #include<ntddk.h> #include<ntstrsafe.h> #ifndef MAX_PATH #define MAX_PATH 260 #endif // !MAX_PATH #define REG_PATH L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Shares" #define DEVICE_NAME L"\\device\\U2LDrv" #define LINK_NAME L"\\dosdevices\\U2LDrv" //实现strchr WCHAR* RTLUnicodeStringChr(PUNICODE_STRING IN pStr, WCHAR chr) { ULONG i = 0; ULONG size = pStr->Length>>1; for (i = 0; i < size ; i++) { if (pStr->Buffer[i] == chr) { return pStr->Buffer + i; } } return NULL; } //实现strstr WCHAR* RTLUnicodeStringStr(const PUNICODE_STRING IN pStr, const PUNICODE_STRING IN pSubStr) { USHORT uLengthStep = 0; USHORT uStrlen = pStr->Length; USHORT uSubStrlen = pSubStr->Length; USHORT i = 0; UNICODE_STRING str1 = { 0 }; str1.MaximumLength = uStrlen; UNICODE_STRING str2 = { 0 }; str2.MaximumLength = uSubStrlen; str2.Buffer = pSubStr->Buffer; //str2.Length = pSubStr->Length; if (pStr == NULL || pSubStr == NULL|| uStrlen < uSubStrlen) { return NULL; } uLengthStep = ((uStrlen - uSubStrlen) >> 1 )+ 1; for (i = 0; i < uLengthStep; i++) { str1.Length = str1.MaximumLength = (USHORT)uSubStrlen; str2.Length = str2.MaximumLength = (USHORT)uSubStrlen; str1.Buffer = pStr->Buffer + i; str2.Buffer = pSubStr->Buffer; if (0 == RtlCompareUnicodeString(&str1, &str2, TRUE)) { return pStr->Buffer + i; } } return NULL; } UNICODE_STRING* getShareName(PUNICODE_STRING IN pStrUnc, PUNICODE_STRING OUT pStrShare) { WCHAR * pTmp = pStrUnc->Buffer; WCHAR *pSharStart = NULL; WCHAR *pSharEnd = NULL; ULONG uShareLen = 0;//share长度 ULONG i = 0; ULONG uSize = (pStrUnc->Length) >> 1; //先取SharedDocs观察得shareDocs开头是第三个'\\',结束是第四个‘\\’,所有涉及以下流程 ULONG uTmp = 1;//取第三个'\\'标志位 if (pTmp == NULL) { return NULL; } //取ShareDocs for (i = 0; i < uSize; i++) { if (pStrUnc->Buffer[i] == L'\\') { if (uTmp == 3) { pSharStart = pStrUnc->Buffer + i + 1; } else if (uTmp == 4) { pSharEnd = pStrUnc->Buffer + i - 1; } uTmp++; } } if (NULL == pSharStart || NULL == pSharEnd) { return NULL; } uShareLen = pSharEnd - pSharStart + 1; pStrShare->Buffer = pSharStart; pStrShare->Length = uShareLen * sizeof(WCHAR); return pStrShare; } //逻辑和取share略有差距,所以变量注释有些就没改 UNICODE_STRING* getFileName(PUNICODE_STRING IN pStrUnc, PUNICODE_STRING OUT pStrShare) { WCHAR * pTmp = pStrUnc->Buffer; WCHAR *pSharStart = NULL; WCHAR *pSharEnd = NULL; ULONG uShareLen = 0;//share长度 ULONG i = 0; ULONG uSize = (pStrUnc->Length) >> 1; //先取SharedDocs观察得开始是第四个‘\\’,所有涉及以下流程 ULONG uTmp = 1;//取第四个'\\'标志位 if (pTmp == NULL) { return NULL; } //取ShareDocs for (i = 0; i < uSize; i++) { if (pStrUnc->Buffer[i] == L'\\') { if (uTmp == 4) { pSharStart = pStrUnc->Buffer + i ; break; } uTmp++; } } if (NULL == pSharStart) { return NULL; } uShareLen = pStrUnc->Length - (i)* sizeof(WCHAR); pStrShare->Buffer = pSharStart; pStrShare->Length = uShareLen; return pStrShare; } //\\servername\SharedDocs\xxxx -> C:\\Documents and Settings\\All Users\\Documents\\xxx NTSTATUS UNC2Local(PUNICODE_STRING IN pStrUnc, PUNICODE_STRING OUT pStrLocal) { NTSTATUS status = STATUS_UNSUCCESSFUL; //我的思路是先将L"Doc\\1.txt"的截取出Doc,然后去查注册表,找到Path,再把后面拼接起来 UNICODE_STRING StrShare = { 0 }; StrShare.MaximumLength = MAX_PATH; StrShare.Length = 0; UNICODE_STRING uStrReg = { 0 }; ULONG ulResult = 0;//放长度 PKEY_VALUE_PARTIAL_INFORMATION pvpi = NULL; UNICODE_STRING StrFile = { 0 }; StrFile.MaximumLength = MAX_PATH; StrFile.Length = 0; getShareName(pStrUnc, &StrShare); getFileName(pStrUnc, &StrFile); OBJECT_ATTRIBUTES objectAttr = { 0 }; HANDLE hRegister = NULL; DbgPrint("ShareName is %wZ\n", &StrShare); DbgPrint("file is %wZ\n", &StrFile); //查询注册表shared信息 RtlInitUnicodeString(&uStrReg, REG_PATH); InitializeObjectAttributes(&objectAttr, &uStrReg, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); status = ZwOpenKey(&hRegister, KEY_ALL_ACCESS, &objectAttr); if (!NT_SUCCESS(status)) { DbgPrint("[RegQueryValueKey]ZwOpenKey failed!\n"); return status; } status = ZwQueryValueKey(hRegister, &StrShare, KeyValuePartialInformation, NULL, 0, &ulResult); if (status != STATUS_BUFFER_OVERFLOW && status != STATUS_BUFFER_TOO_SMALL) { ZwClose(hRegister); return status; } pvpi = (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePoolWithTag(PagedPool, ulResult, 'SGER'); if (pvpi == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } status = ZwQueryValueKey(hRegister, &StrShare, KeyValuePartialInformation, pvpi, ulResult, &ulResult); if (!NT_SUCCESS(status)) { ExFreePool(pvpi); ZwClose(hRegister); return status; } if (pvpi->Type != REG_MULTI_SZ) { if (pvpi) { ExFreePool(pvpi); } if (hRegister) { ZwClose(hRegister); } return status; } //然后解析path= UNICODE_STRING uszLoc = { 0 }; uszLoc.Length = (USHORT)pvpi->DataLength; uszLoc.MaximumLength = (USHORT)pvpi->DataLength; uszLoc.Buffer = (WCHAR*)(pvpi->Data); DbgPrint("uszLoc is %wZ\n", &uszLoc);//中间变量,保存查处的 UNICODE_STRING uszLoc2 = { 0 }; //中间变量 WCHAR * pTmp = 0; RtlInitUnicodeString(&uszLoc2, L"Path="); pTmp=RTLUnicodeStringStr(&uszLoc, &uszLoc2); //DbgPrint("pTmp is %wZ\n", *pTmp); if (NULL == pTmp) { status = STATUS_UNSUCCESSFUL; if (pvpi) { ExFreePool(pvpi); } if (hRegister) { ZwClose(hRegister); } return status; } else { WCHAR* i = 0; RtlInitUnicodeString(&uszLoc2, pTmp + wcslen(L"Path=")); RtlAppendUnicodeStringToString(pStrLocal,&uszLoc2); DbgPrint("pStrLocal is %wZ\n", *pStrLocal); RtlAppendUnicodeStringToString(pStrLocal, &StrFile); DbgPrint("pStrLocal is %wZ\n", *pStrLocal); status = STATUS_SUCCESS; if (pvpi) { ExFreePool(pvpi); } if (hRegister) { ZwClose(hRegister); } } return status; } NTSTATUS DispatchCommon(PDEVICE_OBJECT pObject, PIRP pIrp) { UNREFERENCED_PARAMETER(pObject); pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = 0; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return STATUS_SUCCESS; } NTSTATUS DriverUnload(PDRIVER_OBJECT pDriverObject) { UNICODE_STRING uLinkName = { 0 }; RtlInitUnicodeString(&uLinkName, LINK_NAME); IoDeleteSymbolicLink(&uLinkName); IoDeleteDevice(pDriverObject->DeviceObject); DbgPrint("Driver unloaded\n"); } NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, UNICODE_STRING pReg) { UNREFERENCED_PARAMETER(pReg); UNICODE_STRING uDeviceName = { 0 }; UNICODE_STRING uLinkName = { 0 }; PDEVICE_OBJECT pDeviceObject = NULL; ULONG i = 0; DbgPrint("Driver load begin\n"); NTSTATUS status = STATUS_UNSUCCESSFUL; UNICODE_STRING strUnc = { 0 }; UNICODE_STRING strLocal = { 0 }; strLocal.MaximumLength = MAX_PATH; strLocal.Length = 0; strLocal.Buffer = ExAllocatePoolWithTag(PagedPool, MAX_PATH * sizeof(WCHAR), 'TSET'); RtlZeroMemory(strLocal.Buffer, MAX_PATH * sizeof(WCHAR)); RtlInitUnicodeString(&strUnc, L"\\\\127.0.0.1\\Doc\\1.txt");//这里写死,已经在该目录下分享了文件 RtlInitUnicodeString(&uDeviceName, DEVICE_NAME); RtlInitUnicodeString(&uLinkName, LINK_NAME); //设备对象和驱动对象的关系 //二者互指 status = IoCreateDevice(pDriverObject, 0, &uDeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject); if (!NT_SUCCESS(status)) { DbgPrint("IoCreateDevice failed:%x", status); return status; } pDeviceObject->Flags |= DO_BUFFERED_IO; //符号链接的作用 status = IoCreateSymbolicLink(&uLinkName, &uDeviceName); if (!NT_SUCCESS(status)) { IoDeleteDevice(pDeviceObject); DbgPrint("IoCreateSymbolicLink failed:%x\n", status); return status; } for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION + 1; i++) { pDriverObject->MajorFunction[i] = DispatchCommon; } pDriverObject->DriverUnload = DriverUnload; DbgPrint("Driver load ok!\n"); status = UNC2Local(&strUnc, &strLocal); if (!NT_SUCCESS(status)) { DbgPrint("没找到\n"); } else { DbgPrint("%wZ\n", &strLocal); } ExFreePool(strLocal.Buffer); return status; }

    git参考代码地址

    https://github.com/yangruiqiyr/winTestDriver/tree/master/U2LDrv

     

     

    最新回复(0)