找到原始的SSDT表的内容

驱动开发笔记3—SSDT表详解 SSDT表 SSDT的全称是"System Services Descriptor Table",即系统服务描述表,在内核中的实际名称是KeServiceDescriptorTable,这个表由ntoskrnl.exe导出(在x64里不导出)。 SSDT用于处理应用层通过Kernel32.dll下发的各个API操作请求。ntdll.dll中的API是一个简单的包装函数,当Kernel32.dll中的API通过Ntdll.dll时,会先完成对参数的检查,再调用一个中断(int 2Eh 或者 SysEnter指 阅读详情

DWORD GetOrgWindowsServiceTable() 1.Mb45.{  
{ qrMhg2'k  
     CLocalFileIO LocalFileIO; zN'MZVj  
     gpFileIO = &LocalFileIO; hYxh2Lp  
     CPEFile PEFile; &"#lrfhN/  
     DWORD NtKernelBaseAddress=0; 0xsvx?9  
     CPEFile PEFile2; tv:/+O9G  
     HANDLE hFile,hFile2; C$CT;g&uS  
     DWORD n,m,k,MaxServiceNum=0; oq,e`aH5  
     bool bOK; >? ?cj!3  
     DWORD Func1Addr,NtdllAddr1,ServiceNum1; q9I]2o@kW  
     DWORD Func2Addr,NtDllAddr2,ServiceNum2,ReadBufferLen; }N)v|  
     char Fun1[30]; [L9I4  
     char Fun2[30]; d3&Et`  
     BYTE CodeBuffer[0x0f]; QVc qb i  
     ULSIZE ReadLen,Pos; u0h6=/BR47  
     char* FunctionName; oV !b  
     char *ReadBuffer; p }e !bRQ  
     PEFile.m_OpenMode = PE_OPEN_NO_IMPORT|PE_OPEN_SYS; $+|&U  
     if(gpPsLoadedModuleListHeader==NULL) OA zr)=8D8  
           return 0; 8|s-Pl  
     NtKernelBaseAddress = GetKernelName(&gszKernelName[TStrLen(gszKernelName)],NULL); d_LSLD  
     if(NtKernelBaseAddress==0) njRA7:  
           return 0; |B {+{  
     bOK = PEFile.Open(gszKernelName,&hFile); FK<H60,[  
     if(bOK==false) "u@ /(=*%  
     { % M6KL[d  
           return 0; Bl}y[,  
     } APCi~hsg  
     Fun1[0]=0; (y>, Xt  
     Fun2[0]=0; e9bP "#C  
     for(n=0;n<(DWORD)PEFile.m_ExportFuncCount;n++) a3,~a7 U!  
     { @:B7m:oH  
           FunctionName = PEFile.m_ExportFunc[n].FuncName; #qNiSjP?  
           if(FunctionName[0]!='N'||FunctionName[1]!='t')continue; ra<R(j  
           if(TStrLen(FunctionName)>=30)continue; %,P7V8}o  
           if(Fun1[0]==0) eC]t'a$@  
           { $57nkL re  
                 TStrCpy(Fun1,FunctionName); &gQj+f/  
                 Func1Addr=PEFile.m_ExportFunc[n].Address; =vR<r-u_h  
                 continue; W A/"'Z?  
           } ER}/6[][  
           if(Fun2[0]==0) 4Ee+c-d8C  
           { ?C[T9X  
                 TStrCpy(Fun2,FunctionName); w<]`qmgI  
                 Func2Addr=PEFile.m_ExportFunc[n].Address; /wp| eSUt  
                 break; 6f6lPdO  
           } Gz/]g j#  
     } tfm9 _$9D  
      -mYl~eV(G  
      *F##gCjz|  
     PEFile2.m_OpenMode=PE_OPEN_NO_IMPORT|PE_OPEN_DLL; k4_-Io|r  
     bOK = PEFile2.Open(gszNtdllName,&hFile2); ?>Xl.Uv$C  
     if(bOK==false) dC"Irw  
     { Td/NWz  
           DbgPrint("Open ntdll.dll error/n"); &ari|} :  
           PEFile.Close(); ~2~Tlb;  
           return 0; kT;=Vw  
     } GrtS 3  
     NtdllAddr1 = PEFile2.GetExportFunc(Fun1); /Y? R#  
     NtDllAddr2 = PEFile2.GetExportFunc(Fun2); +FiT?q  
     memset(CodeBuffer,0,sizeof(CodeBuffer)); C/Byw:  
     ReadLen = PEFile2.ReadImageMemory(NtdllAddr1,CodeBuffer,sizeof(CodeBuffer)); molwfPo/r  
     if(ReadLen!=sizeof(CodeBuffer)) 3 ]5|z  
     { SY"8iWE  
           PEFile.Close(); =pK2R LI  
     } n&br&q  
     ServiceNum1 = *(DWORD*)&CodeBuffer[1]; n%97jD3W  
     memset(CodeBuffer,0,sizeof(CodeBuffer)); >yZ~t|o  
     ReadLen = PEFile2.ReadImageMemory(NtDllAddr2,CodeBuffer,sizeof(CodeBuffer)); #KWh5/  
     ServiceNum2 = *(DWORD*)&CodeBuffer[1]; ^hVwho  
8D@Q;-g  
     DbgPrint("%s = %08x %08x %08x/n",Fun1,NtdllAddr1,ServiceNum1,Func1Addr); &-?{X {  
     DbgPrint("%s = %08x %08x %08x/n",Fun2,NtDllAddr2,ServiceNum2,Func2Addr); cqy5JK t  
#~KrPZZf  
     for(n=0;n<(DWORD)PEFile2.m_ExportFuncCount;n++) Pbtr9KzT|`  
     { f07EWOsJ  
           FunctionName = PEFile2.m_ExportFunc[n].FuncName; V6b8y*=  
           if((FunctionName[0]=='N'&&FunctionName[1]=='t')||(FunctionName[0]=='Z'&&FunctionName[1]=='w')) dl>6  
           { )k&cT#qr}  
                 ReadLen = PEFile2.ReadImageMemory(PEFile2.m_ExportFunc[n].Address,CodeBuffer,sizeof(CodeBuffer)); BO[(S|  
                 if(ReadLen<sizeof(CodeBuffer))continue; 9 )k;R42,  
                 if(*(DWORD*)&CodeBuffer[1] > MaxServiceNum&&CodeBuffer[0]==0xb8) e+7A:F  
                 { ;)/^ZO j  
                       MaxServiceNum=*(DWORD*)&CodeBuffer[1]; sMCB7:  
                       DbgPrint("%s %d/n",FunctionName,MaxServiceNum); +*ID "k  
                 } [-g$?-V  
           } a}}{u+?N  
            #<ce'MHd  
     } $VEI&}k":z  
tDbj _&X*  
     PEFile2.Close(); 4[ws5A  
     if(ServiceNum1>ServiceNum2) J;'K^QGFZ  
     { |nhttk?  
           ServiceNum1+=ServiceNum2; ."TP Q7%/  
           ServiceNum2=ServiceNum1-ServiceNum2; 6 /5Vn  
           ServiceNum1-=ServiceNum2; -|U MC  
           Func1Addr+=Func2Addr; .k/hWn  
           Func2Addr=Func1Addr-Func2Addr; {Df#W7  
           Func1Addr-=Func2Addr; 5!?A>=g  
     } ^_^<]T.  
     ReadBuffer = new char[0x1007]; w9NL3U  
     memset(ReadBuffer,0,0x1007); 8L+24[,  
     ReadBufferLen = 0x1000; [;E=j8 !  
     ULONG KeServiceDescriptorTableFilePos=0; (f@w]ztTM  
     bool bFindOk=false; tnn`{ZnG  
     for(n = 0; n < PEFile.m_FileSize;n+=ReadBufferLen) Lm*v2w*$p  
     { Wv-Hq4  
           if(PEFile.m_FileSize-n<0x1000) rc86=5fg  
                 ReadBufferLen=PEFile.m_FileSize-n; N_RF(O  
           PEFile.ReadFile(n,&ReadBuffer[0x3],ReadBufferLen); X6q6p59N|  
           for(k=0;k<ReadBufferLen+3;k++) . Gq#1,T  
           { )ata=C{  
                 if(*(DWORD*)&ReadBuffer[k]==Func1Addr) bd/U?<ZH+  
                 { vi )*_  
                       m = k+(ServiceNum2-ServiceNum1)*sizeof(ULONG); 1 $t/+N  
                       if(m < ReadBufferLen) %~E;DSG.  
                       { iGyC  
                             if(*(DWORD*)&ReadBuffer[m]==Func2Addr) 8/Jy&  
                             { & phT,f  
                                   KeServiceDescriptorTableFilePos = n+k-3-ServiceNum1*sizeof(ULONG); @e'4]{$  
                                   bFindOk=true; ,-g5}N@  
                                   break; 7V|g}q0 /  
                             } %,W0:zC`J/  
                       } r*q}[MT  
                       else ," V&~n>  
                       { 3l'v n;  
                             m=m+n-3; fle+m:Z?>  
                             ULONG FuncAddr=0; .,e 3>Q  
                             PEFile.ReadFile(m,&FuncAddr,sizeof(ULONG)); O1: C^  
                             if(FuncAddr==Func2Addr) 2NLHs* X  
                             { }XN@4MS;P  
                                   KeServiceDescriptorTableFilePos=m; Y9fE V/.  
                                   bFindOk=true; Yv? Mz  
                                   break; }wYnMu  
                             } XKR8~nj:v  
                       } ra{/_(ba/  
                 } f9$!pGp  
           } +jZ s|O`  
           if(bFindOk)break; Z&I8<. U  
           *(DWORD*)&ReadBuffer[0] = *(DWORD*)&ReadBuffer[0xffd]; 6m0Kxp_EE  
     } SD!I Nm  
     if(bFindOk) }'^$tj  
     { &++*Z/:%B  
           DbgPrint("KeServiceDescriptorTableFilePos = %08x %d %08x %d/n",KeServiceDescriptorTableFilePos,KeServiceDescriptorTableFilePos,MaxServiceNum,MaxServiceNum); v7dm]<)/  
           if(MaxServiceNum>=0x1000) $_/Pu/T5  
                 MaxServiceNum=0x1000; *ct(JsN y  
           gOrgWindowsKeServiceDescriptorTable=new DWORD[MaxServiceNum]; 9jQnRz  
           if(gOrgWindowsKeServiceDescriptorTable) (|.4*w2*8  
           { lf5K4TGSj  
                 memset(gOrgWindowsKeServiceDescriptorTable,0,sizeof(DWORD)*MaxServiceNum); ~ 'pcx<t]  
                 ReadBufferLen=sizeof(DWORD)*MaxServiceNum; &JFvLQ8  
                 if(ReadBufferLen+KeServiceDescriptorTableFilePos>PEFile.m_FileSize) 2e0@-/5J`y  
                       ReadBufferLen=PEFile.m_FileSize-KeServiceDescriptorTableFilePos; Q0J[GE9:{  
                 PEFile.ReadFile(KeServiceDescriptorTableFilePos,gOrgWindowsKeServiceDescriptorTable,ReadBufferLen); QdvjI"P6  
                 gMaxServiceNum=ReadBufferLen/sizeof(DWORD); =|{ ;Ob  
                 for(n = 0; n < gMaxServiceNum;n++) Hmg@VgTR  
                 { 8o*(e`mm  
                       gOrgWindowsKeServiceDescriptorTable[n]+=(NtKernelBaseAddress - PEFile.m_ImageBase); d2w=MP  
                 } e9VA,r  
           } ,vK8-ba  
     } [ Zq~c6nl  
     delete []ReadBuffer; 9Y8+uw"2  
     PEFile.Close(); f/( ;QGI  
     return KeServiceDescriptorTableFilePos; J+7> ei  
}

 
SSDT获取原始服务地址的方法与原理(灯灯灯灯,我肥来了..) 好吧,我胡汉三肥来了..(确实肥了- -),几个月没发什么文章.其实.我也只是一个新丁~欢迎大家交流,高手勿喷,谢谢合作^_^     对于SSDT,不知道的同学请自己百度,判断出SSDT被HOOK之后,如何恢复成原始服务地址?主要方法有两个,简单来说,一个Ring0,一个Ring3的方法(可能分类不够准确),我今天除了介绍方法之外,主要还是讲讲里面的原理吧,原理神马的才是最吸引人的对吧. 阅读详情

相关推荐

深入解析Shadow SSDT服务函数原始地址获取技术

回顾这场长达二十年的攻防拉锯战,你会发现:SSDT Hook 曾经是 Rootkit 的标配技能;Shadow SSDT 的出现标志着微软开始推行纵深防御理念;PatchGuard 让“默认拒绝”成为内核设计的新哲学;如今的终端安全早已超越单一技术点,走向体系化对抗。而对于我们这些技术人员来说,理解这些底层机制的意义远不止于“炫技”。当你知道不仅是一个隐藏的结构,更是现代操作系统自我保护思想的具体体现时,你会更加敬畏每一行代码背后的工程智慧。

weixin_35257663的博客 1027

PE_导出表

PE

qq_42363151的博客 205

Windows内核SSDT Hook技术详解

SSDT(System Service Descriptor Table)是指系统服务描述表,它是Windows操作系统中用于管理系统服务调用的重要数据结构。SSDT定义了系统服务的入口点,允许系统和应用程序通过系统调用来访问各种服务。每个服务都有一个相应的索引号,通过这个索引,操作系统可以根据需要调用相应的服务。系统服务描述表(System Service Descriptor Table, SSDT)是Windows操作系统中用于存储系统服务函数地址的数据结构。

weixin_28681379的博客 1173

动态调用kernel任意函数(anycall)

有的时候只需要简单调用下别的kernel函数 或者别的模块函数没有export,而你又不想单独编译kernel重新下载的时候 或者动态去修改某个驱动的寄存器值。 首先看下效果及使用步骤: 加入kernel ,更多时候是驱动中有以下函数: ssize_t justfortest0() { printk(KERN_ERR"[anycall] successful....just

李子的备忘录 2051

SSDT表概念及遍历

windows内核SSDT表的概念和SSDT表的遍历代码示例

R0层获取ShadowSSDT函数原始地址实例

本实例由VS2008开发,在提供了一套驱动开发框架的同时,又演示了如何获取Shadow SSDT表函数原始地址的办法。 主要函数:ULONG GetShadowSSDT_Function_OriAddr(ULONG index); 原理说明: 根据特征码搜索导出函数KeAddSystemServiceTable来获取Shadow SSDT基址,以及通过ZwQuerySystemInformation()函数获取win32k.sys基址,然后解析PE定位到Shadow SSDT在win32k.sys的偏移地址,并通过进一步计算来得到Shadow SSDT表函数的原始地址。 这里只测试了三个函数:(460)NtUserMessageCall、(475)NtUserPostMessage和(502)NtUserSendInput,具体使用时可以举一反三,网上完整的源代码实例并不太多,希望可以帮到真正有需要的朋友。 系统环境: 在WinXP SP3系统 + 瑞星杀毒软件 打印输出: [ LemonInfo : Loading Shadow SSDT Original Address Driver... ] [ LemonInfo : 创建“设备”值为:0 ] [ LemonInfo : 创建“设备”成功... ] [ LemonInfo : 创建“符号链接”状态值为:0 ] [ LemonInfo : 创建“符号链接”成功... ] [ LemonInfo : 驱动加载成功... ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP 开始... ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP Enter IRP_MJ_DEVICE_CONTROL... ] [ LemonInfo : 获取ShadowSSDT表 (460)NtUserMessageCall 函数的“当前地址”为:0xB83ECFC4,“起源地址”为:0xBF80EE6B ] [ LemonInfo : 获取ShadowSSDT表 (475)NtUserPostMessage 函数的“当前地址”为:0xB83ECFA3,“起源地址”为:0xBF8089B4 ] [ LemonInfo : 获取ShadowSSDT表 (502)NtUserSendInput 函数的“当前地址”为:0xBF8C31E7,“起源地址”为:0xBF8C31E7 ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP_MJ_DEVICE_CONTROL 成功执行... ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP 结束... ] [ LemonInfo : UnLoading Shadow SSDT Original Address Driver... ] [ LemonInfo : 删除“符号链接”成功... ] [ LemonInfo : 删除“设备”成功... ] [ LemonInfo : 驱动卸载成功... ]

VC++实现恢复SSDT

SSDT(System Services Descriptor Table),系统服务描述符表。这个表就是一个把ring3的Win32 API和ring0的内核API联系起来。SSDT并不仅仅只包含一个庞大的地址索引表,它还包含着一些其它有用的信息,诸如地址索引的基地址、服务函数个数等。  通过修改此表的函数地址可以对常用windows函数及API进行hook,从而实现对一些关心的系统动作进行...

weixin_30809173的博客 241

SSDT表 hook 原理 教程源码

SSDT表 hook 原理 源码

windbg查看SSDT表

SSDT,System Services Descriptor Table,系统服务描述符表。 见此 https://blog.youkuaiyun.com/bcbobo21cn/article/details/52083557 这个表就是一个把ring3的Win32 API和ring0的内核函数联系起来。SSDT包含一个庞大的地址索引表,它还包含着一些其它有用的信息,诸如地址索引的基地址、服务函数个数等。 SSDT定义为下面结构体; typedef struct _SYSTEM_SERVICE_T...

bcbobo21cn的专栏 1585

SSDT表的Hook原理和示例代码

csdn的排版不是特别好,特此上传SSDT表的Hook原理文档和SSDK的Hook的示例代码。

SSDT 安装文件

SSDT for Visual studio 2015

获取SSDT,SSSDT原始函数地址

SSDT 当前函数地址 = KiSeviceTable + *(KiServiceTalbe + index * 4); TableRVA = KiSeviceTable - 内核真实加载地址 ; ImageBase = 0x140000000;(理想加载地址) ImageKiSeviceTable = ImageBase + TableRVA; LoadDLLBase = LoadLi

zhuhuibeishadiao 4886

机器学习发展历史及现状(重要的期刊,会议,大牛总结)

1 引言 机器学习是指通过计算机学习数据中的内在规律性信息,获得新的经验和知识,以提高计算机的智能性,使计算机能够像人那样去决策。随着各行业对数据的需求量增多,对处理和分析数据的效率要求变高,一系列机器学习算法应运而生。机器学习算法主要是指通过数学及统计方法求解最优化问题的步骤和过程。针对不同的数据和不同模型需求,选择和使用适当的的机器学习算法可以更高效地解决一些实际问题。本文将从机器学习的起源...

Oscar2018的博客 5万+

寻找原始表,恢复 ssdt 表 RING3

<br />标 题: 【原创】寻找原始表,恢复 ssdt 表 作 者: dummy 时 间: 2007-08-17,19:28 链 接: http://bbs.pediy.com/showthread.php?t=49848 // 只贴 ring3 部分,这也是最主要的代码,驱动只是负责把得到的原始值写到 ssdt,其他啥也不做 // 简单说一下,找 KiServiceTable 表过程, 是直接读取原始内核文件,寻找输出符号,然后结合重定位信息,谁向 KeServiceDes

Rootkit ﹏ 609

鸿蒙日历组件进阶:教你打造个性化日程管理界面(支持月份切换)

本文深入探讨了鸿蒙应用开发中自定义日历组件的构建方法。通过详解基于Grid的布局设计、核心日期算法、月份切换逻辑以及事件管理集成,指导开发者打造支持个性化日程管理的高性能日历界面,提升应用交互体验。

weixin_29207149的博客 68

IM 系统设计:仿微信架构,Netty + Protobuf + WebSocket 如何支撑百万级长连接?

相比 JSON,Protobuf 的体积通常只有前者的 1/5 到 1/10,且解析速度快一个数量级。// 消息类型:1-登录,2-心跳,3-单聊,4-群聊,5-ACK// 发送方ID// 接收方ID// 消息内容// 时间戳// 消息唯一ID,用于去重和ACK。

BUG猿的博客 1381

驱动开发:如何枚举所有SSDT表地址

中已经教大家如何寻找SSDT表基地址了,找到后我们可根据序号获取到该SSDT的地址,如果需要输出所有SSDT表信息,则可以定义字符串列表,以此循环调用。函数依次获取,SSDT列表我已经提取出来了,该办法虽然笨但也是可以正常使用的。

微软技术分享 9988

[xboard-real6410]39 real6410中的BL1和BL2实验及流程分析

文章目录uboot控制uboot 流程uboot加载kernel uboot控制 uboot 流程 uboot加载kernel

鹰之翔 298

SSDT原始地址, 现在地址

<br />#include <windows.h> #include <winnt.h> #include <WindowsX.h> #include <commctrl.h> #include <stdio.h> #define ibaseDD *(PDWORD)&ibase HINSTANCE g_hInst; HWND hWinMain,hList; #define ID_LISTVIEW 104 #pragma comment(lib,"comctl32") typedef

Rootkit ﹏ 761

【系统分析师】高分论文:论软件开发方法及应用(数据中心CMDB 系统)

【摘要】本文以作者负责的"数据中心CMDB系统"建设项目为例,探讨了系统分析和建模方法在IT项目中的应用实践。项目基于ITIL框架,旨在整合分散的配置信息,构建统一CMDB平台。通过分析结构化、面向对象和构件化三种开发方法特点,项目最终采用结构化分析与V模型结合的方式,并融入面向对象设计理念。系统经过4个月开发后上线,通过增量迭代满足不同数据源接口需求,采用适配器模式提高兼容性。经过2个月试点运行和优化,系统已稳定运行并获得用户认可,为后续IT服务管理集成奠定了基础。项目实施使作者积累了

数据知道的博客 4300

基于STM32L4XX、HAL库的RTL8211FSI-CG以太网收发器(PHY)驱动程序设计

一、简介:RTL8211FSI-CG是Realtek公司生产的一款高性能、低功耗的单端口10/100M以太网收发器(PHY)。它通过RMII(Reduced Media Independent Interface)或MII接口与MAC控制器连接。

zhusl6688的博客 534

x64技术之SSDT_Hook

x64技术之SSDT_Hook测试环境:虚拟机: Windows 7 64bit过PG工具驱动加载工具PCHunter64系统自带的计算器和任务管理器等实现思路:实际思路与win32的思路一样.都是替换SSDT表里边的函数地址.不过微软被搞怕了,所以在x64上做了一些手脚.具体手脚就是x64通过SSDT得到的函数地址,不是真实的函数绝对地址了,而是加密了的.HOOK1.得到系统服务表基址2.保存需...

Hades的博客 5998

EXCEL VBA从入门到精通 第一章:VBA入门

在VBA中,需要使用关键字Dim来定义一个变量,后面跟上变量名和变量的数据类型。例如,下面的代码定义了一个整型变量x和一个字符串变量name在VBA中,使用关键字Const来定义常量,后面跟上常量名和常量的值。例如,下面的代码定义了一个整型常量MAX_NUM和一个字符串常量MESSAGE需要注意的是,常量一旦被定义,其值就不能被改变。

1万+

SSDT Hook

看看大概的调用情况 左边是2000有的,右边是xp后走的 Ntdll.dll 中的 API 是一个简单的包装函数。 当 Kernel32.dll 中的 API 通过 Ntdll.dll 时,会完成参数的检查再调用一个中断(int 2Eh 或者 SysEnter 指令),从而实现从 Ring3 进入 Ring0 层 并且将所要调用的服务号(也就是在 S

zhuhuibeishadiao 3445

32、生物信息学中的符号、缩写及相关概念解析

本文详细解析了生物信息学中常用的符号、缩写及相关概念,涵盖概率理论、函数表示、模型结构、图与集合、维度参数、神经网络、隐藏马尔可夫模型、双向架构、语法系统、系统发育树、微阵列分析以及核方法与支持向量机等多个领域。通过表格和mermaid流程图的形式,系统梳理了各类符号的定义与应用场景,并介绍了常见缩写的全称与意义。文章旨在帮助研究人员准确理解生物信息学中的基础术语,提升对基因表达分析、序列建模、机器学习等技术的理解与应用能力。

rrr55的博客 148

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

上一篇: 多CPU的机器上在驱动中如何HOOK中断
下一篇: Protecting Your Code with Visual C++ Defenses
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值