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

Posted

技术标签:

【中文标题】在没有管理员权限的情况下连接到同一网络中的命名管道【英文标题】:Connect to a named pipe in the same network without Administrator rights 【发布时间】:2018-10-14 11:51:39 【问题描述】:

我创建了一个命名管道服务器并授予了所有人的完全访问权限。 我试图从同一网络上的不同机器连接到命名管道服务器,但我收到一条错误消息,提示登录失败 - 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);

【问题讨论】:

你能提供一些关于失败的代码和细节吗? @Hogstrom 已编辑 每个人!= 匿名 - 这是不同的 sid。你什么都不授予匿名。在这种情况下也更好,只需将 DACL 设置为 0 @RbMm 同样的错误。 这个错误发生在检查管道之前。你甚至可以设置不存在的名称 - 你得到了同样的错误 - STATUS_LOGON_TYPE_NOT_GRANTED 【参考方案1】:

How to create an anonymous pipe that gives access to everyone中描述的这个任务怎么做

错误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);

从服务器端不仅需要在 DACL 位置设置 0(这允许任何访问)或为 WinAnonymousSid 添加允许的 ACE(这是!= WinWorldSid aka everyone)但也设置了不受信任的强制标签。这在代码示例中被忽略了,因为我认为代码尚未出现在 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);
                
            
        
    

【讨论】:

以上是关于在没有管理员权限的情况下连接到同一网络中的命名管道的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有认证问题的情况下连接到 URL?

在没有元数据的情况下连接到 Web 服务

如何在不使用 *** 映像的情况下连接到 docker 中的 ***?

Swift:检查iOS是不是在没有互联网的情况下连接到wifi

在没有 mssql 支持的情况下连接到 mssql

在没有公共 API 的情况下连接到网站 webosocket