在没有管理员权限的情况下连接到同一网络中的命名管道

Connect to a named pipe in the same network without Administrator rights

本文关键字:网络 管道 连接 管理员 权限 情况下      更新时间:2023-10-16

我创建了一个命名管道服务器,并向所有人授予了完全访问权限。 我尝试从同一网络上的不同计算机连接到命名管道服务器,但出现错误,指出登录失败 - ERROR_LOGON_FAILURE。

我阅读了有关NullSessionPipes的信息,并从MSDN编译了该示例。但是,我需要管理权限才能在注册表中注册 NullSessionPipe,这是我试图避免的。

CreateFile 如何实际登录到远程命名管道?我是否需要在特定上下文中运行我的客户端才能使其正常工作?(例如客人(。

服务器代码:

DWORD dwRes, dwDisposition;
PSID pEveryoneSID = NULL, pAdminSID = NULL;
PACL pACL = NULL;
PSECURITY_DESCRIPTOR pSD = NULL;
EXPLICIT_ACCESS ea[2];
SID_IDENTIFIER_AUTHORITY SIDAuthWorld =
SECURITY_WORLD_SID_AUTHORITY;
SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
SECURITY_ATTRIBUTES sa;
LONG lRes;
HKEY hkSub = NULL;
// Create a well-known SID for the Everyone group.
if (!AllocateAndInitializeSid(&SIDAuthWorld, 1,
SECURITY_WORLD_RID,
0, 0, 0, 0, 0, 0, 0,
&pEveryoneSID))
{
return false;
}
// Initialize an EXPLICIT_ACCESS structure for an ACE.
// The ACE will allow Everyone read access to the key.
ZeroMemory(&ea, 1 * sizeof(EXPLICIT_ACCESS));
ea[0].grfAccessPermissions = 0xFFFFFFFF;
ea[0].grfAccessMode = SET_ACCESS;
ea[0].grfInheritance = NO_INHERITANCE;
ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
ea[0].Trustee.ptstrName = (LPTSTR)pEveryoneSID;
// Create a new ACL that contains the new ACEs.
dwRes = SetEntriesInAcl(1, ea, NULL, &pACL);
if (ERROR_SUCCESS != dwRes)
{
return false;
}
// Initialize a security descriptor.  
pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR,
SECURITY_DESCRIPTOR_MIN_LENGTH);
if (NULL == pSD)
{
return false;
}
if (!InitializeSecurityDescriptor(pSD,
SECURITY_DESCRIPTOR_REVISION))
{
return false;
}
// Add the ACL to the security descriptor. 
if (!SetSecurityDescriptorDacl(pSD,
TRUE,     // bDaclPresent flag   
pACL,
FALSE))   // not a default DACL 
{
return false;
}
// Initialize a security attributes structure.
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = pSD;
sa.bInheritHandle = FALSE;
// create named pipe
auto NamedPipe = CreateNamedPipeA(namedPipeName,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_NOWAIT | PIPE_ACCEPT_REMOTE_CLIENTS,
PIPE_UNLIMITED_INSTANCES,
NAMED_PIPE_SIZE,
NAMED_PIPE_SIZE,
NMPWAIT_USE_DEFAULT_WAIT, 
&sa);

如何执行如何执行此任务 如何创建向所有人提供访问权限的匿名管道中所述

该错误ERROR_LOGON_FAILURE表示客户端代码未连接到网络资源。 确实需要调用WNetAddConnection2(或在远程管道上调用CreateFile之前的模拟 API(

客户端通过调用CreateFile函数打开管道。如果 发生错误,客户端检查是否为登录失败错误,一个 访问被拒绝错误或密码错误。如果发生错误, 通过调用WNetAddConnection2函数执行匿名登录 并将空字符串作为用户名和密码传递。当空 会话建立,客户端调用CreateFile函数 再。

因此,客户端代码必须如下所示:

NETRESOURCE nr = {};
nr.dwUsage = RESOURCEUSAGE_CONNECTABLE|RESOURCEUSAGE_CONTAINER;
nr.lpRemoteName = L"\\server\IPC$";
WNetAddConnection2W(&nr, L"", L"",0);
HANDLE hFile = CreateFileW(L"\\?\UNC\server\PIPE\MyPipe",
FILE_GENERIC_READ|FILE_GENERIC_WRITE, 
0, 0, OPEN_EXISTING, 0, 0);

从服务器端不仅需要将 0 设置在适当的DACL(这允许任何访问(或为WinAnonymousSid添加允许的ACE(这是 !=WinWorldSidaka每个人(,而且还需要设置不受信任的强制标签。 这在代码示例中被遗漏了,因为我认为代码尚未预先 Vista。

SECURITY_DESCRIPTOR sd;
BOOL fOk = InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION) &&
SetSecurityDescriptorDacl(&sd, TRUE, 0, FALSE);
if (fOk)
{
RTL_OSVERSIONINFOW ovi = { sizeof(ovi) };
if (0 > RtlGetVersion(&ovi))
{
fOk = FALSE;
}
else
{
if (ovi.dwMajorVersion > 5)
{
fOk = FALSE;
ULONG cb = GetSidLengthRequired(1);
PSID UntrustedLabelSid = alloca(cb);
if (CreateWellKnownSid(WinUntrustedLabelSid, 0, UntrustedLabelSid, &cb))
{
PACL Sacl = (PACL)alloca(cb += sizeof(ACL) + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK));
fOk = InitializeAcl(Sacl, cb, ACL_REVISION) &&
AddMandatoryAce(Sacl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, UntrustedLabelSid) &&
SetSecurityDescriptorSacl(&sd, TRUE, Sacl, FALSE);
}
}
}
}