• 【原创】关于LSP的一点记录

    2009-05-25

    分类:信息安全

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://nokyo.blogbus.com/logs/39936957.html

          关于LSP是什么我就不多说了,假定大家都知道,不知道的可以去Google问问。
          LSP其实还是很有用的,不过最近看到许多人在学习过程中老遇到一些问题,下面就把我的一些经验说出来,纯属个人理解,有错勿怪。

    1,安装LSP后系统逐渐卡死?
          额,我当时学习的时候曾经遇到过这个问题,没仔细研究是什么原因,最近解决的方法是禁止Explorer.exe进程加载。

    2,安装LSP后上不了网?
          写完DLL后忘记导出一些函数了吧?其中WSPStartup是必须要导出的,通常情况下这个函数的写法也是固定的。由于blogbus的日志限制字数,我发了几次都被截断了,所以就把这个代码省略了,大家去网上找吧。

    3,LSP怎么安装?
          很多人都是通过王艳平《Windows网络与通信程序设计》一书学习的,不过那本书的安装代码有问题,在XP上没法用。下面我发出自己的安装/卸载代码。

    #include <ws2spi.h>
    #include <sporder.h>
    #include <windows.h>
    #include <stdio.h>

    #pragma comment(lib,"ws2_32.lib")
    #pragma comment(lib,"rpcrt4.lib")
    #pragma comment(lib,"sporder.lib")

    //
    // 要安装的LSP的硬编码,在移除的时候还要使用它
    //
    GUID  ProviderGuid = {0x9d6c9dd7,0xa201,0x42f5,{0xa8,0xbc,0x03,0xf0,0x1f,0x41,0x72,0xc6}};

    //
    // 枚举协议链
    //
    LPWSAPROTOCOL_INFOW GetProvider(LPINT lpnTotalProtocols)
    {
        DWORD dwSize = 0;
        int nError;
        LPWSAPROTOCOL_INFOW pProtoInfo = NULL;
       
        // 取得需要的缓冲区大小
        if(::WSCEnumProtocols(NULL, pProtoInfo, &dwSize, &nError) == SOCKET_ERROR)
        {
            if(nError != WSAENOBUFS)
                return NULL;
        }
       
        // 分配缓冲区
        pProtoInfo = (LPWSAPROTOCOL_INFOW)::GlobalAlloc(GPTR, dwSize);

        *lpnTotalProtocols = ::WSCEnumProtocols(NULL, pProtoInfo, &dwSize, &nError);
        return pProtoInfo;
    }

    //
    // 释放缓冲区
    //
    void FreeProvider(LPWSAPROTOCOL_INFOW pProtoInfo)
    {
        ::GlobalFree(pProtoInfo);
    }

    //
    // 安装LSP
    //
    BOOL InstallProvider(char *pszPathName)
    {
        WCHAR wszLSPName[] = L"CuitWlgcxLSP";
        LPWSAPROTOCOL_INFOW pProtoInfo;
        WSAPROTOCOL_INFOW    OriginalProtocolInfo[3];
        DWORD                dwOrigCatalogId[3];
        DWORD                dwLayeredCatalogId;        // 我们的分层协议目录ID
        int        nProtocols;   
        int        nArrayCount = 0;
        int        nError;
        WCHAR    wszPathName[256];

        memset(wszPathName, 0, sizeof(wszPathName));
        if(!::MultiByteToWideChar(CP_ACP, 0, pszPathName, -1, wszPathName, 256))
        {
            printf("MultiByteToWideChar Failed!(%d)\n", ::GetLastError());
            return FALSE;
        }
        // --输出LSP DLL路径
        printf("LSP PathName: %s\n", pszPathName);
       
        // 找到我们的下层协议,将信息放入数组中
        pProtoInfo      = GetProvider(&nProtocols);
        BOOL bFindUdp = FALSE;
        BOOL bFindTcp = FALSE;
        BOOL bFindRaw = FALSE;
        for(int i=0; i<nProtocols; i++)
        {
            if(pProtoInfo[i].iAddressFamily == AF_INET)
            {
                if(!bFindTcp && pProtoInfo[i].iProtocol == IPPROTO_TCP)
                {
                    memcpy(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));
                    // 去掉XP1_IFS_HANDLES标志
                    OriginalProtocolInfo[nArrayCount].dwServiceFlags1 = OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES);
                    // 保存原来的入口ID
                    dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;
                   
                    bFindTcp = TRUE;
                }
                if(!bFindUdp && pProtoInfo[i].iProtocol == IPPROTO_UDP)
                {
                    memcpy(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));
                    OriginalProtocolInfo[nArrayCount].dwServiceFlags1 = OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES);
                   
                    dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;
                    bFindUdp = TRUE;
                }
                if(!bFindRaw && pProtoInfo[i].iProtocol == IPPROTO_IP)
                {
                    memcpy(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));
                    OriginalProtocolInfo[nArrayCount].dwServiceFlags1 = OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES);
                   
                    dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;
                    bFindRaw = TRUE;
                }
            }
        } 
       
        // 安装我们的分层协议,获取一个dwLayeredCatalogId
        // 随便找一个下层协议的结构复制过来即可
        WSAPROTOCOL_INFOW LayeredProtocolInfo;
        memcpy(&LayeredProtocolInfo, &OriginalProtocolInfo[0], sizeof(WSAPROTOCOL_INFOW));
        // 修改协议名称,类型,设置PFL_HIDDEN标志
        wcscpy(LayeredProtocolInfo.szProtocol, wszLSPName);
        LayeredProtocolInfo.ProtocolChain.ChainLen = LAYERED_PROTOCOL;
        LayeredProtocolInfo.dwProviderFlags          |= PFL_HIDDEN;
        // 正式安装
        if(::WSCInstallProvider(&ProviderGuid, wszPathName, &LayeredProtocolInfo, 1, &nError) == SOCKET_ERROR)
        {
            return FALSE;
        }
        // 重新枚举协议,获取分层协议的目录ID号
        FreeProvider(pProtoInfo);
        pProtoInfo = GetProvider(&nProtocols);
        for(i=0; i<nProtocols; i++)
        {
            if(memcmp(&pProtoInfo[i].ProviderId, &ProviderGuid, sizeof(ProviderGuid)) == 0)
            {
                dwLayeredCatalogId = pProtoInfo[i].dwCatalogEntryId;
                break;
            }
        }
       
        // 安装协议链
        // 修改协议名称,类型
        WCHAR wszChainName[WSAPROTOCOL_LEN + 1];
        for(i=0; i<nArrayCount; i++)
        {
            swprintf(wszChainName, L"%ws over %ws", wszLSPName, OriginalProtocolInfo[i].szProtocol);
            wcscpy(OriginalProtocolInfo[i].szProtocol, wszChainName);
            if(OriginalProtocolInfo[i].ProtocolChain.ChainLen == 1)
            {
                OriginalProtocolInfo[i].ProtocolChain.ChainEntries[1] = dwOrigCatalogId[i];
            }
            else
            {
                for(int j = OriginalProtocolInfo[i].ProtocolChain.ChainLen; j>0; j--)
                {
                    OriginalProtocolInfo[i].ProtocolChain.ChainEntries[j] = OriginalProtocolInfo[i].ProtocolChain.ChainEntries[j-1];
                }
            }
            OriginalProtocolInfo[i].ProtocolChain.ChainLen ++;
            OriginalProtocolInfo[i].ProtocolChain.ChainEntries[0] = dwLayeredCatalogId;   
        }
        // 获取一个Guid,安装之
        GUID ProviderChainGuid;
        if(::UuidCreate(&ProviderChainGuid) == RPC_S_OK)
        {
            if(::WSCInstallProvider(&ProviderChainGuid, wszPathName, OriginalProtocolInfo, nArrayCount, &nError) == SOCKET_ERROR)
            {
                return FALSE;   
            }
        }
        else
            return FALSE;
       
        // 重新排序Winsock目录,将我们的协议链提前
        // 重新枚举安装的协议
        FreeProvider(pProtoInfo);
        pProtoInfo = GetProvider(&nProtocols);
       
        DWORD dwIds[20];
        int nIndex = 0;
        // 添加我们的协议链
        for(i=0; i<nProtocols; i++)
        {
            if((pProtoInfo[i].ProtocolChain.ChainLen > 1) && (pProtoInfo[i].ProtocolChain.ChainEntries[0] == dwLayeredCatalogId))
            {
                dwIds[nIndex++] = pProtoInfo[i].dwCatalogEntryId;
            }
        }
        // 添加其它协议
        for(i=0; i<nProtocols; i++)
        {
            if((pProtoInfo[i].ProtocolChain.ChainLen <= 1) || (pProtoInfo[i].ProtocolChain.ChainEntries[0] != dwLayeredCatalogId))
            {
                dwIds[nIndex++] = pProtoInfo[i].dwCatalogEntryId;
            }
        }
        // 重新排序Winsock目录
        if((nError = ::WSCWriteProviderOrder(dwIds, nIndex)) != ERROR_SUCCESS)
        {
            return FALSE;
        }
        FreeProvider(pProtoInfo);
       
        return TRUE;
    }

    //
    // 卸载LSP
    //
    BOOL RemoveProvider()
    {
        LPWSAPROTOCOL_INFOW pProtoInfo;
        int nProtocols;
        DWORD dwLayeredCatalogId;
       
        // 根据Guid取得分层协议的目录ID号
        pProtoInfo = GetProvider(&nProtocols);
        int nError;
        for(int i=0; i<nProtocols; i++)
        {
            if(memcmp(&ProviderGuid, &pProtoInfo[i].ProviderId, sizeof(ProviderGuid)) == 0)
            {
                dwLayeredCatalogId = pProtoInfo[i].dwCatalogEntryId;
                break;
            }
        }
       
        if(i < nProtocols)
        {
            // 移除协议链
            for(i=0; i<nProtocols; i++)
            {
                if((pProtoInfo[i].ProtocolChain.ChainLen > 1) && (pProtoInfo[i].ProtocolChain.ChainEntries[0] == dwLayeredCatalogId))
                {
                    ::WSCDeinstallProvider(&pProtoInfo[i].ProviderId, &nError);
                }
            }
            // 移除分层协议
            ::WSCDeinstallProvider(&ProviderGuid, &nError);
        }
       
        return TRUE;
    }

    void main(int argc, char *argv[])
    {
        char szFileName[256];
        char szPathName[256];
        char* p;

        if(argc == 3)
        {
            strcpy(szFileName,argv[2]);
            if(strcmp(argv[1], "-install")==0)  
            {
               

                if(::GetFullPathName(szFileName, 256, szPathName, &p) != 0)
                {
                    if(InstallProvider(szPathName))
                    {
                        printf("\nInstall Successully!\n");
                        return;
                    }
                }
               
                if(::GetFileAttributes(szPathName) == -1)
                {
                    printf("Error:Can't Find File!\n");
                    return;
                }
               
                printf("\nInstall Failed -> %d\n",::GetLastError());
                return;
            }
            else if(strcmp(argv[1],"-remove")==0
            {
                if(RemoveProvider())
                    printf("\nRemove Successully!\n");
                else
                    printf("\nRemove Failed -> %d\n",::GetLastError());
                return;
            }
        }
    }