UNC路径转本地路径

85 篇文章 6 订阅
83 篇文章 9 订阅

 

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
来源:CSDN
原文: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
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值