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.youkuaiyun.com/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