LSP->包过滤->防火墙[转载]

本文介绍了如何利用LSP(分层服务提供者)实现网络包过滤,并提供了详细的代码示例,包括安装、卸载LSP的过程及核心SPI函数的重写。
LSP->包过滤->防火墙,有趣
2008-08-23 01:02

        LSP :分层服务提供者,顾名思义是某种服务的提供者且具有分层的特性,它是 WinSock2 的特性吧,与以往的 WinSock1.0 不同,WinSock1.0 仅围绕着TCP/IP协议运行的,但是在Winsock2中却增加了对更多传输协议的支持。“Winsock2不仅提供了一个供应用程序访问网络服务的Windowssocket应用程序编程接口(API),还包含了由传输服务提供者和名字解析服务提供者实现的Winsock服务提供者接口(SPI)和ws2_32.dll。”。就现在 NT 以后的网络而言(不知道Vista及后的了),应用层EXE创建套接字时,会先在 WinSock 目录中寻找全适的协议(如 TCP、UDP ......),找到之后再调用此协议的 提供者 来完成各种功能,其中 提供者 又是通过 SPI函数 来完成任务的。所以,对于这种类型的网络调用而言, LSP 是主题而其中的 SPI 则是灵魂,没有 SPI 的话 LSP 就只是一个框架而已,LSP大概的层次如图 :

---------------------------------
│ Windows socket 2 EXE│
---------------------------------Windows socket 2 API
│ WS2_32.DLL            │
---------------------------------Windows socket 2 传输SPI
│ LSP                       DLL │
-----------------------------------
│ 基础服务提供程序       │
----------------------------------

        现在可以知道几乎所有的 WinSock API 调用都会先告诉 WS2_32.DLL ,再由 WS2_32.DLL 传达给 LSP (类型转换的那些不是,不知道还有没有......-_-!),最后到 基础服务提供程序 全权代理实现。所以,大多数的 WinSock API 都是可以 HOOK 的,前提是要安装了 LSP ,由 SPI 进行 HOOK。

        上图中已示意了 LSP 其实是 DLL 的形式,它是不可以直接执行的,得由 EXE 程序来安装,所以在想采用 LSP 来过滤封包,还得先编译个可执行程序来安装这,至于这个安装 LSP 的程序很多时候都是一个固定的框架:枚举 LSP、安装 LSP、卸载 LSP ,在实现的时候,我用了一个头文件来实现这个框架(本想用类来封装的~~~):

LSPIn-Unstall.h

#define UNICODE
#define _UNICODE

#include <Ws2spi.h>
// 定义了WSCWriteProviderOrder函数
#include <Sporder.h>  
#include <windows.h>
#include <stdio.h>

#pragma comment(lib, "Ws2_32.lib")
// 实现了UuidCreate函数
#pragma comment(lib, "Rpcrt4.lib")

// 要安装的LSP的硬编码,在移除的时候还要使用它
GUID ProviderGuid = {0x8a, 0x88b, 0x888c,
        {0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a}};

//获得所有已经安装的传输服务提供者
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提供者安装到TCP UDP 和原始套节字之上
BOOL InstallProvider(WCHAR *pwszPathName)
{
//LSP的名字
WCHAR wszLSPName[] = L"MyFirstLSP";
LPWSAPROTOCOL_INFOW pProtoInfo;
int nProtocols;
WSAPROTOCOL_INFOW OriginalProtocolInfo[3];
DWORD    dwOrigCatalogId[3];
int nArrayCount = 0;

// 我们分层协议的目录ID号
DWORD dwLayeredCatalogId;  

int nError;

// 找到我们的下层协议,将信息放入数组中
// 枚举所有服务程序提供者
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(!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(!bFindTcp && pProtoInfo[i].iProtocol == IPPROTO_TCP)
    {
     memcpy(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));
     OriginalProtocolInfo[nArrayCount].dwServiceFlags1 =
      OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES);
    
     dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;

     bFindTcp = 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; // 0;
LayeredProtocolInfo.dwProviderFlags |= PFL_HIDDEN;
// 安装
if(::WSCInstallProvider(&ProviderGuid,
      pwszPathName, &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,
      pwszPathName, 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;
}
//卸载分层协议和协议链
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;
}

        接着就是主函数的调用了:

LSPControl.cpp

#include <iostream.h>
#include "LSPIn-Unstall.h"

//安装LSP
void install();
//卸载LSP
void remove();
//查看已安装了的LSP
void view();

void main()
{
//命令参数
char order[128];

while(1)
{
   cin.getline(order,128);
   if(strcmp(order,"exit")==0)
    break;
   else if(strcmp(order,"install")==0)
    install();
   else if(strcmp(order,"remove")==0)
    remove();
   else if(strcmp(order,"view")==0)
    view();
}
}
//安装LSP
void install()
{
TCHAR szPathName[256];
TCHAR* p;

//LSP所在的路径
if(::GetFullPathName(L"MyFirstLSP.dll", 256, szPathName, &p) != 0)
{
   if(InstallProvider(szPathName))
   {
    printf(" ^-^ 安装成功!/n");
    return;
   }
}
printf(" o_o! 安装失败!/n");
}
//卸载LSP
void remove()
{
if(RemoveProvider())
   printf(" ^-^ 卸载成功!/n");
else
   printf(" o_o! 卸载失败!/n");
}
//查看已安装了的LSP
void view()
{
LPWSAPROTOCOL_INFOW pProtoInfo;
int nProtocols;
pProtoInfo = GetProvider(&nProtocols);

printf("/n   ---------------------------   已安装的LSP   ---------------------------   /n/n");
for(int i=0; i<nProtocols; i++)
{
   printf(" Protocol: %ws /n", pProtoInfo[i].szProtocol);
   printf(" CatalogEntryId: %d   ChainLen: %d /n/n", pProtoInfo[i].dwCatalogEntryId, pProtoInfo[i].ProtocolChain.ChainLen);
}
printf("/n   ---------------------------   已安装的LSP   ---------------------------   /n/n");
}

        看起来是很繁琐,实际上也就是一些框架,已经实现了查看(view)、安装(install)、卸载(remove)。

        有了可以操控 LSP 程序,接下来就是生成 LSP 了,LSP 以DLL的形式来实现的,这里用的是 VC++6.0 的动态链接工程,在建立好该工程后,还要在工程里头导入一个 .def 格式的文件,其中有导出 LSP WSPStarUP 函数的 EXPORTS 语句,之后就是编写代码了。LSP 只是提供了一个接口,有些代码跟上面的一样看似繁,实则是一个框架,了解就OK了(汗,说到繁,NDIS 更让人头晕```),下面的代码中,最后的 WSPSendTo()WSPBind() 函数的定义就是 SPI 了,累了那么久,就是用到这些 SPI 来进行包过滤(甚至是实现防火墙等):

Debug.h

#ifndef __DEBUG_H__
#define __DEBUG_H__
#ifdef _DEBUG

#define ODS(szOut)      /
{          /
   OutputDebugString(szOut);   /
}

#define ODS1(szOut, var)    /
{          /
   TCHAR sz[1024];        /
   _stprintf(sz, szOut, var);   /
   OutputDebugString(sz);    /
}

#else

#define ODS(szOut)
#define ODS1(szOut, var)

#endif

#endif

LSP.cpp

// --- 声明要使用UNICODE字符串---(到了驱动的话,大都是用 UNICODE 的)
#define UNICODE
#define _UNICODE

#include <Winsock2.h>
#include <Ws2spi.h>
#include <Windows.h>
#include <tchar.h>
#include "Debug.h"
#include <fstream.h>

#pragma comment(lib, "Ws2_32.lib")

WSPUPCALLTABLE g_pUpCallTable;   // 上层函数列表。如果LSP创建了自己的伪句柄,才使用这个函数列表
WSPPROC_TABLE g_NextProcTable;   // 下层函数列表
TCHAR g_szCurrentApp[MAX_PATH]; // 当前调用本DLL的程序的名称

BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD ul_reason_for_call,
                       LPVOID lpReserved
      )
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
   {
    // 取得主模块的名称
    ::GetModuleFileName(NULL, g_szCurrentApp, MAX_PATH);
   }
   break;
}
return TRUE;
}
//得到当前所有已安装的LSP
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);
}


int WSPAPI WSPSendTo(
SOCKET    s,
LPWSABUF   lpBuffers,
DWORD    dwBufferCount,
LPDWORD    lpNumberOfBytesSent,
DWORD    dwFlags,
const struct sockaddr FAR * lpTo,
int     iTolen,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
LPWSATHREADID lpThreadId,
LPINT    lpErrno
)
{
ODS1(L" query send to... %s", g_szCurrentApp);

SOCKADDR_IN sa = *(SOCKADDR_IN*)lpTo;
if(sa.sin_port == htons(要过滤的端口<为 int 类型>) )   // 若符合则过滤掉了

{
   int iError;
   g_NextProcTable.lpWSPShutdown(s, SD_BOTH, &iError);
   *lpErrno = WSAECONNABORTED;

   ODS(L" deny a sendto ");
   return SOCKET_ERROR;
}


return g_NextProcTable.lpWSPSendTo(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpTo
    , iTolen, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno);
}

int WSPAPI WSPBind(SOCKET s, const struct sockaddr* name, int namelen, LPINT lpErrno)
{
//这里再进行处理(一般情况之下,Bind 都是作为服务程序用的函数:绑定端口后再进而监听)
return g_NextProcTable.lpWSPBind(s, name, namelen, lpErrno);
}

//这里为入口函数(必备)
int WSPAPI WSPStartup(
WORD wVersionRequested,
LPWSPDATA lpWSPData,
LPWSAPROTOCOL_INFO lpProtocolInfo,
WSPUPCALLTABLE UpcallTable,
LPWSPPROC_TABLE lpProcTable
)
{
ODS1(L" WSPStartup... %s /n", g_szCurrentApp);

if(lpProtocolInfo->ProtocolChain.ChainLen <= 1)
{
   return WSAEPROVIDERFAILEDINIT;
}

// 保存向上调用的函数表指针(在这里没有使用它)
g_pUpCallTable = UpcallTable;

// 枚举协议,找到下层协议的WSAPROTOCOL_INFOW结构
WSAPROTOCOL_INFOW NextProtocolInfo;
int nTotalProtos;
LPWSAPROTOCOL_INFOW pProtoInfo = GetProvider(&nTotalProtos);
// 下层入口ID
DWORD dwBaseEntryId = lpProtocolInfo->ProtocolChain.ChainEntries[1];
for(int i=0; i<nTotalProtos; i++)
{
   if(pProtoInfo[i].dwCatalogEntryId == dwBaseEntryId)
   {
    memcpy(&NextProtocolInfo, &pProtoInfo[i], sizeof(NextProtocolInfo));
    break;
   }
}
if(i >= nTotalProtos)
{
   ODS(L" WSPStartup: Can not find underlying protocol /n");
   return WSAEPROVIDERFAILEDINIT;
}

// 加载下层协议的DLL
int nError;
TCHAR szBaseProviderDll[MAX_PATH];
int nLen = MAX_PATH;
// 取得下层提供程序DLL路径
if(::WSCGetProviderPath(&NextProtocolInfo.ProviderId, szBaseProviderDll, &nLen, &nError) == SOCKET_ERROR)
{
   ODS1(L" WSPStartup: WSCGetProviderPath() failed %d /n", nError);
   return WSAEPROVIDERFAILEDINIT;
}
if(!::ExpandEnvironmentStrings(szBaseProviderDll, szBaseProviderDll, MAX_PATH))
{
   ODS1(L" WSPStartup: ExpandEnvironmentStrings() failed %d /n", ::GetLastError());
   return WSAEPROVIDERFAILEDINIT;
}
// 加载下层提供程序
HMODULE hModule = ::LoadLibrary(szBaseProviderDll);
if(hModule == NULL)
{
   ODS1(L" WSPStartup: LoadLibrary() failed %d /n", ::GetLastError());
   return WSAEPROVIDERFAILEDINIT;
}

// 导入下层提供程序的WSPStartup函数
LPWSPSTARTUP pfnWSPStartup = NULL;
pfnWSPStartup = (LPWSPSTARTUP)::GetProcAddress(hModule, "WSPStartup");
if(pfnWSPStartup == NULL)
{
   ODS1(L" WSPStartup: GetProcAddress() failed %d /n", ::GetLastError());
   return WSAEPROVIDERFAILEDINIT;
}

// 调用下层提供程序的WSPStartup函数
LPWSAPROTOCOL_INFOW pInfo = lpProtocolInfo;
if(NextProtocolInfo.ProtocolChain.ChainLen == BASE_PROTOCOL)
   pInfo = &NextProtocolInfo;

int nRet = pfnWSPStartup(wVersionRequested, lpWSPData, pInfo, UpcallTable, lpProcTable);
if(nRet != ERROR_SUCCESS)
{
   ODS1(L" WSPStartup: underlying provider's WSPStartup() failed %d /n", nRet);
   return nRet;
}
// 保存下层提供者的函数表
g_NextProcTable = *lpProcTable;
// 修改传递给上层的函数表,Hook感兴趣的函数
// 好像可以 Hook 30个函数,书里头写着列表有 30 个ISP函数
lpProcTable->lpWSPSendTo = WSPSendTo;
lpProcTable->lpWSPBind = WSPBind;

FreeProvider(pProtoInfo);
return nRet;
}

         一个防火墙的模型就出来了,不过在用户模式下它虽然不错,但是并非能够过滤所有的封包,除非编写内核模式的 NDIS 驱动(强捍的NDIS)~~~

        编译成 DLL 后,将上面生成的操作 LSP 的程序与 生成的 DLL 放在同一目录之下,DLL 的由字要是 MyFirstLSP (因为上面:GetFullPathName(L"MyFirstLSP.dll", 256, szPathName, &p) 中的DLL文件就是它,以前调试的时候忘记看了,试了N次都没找出失误的原因 @_@ )...... MY God~~~凌晨 1 点整,Sleep(30000000) z Z Z Z Z

Defaulting to user installation because normal site-packages is not writeableNote: you may need to restart the kernel to use updated packages. Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple Collecting ipympl Using cached https://pypi.tuna.tsinghua.edu.cn/packages/b2/6e/9148bfed8ca535e4c61ce7843327c76ec7c63c40e33848ec03aa844a26af/ipympl-0.9.8-py3-none-any.whl (515 kB) Requirement already satisfied: ipython<10 in e:\dev\anaconda\lib\site-packages (from ipympl) (8.25.0) Requirement already satisfied: ipywidgets<9,>=7.6.0 in e:\dev\anaconda\lib\site-packages (from ipympl) (7.8.1) Requirement already satisfied: matplotlib<4,>=3.5.0 in e:\dev\anaconda\lib\site-packages (from ipympl) (3.8.4) Requirement already satisfied: numpy in e:\dev\anaconda\lib\site-packages (from ipympl) (1.26.4) Requirement already satisfied: pillow in e:\dev\anaconda\lib\site-packages (from ipympl) (10.3.0) Requirement already satisfied: traitlets<6 in e:\dev\anaconda\lib\site-packages (from ipympl) (5.14.3) Requirement already satisfied: decorator in e:\dev\anaconda\lib\site-packages (from ipython<10->ipympl) (5.1.1) Requirement already satisfied: jedi>=0.16 in e:\dev\anaconda\lib\site-packages (from ipython<10->ipympl) (0.18.1) Requirement already satisfied: matplotlib-inline in e:\dev\anaconda\lib\site-packages (from ipython<10->ipympl) (0.1.6) Requirement already satisfied: prompt-toolkit<3.1.0,>=3.0.41 in e:\dev\anaconda\lib\site-packages (from ipython<10->ipympl) (3.0.43) Requirement already satisfied: pygments>=2.4.0 in e:\dev\anaconda\lib\site-packages (from ipython<10->ipympl) (2.15.1) Requirement already satisfied: stack-data in e:\dev\anaconda\lib\site-packages (from ipython<10->ipympl) (0.2.0) Requirement already satisfied: colorama in e:\dev\anaconda\lib\site-packages (from ipython<10->ipympl) (0.4.6) Requirement already satisfied: comm>=0.1.3 in e:\dev\anaconda\lib\site-packages (from ipywidgets<9,>=7.6.0->ipympl) (0.2.1) Requirement already satisfied: ipython-genutils~=0.2.0 in e:\dev\anaconda\lib\site-packages (from ipywidgets<9,>=7.6.0->ipympl) (0.2.0) Requirement already satisfied: widgetsnbextension~=3.6.6 in e:\dev\anaconda\lib\site-packages (from ipywidgets<9,>=7.6.0->ipympl) (3.6.6) Requirement already satisfied: jupyterlab-widgets<3,>=1.0.0 in e:\dev\anaconda\lib\site-packages (from ipywidgets<9,>=7.6.0->ipympl) (1.0.0) Requirement already satisfied: contourpy>=1.0.1 in e:\dev\anaconda\lib\site-packages (from matplotlib<4,>=3.5.0->ipympl) (1.2.0) Requirement already satisfied: cycler>=0.10 in e:\dev\anaconda\lib\site-packages (from matplotlib<4,>=3.5.0->ipympl) (0.11.0) Requirement already satisfied: fonttools>=4.22.0 in e:\dev\anaconda\lib\site-packages (from matplotlib<4,>=3.5.0->ipympl) (4.51.0) Requirement already satisfied: kiwisolver>=1.3.1 in e:\dev\anaconda\lib\site-packages (from matplotlib<4,>=3.5.0->ipympl) (1.4.4) Requirement already satisfied: packaging>=20.0 in e:\dev\anaconda\lib\site-packages (from matplotlib<4,>=3.5.0->ipympl) (23.2) Requirement already satisfied: pyparsing>=2.3.1 in e:\dev\anaconda\lib\site-packages (from matplotlib<4,>=3.5.0->ipympl) (3.0.9) Requirement already satisfied: python-dateutil>=2.7 in e:\dev\anaconda\lib\site-packages (from matplotlib<4,>=3.5.0->ipympl) (2.9.0.post0) Requirement already satisfied: parso<0.9.0,>=0.8.0 in e:\dev\anaconda\lib\site-packages (from jedi>=0.16->ipython<10->ipympl) (0.8.3) Requirement already satisfied: wcwidth in e:\dev\anaconda\lib\site-packages (from prompt-toolkit<3.1.0,>=3.0.41->ipython<10->ipympl) (0.2.5) Requirement already satisfied: six>=1.5 in e:\dev\anaconda\lib\site-packages (from python-dateutil>=2.7->matplotlib<4,>=3.5.0->ipympl) (1.16.0) Requirement already satisfied: notebook>=4.4.1 in e:\dev\anaconda\lib\site-packages (from widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (7.0.8) Requirement already satisfied: executing in e:\dev\anaconda\lib\site-packages (from stack-data->ipython<10->ipympl) (0.8.3) Requirement already satisfied: asttokens in e:\dev\anaconda\lib\site-packages (from stack-data->ipython<10->ipympl) (2.0.5) Requirement already satisfied: pure-eval in e:\dev\anaconda\lib\site-packages (from stack-data->ipython<10->ipympl) (0.2.2) Requirement already satisfied: jupyter-server<3,>=2.4.0 in e:\dev\anaconda\lib\site-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (2.14.1) Requirement already satisfied: jupyterlab-server<3,>=2.22.1 in e:\dev\anaconda\lib\site-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (2.25.1) Requirement already satisfied: jupyterlab<4.1,>=4.0.2 in e:\dev\anaconda\lib\site-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (4.0.11) Requirement already satisfied: notebook-shim<0.3,>=0.2 in e:\dev\anaconda\lib\site-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (0.2.3) Requirement already satisfied: tornado>=6.2.0 in e:\dev\anaconda\lib\site-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (6.4.1) Requirement already satisfied: anyio>=3.1.0 in e:\dev\anaconda\lib\site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (4.2.0) Requirement already satisfied: argon2-cffi>=21.1 in e:\dev\anaconda\lib\site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (21.3.0) Requirement already satisfied: jinja2>=3.0.3 in e:\dev\anaconda\lib\site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (3.1.4) Requirement already satisfied: jupyter-client>=7.4.4 in e:\dev\anaconda\lib\site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (8.6.0) Requirement already satisfied: jupyter-core!=5.0.*,>=4.12 in e:\dev\anaconda\lib\site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (5.7.2) Requirement already satisfied: jupyter-events>=0.9.0 in e:\dev\anaconda\lib\site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (0.10.0) Requirement already satisfied: jupyter-server-terminals>=0.4.4 in e:\dev\anaconda\lib\site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (0.4.4) Requirement already satisfied: nbconvert>=6.4.4 in e:\dev\anaconda\lib\site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (7.10.0) Requirement already satisfied: nbformat>=5.3.0 in e:\dev\anaconda\lib\site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (5.9.2) Requirement already satisfied: overrides>=5.0 in e:\dev\anaconda\lib\site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (7.4.0) Requirement already satisfied: prometheus-client>=0.9 in e:\dev\anaconda\lib\site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (0.14.1) Requirement already satisfied: pywinpty>=2.0.1 in e:\dev\anaconda\lib\site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (2.0.10) Requirement already satisfied: pyzmq>=24 in e:\dev\anaconda\lib\site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (25.1.2) Requirement already satisfied: send2trash>=1.8.2 in e:\dev\anaconda\lib\site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (1.8.2) Requirement already satisfied: terminado>=0.8.3 in e:\dev\anaconda\lib\site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (0.17.1) Requirement already satisfied: websocket-client>=1.7 in e:\dev\anaconda\lib\site-packages (from jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (1.8.0) Requirement already satisfied: async-lru>=1.0.0 in e:\dev\anaconda\lib\site-packages (from jupyterlab<4.1,>=4.0.2->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (2.0.4) Requirement already satisfied: ipykernel in e:\dev\anaconda\lib\site-packages (from jupyterlab<4.1,>=4.0.2->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (6.28.0) Requirement already satisfied: jupyter-lsp>=2.0.0 in e:\dev\anaconda\lib\site-packages (from jupyterlab<4.1,>=4.0.2->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (2.2.0) Requirement already satisfied: babel>=2.10 in e:\dev\anaconda\lib\site-packages (from jupyterlab-server<3,>=2.22.1->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (2.11.0) Requirement already satisfied: json5>=0.9.0 in e:\dev\anaconda\lib\site-packages (from jupyterlab-server<3,>=2.22.1->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (0.9.6) Requirement already satisfied: jsonschema>=4.18.0 in e:\dev\anaconda\lib\site-packages (from jupyterlab-server<3,>=2.22.1->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (4.19.2) Requirement already satisfied: requests>=2.31 in e:\dev\anaconda\lib\site-packages (from jupyterlab-server<3,>=2.22.1->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (2.32.2) Requirement already satisfied: idna>=2.8 in e:\dev\anaconda\lib\site-packages (from anyio>=3.1.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (3.7) Requirement already satisfied: sniffio>=1.1 in e:\dev\anaconda\lib\site-packages (from anyio>=3.1.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (1.3.0) Requirement already satisfied: argon2-cffi-bindings in e:\dev\anaconda\lib\site-packages (from argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (21.2.0) Requirement already satisfied: pytz>=2015.7 in e:\dev\anaconda\lib\site-packages (from babel>=2.10->jupyterlab-server<3,>=2.22.1->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (2024.1) Requirement already satisfied: MarkupSafe>=2.0 in e:\dev\anaconda\lib\site-packages (from jinja2>=3.0.3->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (2.1.3) Requirement already satisfied: attrs>=22.2.0 in e:\dev\anaconda\lib\site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.22.1->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (23.1.0) Requirement already satisfied: jsonschema-specifications>=2023.03.6 in e:\dev\anaconda\lib\site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.22.1->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (2023.7.1) Requirement already satisfied: referencing>=0.28.4 in e:\dev\anaconda\lib\site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.22.1->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (0.30.2) Requirement already satisfied: rpds-py>=0.7.1 in e:\dev\anaconda\lib\site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.22.1->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (0.10.6) Requirement already satisfied: platformdirs>=2.5 in e:\dev\anaconda\lib\site-packages (from jupyter-core!=5.0.*,>=4.12->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (3.10.0) Requirement already satisfied: pywin32>=300 in e:\dev\anaconda\lib\site-packages (from jupyter-core!=5.0.*,>=4.12->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (305.1) Requirement already satisfied: python-json-logger>=2.0.4 in e:\dev\anaconda\lib\site-packages (from jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (2.0.7) Requirement already satisfied: pyyaml>=5.3 in e:\dev\anaconda\lib\site-packages (from jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (6.0.1) Requirement already satisfied: rfc3339-validator in e:\dev\anaconda\lib\site-packages (from jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (0.1.4) Requirement already satisfied: rfc3986-validator>=0.1.1 in e:\dev\anaconda\lib\site-packages (from jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (0.1.1) Requirement already satisfied: beautifulsoup4 in e:\dev\anaconda\lib\site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (4.12.3) Requirement already satisfied: bleach!=5.0.0 in e:\dev\anaconda\lib\site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (4.1.0) Requirement already satisfied: defusedxml in e:\dev\anaconda\lib\site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (0.7.1) Requirement already satisfied: jupyterlab-pygments in e:\dev\anaconda\lib\site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (0.1.2) Requirement already satisfied: mistune<4,>=2.0.3 in e:\dev\anaconda\lib\site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (2.0.4) Requirement already satisfied: nbclient>=0.5.0 in e:\dev\anaconda\lib\site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (0.8.0) Requirement already satisfied: pandocfilters>=1.4.1 in e:\dev\anaconda\lib\site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (1.5.0) Requirement already satisfied: tinycss2 in e:\dev\anaconda\lib\site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (1.2.1) Requirement already satisfied: fastjsonschema in e:\dev\anaconda\lib\site-packages (from nbformat>=5.3.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (2.16.2) Requirement already satisfied: charset-normalizer<4,>=2 in e:\dev\anaconda\lib\site-packages (from requests>=2.31->jupyterlab-server<3,>=2.22.1->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (2.0.4) Requirement already satisfied: urllib3<3,>=1.21.1 in e:\dev\anaconda\lib\site-packages (from requests>=2.31->jupyterlab-server<3,>=2.22.1->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (2.2.2) Requirement already satisfied: certifi>=2017.4.17 in e:\dev\anaconda\lib\site-packages (from requests>=2.31->jupyterlab-server<3,>=2.22.1->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (2024.6.2) Requirement already satisfied: debugpy>=1.6.5 in e:\dev\anaconda\lib\site-packages (from ipykernel->jupyterlab<4.1,>=4.0.2->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (1.6.7) Requirement already satisfied: nest-asyncio in e:\dev\anaconda\lib\site-packages (from ipykernel->jupyterlab<4.1,>=4.0.2->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (1.6.0) Requirement already satisfied: psutil in e:\dev\anaconda\lib\site-packages (from ipykernel->jupyterlab<4.1,>=4.0.2->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (5.9.0) Requirement already satisfied: webencodings in e:\dev\anaconda\lib\site-packages (from bleach!=5.0.0->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (0.5.1) Collecting fqdn (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) Downloading https://pypi.tuna.tsinghua.edu.cn/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl (9.1 kB) Collecting isoduration (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) Downloading https://pypi.tuna.tsinghua.edu.cn/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl (11 kB) Requirement already satisfied: jsonpointer>1.13 in e:\dev\anaconda\lib\site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (2.1) Collecting uri-template (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) Using cached https://pypi.tuna.tsinghua.edu.cn/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl (11 kB) Collecting webcolors>=1.11 (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) Downloading https://pypi.tuna.tsinghua.edu.cn/packages/60/e8/c0e05e4684d13459f93d312077a9a2efbe04d59c393bc2b8802248c908d4/webcolors-24.11.1-py3-none-any.whl (14 kB) Requirement already satisfied: cffi>=1.0.1 in e:\dev\anaconda\lib\site-packages (from argon2-cffi-bindings->argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (1.16.0) Requirement already satisfied: soupsieve>1.2 in e:\dev\anaconda\lib\site-packages (from beautifulsoup4->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (2.5) Requirement already satisfied: pycparser in e:\dev\anaconda\lib\site-packages (from cffi>=1.0.1->argon2-cffi-bindings->argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (2.21) Requirement already satisfied: arrow>=0.15.0 in e:\dev\anaconda\lib\site-packages (from isoduration->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->notebook>=4.4.1->widgetsnbextension~=3.6.6->ipywidgets<9,>=7.6.0->ipympl) (1.2.3) Installing collected packages: webcolors, uri-template, fqdn, isoduration, ipympl Successfully installed fqdn-1.5.1 ipympl-0.9.8 isoduration-20.11.0 uri-template-1.3.0 webcolors-24.11.1
最新发布
10-27
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值