关闭

关闭

关闭

封号提示

内容

首页 实用电脑技术实例-1268.PDF

实用电脑技术实例-1268.PDF

实用电脑技术实例-1268.PDF

等你来聊 2012-06-26 评分 0 浏览量 0 0 0 0 暂无简介 简介 举报

简介:本文档为《实用电脑技术实例-1268pdf》,可适用于高等教育领域,主题内容包含破解技术实例(转)Gloomy对Windows内核的分析标题:(转载)Gloomy对Windows内核的分析发帖者:一民详细信息:INTRO(写给N符等。

破解技术实例(转)Gloomy对Windows内核的分析标题:(转载)Gloomy对Windows内核的分析发帖者:一民详细信息:INTRO(写给NT研究者)=============================МывсеголишьмоментвовремениОтблесквглазах,Мечтыослепоте,Образыумирающегорассудка(c)byAnathema系统组件WindowsNT操作系统的内存格局WindowsNT与FLAT模型线程信息块(THREADINFORMATIONBLOCK)进程控制域(PROCESSORCONTROLREGION)系统组件=====================实际上所有的WindowsNT组件其本身都是DLL、PE格式的EXE文件、导入导出函数。WindowsNT的主要组件有:*Ntoskrnlexe系统核心。系统执行函数都集中于此这些函数又会调用其它组件。核心组件有:对象管理器、内存管理器、进线程创建、进线程控制、LPC、安全管理、异常处理、文件系统、输入输出、VDM、和тд一般都位于大于h的地址上。*Haldll硬件抽象层(HardwareAbstractionLayer)-硬件相关的模块。该隔离层将操作系统中硬件相关的部分隔离出来以增强系统的可移植性。主要的模块实现了非常底层的函数:程序控制中断、硬件输入输出等等。一般位于大于h的地址上。*Ntdlldll实现某些WinAPI函数。提供了核心模式与用户模式之间的接口。位于用户空间。换句话说系统函数调用主要由这里导出。*Kerneldll实现了一些函数类似于Winx的核心。其中有很多的函数封装在ntdlldll中。*Csrssexe进程服务器子系统。其是一个单独的进程因此受到保护以免受其它进程(位于其它进程的地址空间中)影响。对服务的请求要借助于LPC产生。*Winksys驱动程序。用以减少调用Csrss服务开销损失。在此程序中实现了GDI和USER函数。不用LPC而用系统调用-这很明显提高了WindowsNT和K的图形处理性能。WindowsNTWindowsNT操作系统的内存格局=============================在WindowsNT中高G的位线性地址空间保存了供系统使用的程序。这种格局地址空间ffffffff为系统组件:驱动程序、系统表、系统数据结构等等。系统内存的精确格局是不可能得到的但是通过其功能用途和大致位置可以区分出各个区域。*FFFFFFF系统代码。在这里驻留的是Hal和ntoskrnl的代码和数据还有驱动程序(boot驱动和加载ntosldr的驱动)。GDT、IDT和TSS结构体同样驻留在这些区域中。*CCFFFFFF系统表的区域。这个线性地址空间区域保存着进程的页表页目录和其它与进程结构体有关的东西。这个区域不是全局性的不像其它的系统空间区域而且对于于每一个进程来说会映射到不同的物理空间其保存着当前进程的数据结构。*EEFFFFF分页池。这个区域可以换出到磁盘上。操作系统中的大多数对象都在这个区域中产生。实际上一些内存池位于这个区域中。*FBFFDFEFFF不可换出页的区域即非分页区(NonPagedPoll)。这个区域中的数据永远不能换出到磁盘上。这个区域中的数据总是系统必需的数据。例如这里有进程与线程的信息块(Threadenvironmentblock,ProcessEnvironmentblock)。*FFDFFFFFFFFFFPCRProcessorControlRegion(进程控制域)用于每一个进程。这个区域中保存着PCR结构体。在此结构体中保存着系统状态的信息。例如关于IRQL、当前线程、IDT等的信息。低G线性地址空间(FFFFFFFF)为进程用户模式的地址空间(每个进程自己的空间)。Win地址空间看上去一般是下面这个样子:*FFFF保护区域。访问此区域会引发异常。被用于检测指针。*xx通常应用程序加载在这样的地址上。*Win子系统的库通常映射到这里。*FFBFFDFFF代码页。*FFDEFFDEFFF用户模式的ThreadEnvironmentBlock。*FFDFFFDFFFF用户模式的ProcessEnvironmentBlock。*FFEFFEFFF共享数据区。*FFFFFFFFFFF保护区域。WindowsNT与FLAT模型===========================自i开始在Intel的处理器里实现了四级保护机制相应的就有四个特权级。代码与数据能够拥有某级别的特权。这样应用程序、系统程序、内核等等都运行在自己的特权级上而且不能随意访问比自己特权级高的代码和数据。实际上没有一个基于Intel处理器的操作系统能用到所有的四个特权级(不为人知的那些不算在内)。WindowsNT操作系统也不例外只用到了两个特权级(ring)。级(最高特权级)下运行内核级(最低特权级)为用户级。Intel处理器提供了强大的内存分段机制其与特权级一起实现了直到段级的保护(例如程序的每一个逻辑段都可以由一个描述符表来描述)。但是WindowsNT实现的是FLAT模型。这就将选择子的使用降到了最低限度。处理器的全局描述符表GDT(GlobalDescriptorTable)由WindowsNT操作系统管理其包含以下描述符(由SoftIce'a得到):SelTypeBaseLimitDPLAttributesGDTbase=Limit=FFCodeFFFFFFFFPREDataFFFFFFFFPRWBCodeFFFFFFFFPREDataFFFFFFFFPRWTSSDABPBDataFFDFFFFFPRWBDataFFDFFFPRWDataFFFFPRWLDTEFFPTSSFPTSSFCPDataFFFFPRWDataBFFFPRWDataFFFFFFPRWCodeFFFFPREDataFFFFPRWDataPRWReservedNPEReservedNPEDataFFFFPRWFCodeDBDPEOFDataFFFFPRWReservedNPFReservedNP前四个选择子全都位于线性地址空间。而且前两个选择子的描述符特权级DPL(DescriptorPrivilegeLevel)等于而后面两个的都是。选择子和由用户应用程序使用。在FLAT模型下应用程序本身并不关心段寄存器的内容。在ring工作时CS、DS、SS寄存器总是分别为值、、。这样系统代码就可以监视段寄存器的值。选择子b和用于内核(驱动程序、系统代码)工作时的寻址。选择子和b分别指向KernelProcessRegion和ThreadInformationBlock。当代码运行在ring时FS寄存器的值为如过运行在ring则FS的值为b。选择子总是指向基址为FFDFF的描述符。选择子b指示的基址则依赖于用户线程。选择子定义了局部描述符表LDT(LocalDescriptorTable)。LDT只在VirtualDOSmachine(VDM)应用程序下使用。当运行该进程时在处理器的LDTR寄存器中加载着相应的指针否则LDTR的值为。LDT主要用在Windowsx应用程序下。Windowsx应用程序运行在WOW(WindowsOnWindows)下而WOW则实现在VDM进程里。VDM进程的LDT使用上和Winx里的一样。在GDT表里总会有两个TSS类型的选择子。这是因为运行在Intel处理器上的WindowsNT操作系统没有使用基于任务门的任务切换机制。IDT包含以下描述符(由SoftIce'a得到):IntTypeSel:OffsetAttributesSymbolOwnerIDTbase=FFCLimit=FFIntG:ECDPL=PKiTrapIntG:FDPL=PKiTrapTaskG:DPL=PIntG:FCADPL=PKiTrapIntG:DPL=PKiTrapFFIntG:DPL=PKiTrapFReserved:DPL=NPReserved:DPL=NPAIntG:EADPL=PKiGetTickCountBIntG:EDPL=PKiCallbackReturnCIntG:EADPL=PKiSetLowWaitHighThreadDIntG:EFCDPL=PKiDebugServiceEIntG:DDDPL=PKiSystemServiceFIntG:DPL=PKiTrapFIntG:FFCDPL=PHalpClockInterruptIntG:EDPL=PIntG:DDPL=PKiUnexpectedInterruptIntG:DPL=PIntG:CEDCDPL=PIntG:EDPL=PIntG:DCDPL=PKiUnexpectedInterruptIntG:DDPL=PKiUnexpectedInterruptIntG:ADPL=PHalpProfileInterruptIntG:DAADPL=PKiUnexpectedInterruptFFIntG:DCDPL=PKiUnexpectedInterrupt表中主要的门类型为中断门。中断任务只是用在关键的时刻保证特殊情况下能正确完成应急处理比如说双重异常(号中断)。中断e是系统调用。中断到f对应于irqirq。于是总是有两个TSS选择子。其中一个()用于双重异常。TSS中除了其自己必需部分所占空间外还在个字节中保存了一个输入输出位图。在执行Win应用程序的时候TSS中的指针保存着不正确的值这样任何对端口的操作都会引发异常。在VDM工作的时候位图用来选择是否禁止对端口的访问。我们来看一下在FLAT模型下是如何进行保护的。要研究这个问题需要将注意力转向下面这个条件保护的原则应该是:保护内核不受用户进程的干扰、保护一个进程不受另一个进程的干扰、保护子系统的代码和数据不受用户进程的干扰。WindowsNT的线性地址空间可以分成用户空间(通常为fffffff)和系统与内核空间(通常为ffffffff)。切换上下文时内核空间对于所有进程几乎都是一样的。在WindowsNT中使用了分页保护的内存。这样实现内核同用户进程隔离方法就是将核心空间地址页的页表项指针的US位置零。这样就不能在ring下随意访问ring下的代码和数据了。同样页的寻址也使得进程彼此间的地址空间得到隔离。WindowsNT保留了KB的页作为区域c中的页目录该页目录映射了所有的GB物理地址空间。在页目录中有个页目录项。每个页目录项都应是B大小(KB)。个页目录项指向个页表每个页表指向一个KB的页。页目录的基地址在上下文切换时会相应发生变化并指向将被使用的页目录当执行新线程时这个页目录被用于线性地址向物理地址的转换(在Intel处理器中这个物理基地址位于CR寄存器中)。结果不同的上下文中里的地址空间(fffffff)中一样的线性地址能够映射到不同物理地址上实现了进程地址空间的彼此隔离。内核空间实际上对所有的上下文都是一样的其被保护起来不能由用户代码访问内核代码的页表项的US位为零。下面我们将不讨论内核模式而是将注意力转到用户模式上来。的确ring和ring寻址使用的描述符有相同的基址和界限这可以作为用户在内核或内核驱动中出错的理由。发生错误时可能会破坏当前进程地址空间中的代码和数据。例如用户进程指针校验错误时调用内核服务可能破坏内核的代码和数据。操作系统的子系统通过导出调用的DLL模块来提供自己的服务。在用户进程向子系统转换时比如调用WInAPI函数开始总是运行DLL模块的代码。随后DLL模块的代码可能通过LPC进行系统调用。所以DLL模块被映射到用户空间中共享进程上下文使用库函数必须保护DLL模块中的代码和数据不会受到可能发生的直接访问。事实上这种并不能保护数据。所有的保护都是通过页表项的RW和US位来实现的。DLL模块的代码和数据通常只允许被读取。用户进程能够不经允许而向数据中写入当然如果告知它们大致的线性地址也可以允许写入。但是如果需要每一个进程能产生自己的数据副本(copyonwrite机制)。例如会有以下的情况出现:分析PE文件kerneldll的文件头可以确定datasection的虚拟地址随后写程序向这个区域写入错误数据之后校对脏数据。在新进程启动时数据将是“恢复了的”。因此如果有进程和子系统破坏系统的正常运行则其只会在自己的上下文中发挥作用。除此之外所有关键的数据(直接访问可能会损害子系统的整体性的数据或是重要的数据)都位于单独的进程地址空间中子系统服务器。使用这些数据的操作都是通过从子系统DLL模块转向服务来进行的(通过LPC)。我们注意到这个操作开销较大所以在WindowsNT中开始进行一系列的尝试来使之减少。特别重要的是现在GDI和USER函数都实现在内核里(更准确的说是在驱动程序Winksys里)。事实上产生了一个结论在安全性上子系统大量依赖于对其的周密考虑。页保护机制本身提供的保护是不够的。线程信息块(THREADINFORMATIONBLOCK)======================================================在线程执行的时候在用户模式下FS寄存器的值为b。这个选择子用于寻址一个结构体这个结构体位于NTDDKH文件中叫做THREADENVIRONMENTBLOCK。每一个线程都有其自己的结构体并在上下文切换时选择子中的基址会改变以指向当前线程线程的这个结构体。在NTDDKH中对这个结构体只描述了很少的一部分如NTTIB(ThreadInformationBlock)。其实NTTIB是结构体NTTEB和NTTIB的结合。NTTEB是用户模式线程访问的结构体。NTTIB通过选择子从内核模式下访问。TEB结构体的几个域在NTDDKH(WindowsNT)中没有描述:typedefstructEXCEPTIONREGISTRATIONRECORD{structEXCEPTIONREGISTRATIONRECORD*pNextFARPROCpfnHandler}EXCEPTIONREGISTRATIONRECORD,*PEXCEPTIONREGISTRATIONRECORDtypedefstructNTTIB{structEXCEPTIONREGISTRATIONRECORD*ExceptionListhHeadofexceptionrecordlistPVOIDStackBasehPVOIDStackLimithPVOIDSubSystemTibChunion{hPVOIDFiberDataforTIBULONGVersionforTEB}PVOIDArbitraryUserPointerhAvailableforapplicationusestructNTTIB*SelfhLinearaddressofTEBstructure}NTTIBtypedefNTTIB*PNTTIBtypedefstructTEB{Size:xF**NTTIBNtTib*C*VOID*EnvironmentPointer**CLIENTIDClientIdPROCESSid,THREADid**HANDLEActiveRpcHandle*C*VOID*ThreadLocalStoragePointer**PEB*ProcessEnvironmentBlockPEB**ULONGLastErrorValue**ULONGCountOfOwnedCriticalSections*C*ULONGCsrClientThread**ULONGWinThreadInfo**UCHARWinClientInfoxC*C*ULONGWOWReserved*C*ULONGCurrentLocale*C*ULONGFpSoftwareStatusRegister*CC*UCHARSystemReservedxDExitStack*A*ULONGSpare*A*ULONGExceptionCode*AC*UCHARSpareBytesx*D*UCHARSystemReservedx*FC*UCHARGdiTebBatchxE*DC*ULONGgdiRgn*E*ULONGgdiPen*E*ULONGgdiBrush*E*CLIENTIDRealClientId*F*ULONGGdiCachedProcessHandle*F*ULONGGdiClientPID*F*ULONGGdiClientTID*FC*ULONGGdiThreadLocalInfo**UCHARUserReservedx**UCHARglDispatchTablex*B*UCHARglReservedx*BDC*ULONGglReserved*BE*ULONGglSectionInfo*BE*ULONGglSection*BE*ULONGglTable*BEC*ULONGglCurrentRC*BF*ULONGglContext*BF*ULONGLastStatusValue*BF*LARGEINTEGERStaticUnicodeString*C*UCHARStaticUnicodeBufferxC*EC*ULONGDeallocationStack*E*UCHARTlsSlotsx*F*LARGEINTEGERTlsLinks*F*ULONGVdm*FC*ULONGReservedForNtRpc*F*LARGEINTEGERDbgSsReserved*F*ULONGHardErrorsAreDisabled*FC*UCHARInstrumentationx*FC*ULONGWinSockData*F*ULONGGdiBatchCount*F*ULONGSpare*F*ULONGSpare*FC*ULONGSpare*F*ULONGReservedForOle*F*ULONGWaitingOnLoaderLock}TEB,*PTEB在Windows下位于TIB中的偏移x的是指向拥有该线程的进程的基址数据指针。在WindowsNT中这个偏移保存的是指向结构体的指针该结构体实现于kerneldll。遗憾的是到现在为止除了几个域之外我还不清楚这个结构体的格式。除此之外类似的在WinK中PEB结构体也发生了变化。typedefstructPROCESSPARAMETERS{**ULONGAllocationSize**ULONGActualSize**ULONGFlagsPPFLAGxxx*c*ULONGUnknown**ULONGUnknown**ULONGUnknown**HANDLEInputHandle*c*HANDLEOutputHandle**HANDLEErrorHandle**UNICODESTRINGCurrentDirectory**HANDLECurrentDir*c*UNICODESTRINGSearchPaths**UNICODESTRINGApplicationName**UNICODESTRINGCommandLine**PVOIDEnvironmentBlock*c*ULONGUnknownUNICODESTRINGUnknownUNICODESTRINGUnknownUNICODESTRINGUnknownUNICODESTRINGUnknown}PROCESSPARAMETERS,*PPROCESSPARAMETERStypedefstructPEB{Size:xD**UCHARInheritedAddressSpace**UCHARReadImageFileExecOptions**UCHARBeingDebugged**UCHARSpareBoolAllocationsize**HANDLEMutant**HINSTANCEImageBaseAddressInstance*C*VOID*DllList**PPROCESSPARAMETERS*ProcessParameters**ULONGSubSystemData**HANDLEDefaultHeap*C*KSPINLOCKFastPebLock**ULONGFastPebLockRoutine**ULONGFastPebUnlockRoutine**ULONGEnvironmentUpdateCount*C*ULONGKernelCallbackTable**LARGEINTEGERSystemReserved**ULONGFreeList*C*ULONGTlsExpansionCounter**ULONGTlsBitmap**LARGEINTEGERTlsBitmapBits*C*ULONGReadOnlySharedMemoryBase**ULONGReadOnlySharedMemoryHeap**ULONGReadOnlyStaticServerData**ULONGAnsiCodePageData*C*ULONGOemCodePageData**ULONGUnicodeCaseTableData**ULONGNumberOfProcessors**LARGEINTEGERNtGlobalFlagAddressofalocalcopy**LARGEINTEGERCriticalSectionTimeout**ULONGHeapSegmentReserve*C*ULONGHeapSegmentCommit**ULONGHeapDeCommitTotalFreeThreshold**ULONGHeapDeCommitFreeBlockThreshold**ULONGNumberOfHeaps*C*ULONGMaximumNumberOfHeaps**ULONGProcessHeaps**ULONGGdiSharedHandleTable**ULONGProcessStarterHelper*C*ULONGGdiDCAttributeList*A*KSPINLOCKLoaderLock*A*ULONGOSMajorVersion*A*ULONGOSMinorVersion*AC*USHORTOSBuildNumber*AE*USHORTOSCSDVersion*B*ULONGOSPlatformId*B*ULONGImageSubsystem*B*ULONGImageSubsystemMajorVersion*BC*ULONGImageSubsystemMinorVersion*C*ULONGImageProcessAffinityMask*C*ULONGGdiHandleBufferx*C*ULONGPostProcessInitRoutine**ULONGTlsExpansionBitmap**UCHARTlsExpansionBitmapBitsx*D*ULONGSessionId}PEB,*PPEB在TEB的开头是NTTIB结构体(TEB和TIB的结合)。这个结构体中的大部分名字都很易懂最有意思的是指向异常处理链表的指针peExcept(Fs:)。这个域经常被引用。如果在随便某个Win应用程序下看一下实际的情况可以看到类似下面这样的代码:B:Amoveax,fs:B:pushebpB:BECmovebp,espB:AFFpushFFBB:FBpushBFB:BpushBB:pusheaxB:movfs:,espBD:ECsubesp,这段有代表性的代码是由编译器生成的用于在堆栈中生成EXCEPTIONREGISTRATIONRECORD。这个堆栈中的结构体用于实现称作“structuredexceptionhandling”的机制这就是结构化异常处理。接着我们来看WindowsNT下的结构化异常处理。这个机制可真是十分著名而且实现在编译器的细节之中。在MSDN中可以找到MattPetriek写得非常详细的文章题为“ACrashCourseontheDepthsofWinStructuredExceptionHandling”此文介绍的就是这项机制。FS:中的指针是指向EXCEPTIONREGISTRATIONRECORD首部的指针。对应地每个结构体在pNext域中包含着指向下一个结构体的指针和指向回调函数pfnHandler的指针。不难猜到这就是异常处理的处理程序。函数的原型如下:EXCEPTIONDISPOSITIONcdeclexcepthandler(structEXCEPTIONRECORD*ExceptionRecord,void*EstablisherFrame,structCONTEXT*ContextRecord,void*DispatcherContext)我们来分析函数的参数。第一个参数是指向下面结构体的指针。typedefstructEXCEPTIONRECORD{DWORDExceptionCodeDWORDExceptionFlagsstructEXCEPTIONRECORD*ExceptionRecordPVOIDExceptionAddressDWORDNumberParametersDWORDExceptionInformationEXCEPTIONMAXIMUMPARAMETERS}EXCEPTIONRECORDExceptionCode是WindowsNT的异常代号。异常在NTSTATUSH文件中被描述为STATUXxxxxxx:ExceptionAddres发生异常的地址。第三个参数是指向CONTEXT结构体的指针。typedefstructCONTEXT{DWORDContextFlagsDWORDDrDWORDDrDWORDDr:DWORDEspDWORDSegSs}CONTEXT这个结构体定义于WINNTH文件。其意义是不言而喻的这里就不全写了。函数返回下面枚举类型值中的一个:typedefenumEXCEPTIONDISPOSITION{ExceptionContinueExecution,ExceptionContinueSearch,ExceptionNestedException,ExceptionCollidedUnwind}EXCEPTIONDISPOSITIONExceptionFlags定义了下面的位标志:#defineEHNONCONTINUABLE#defineEHUNWINDING#defineEHEXITUNWIND#defineEHSTACKINVALID#defineEHNESTEDCALLx在发生异常时控制传递到ntoskrnlexe中相应的处理程序。例如如果试图下面这段代码:moveax,hmovdwordptreax,这会引发异常e控制传递向处理程序KiTrapE堆栈中错误号为(试图在用户模式下向内核写入。该页位于内存中因为线性地址h是内核加载的起始地址)。之后控制传递到ntdlldll在这里解析线程的TEB并顺次执行链表中所有的处理程序直到某个函数的返回代号不是ExceptionContinueSearch。在此之后再次调用链表中的所有处理函数直到找到某个函数但这次用的是另外一个代号ExceptionCode(STATUSUNWIND)并在ExceptionFlags设置位EHUNWINDINGS。这个标志用于异常处理进行堆栈的清除和其它必要的工作。如果没有一个处理程序能处理则就来到链表中最后一个处理程序由Win子系统建立的处理程序。这个处理程序是如何被建立的以及建立在哪里在以后研究CreateProcessW函数时会讲到。关于异常处理的完整介绍可以从MSDN获得因为在反汇编源代码中所得到的是扩大化了的异常处理机制(更高层次的机制)。进程控制域(PROCESSORCONTROLREGION)===========================================================当线程在内核模式下执行时在FS寄存器中加载的是选择子用于寻址PCR结构体(基址xFFDFF界限xFFF)。在NTDDKH中远没有描述结构体所有的成员只是其中不多的部分。为了说明PCR中的成分信息这里列出用于i的结构体(WindowsNT)typedefstructKPCR{Size:xB**NTTIBNtTib*C*structKPCR*SelfPcr**structKPRCB*PrcbCurrentPCB**KIRQLIrqlCurrentIRQL**ULONGIRR*C*ULONGIrrActive**ULONGIDR**ULONGReserved**structKIDTENTRY*ULONGIDT*C*structKGDTENTRY*GDT**structKTSS*TSS**USHORTMajorVersion**USHORTMinorVersion**KAFFINITYSetMember*C*ULONGStallScaleFactor**UCHARDebugActive**UCHARNumberEndofofficialportionofKPCR**BOOLEANVdmAlert**UCHARReserved**UCHARKernelReservedxx**ULONGSecondLevelCacheSize**UCHARHalReservedxDx*D*ULONGInterruptMode*D*ULONGSpare*DC*UCHARKernelReservedxxDCNotethatcurrentthreadisatoffsetx(pointertoKTHREAD)ThisessentiallymeansthatthestPRCBmustmatchtheactiveCPU**UCHARPrcbDataxBxPCBsforallCPUssupported}KPCR,*PKPCRPCR包含着指向PCRB(ProcessorControlRegion)的指针但实际上PCRB位于PCR的偏移x处并且所有的向PCRB域的转换都是相对于PCR的起点的。在WINNTH中描述了PCRB结构体。这里给出整个结构体(WindowsNT):xfromKPCRtypedefstructKPRCB{**USHORTMinorVersion**USHORTMajorVersion**structKTHREAD*CurrentThread**structKTHREAD*NextThread*c*structKTHREAD*IdleThread**CCHARNumber**CCHARReserved**USHORTBuildType**KAFFINITYSetMember**structRESTARTBLOCK*RestartBlock**CCHARCpuType**CCHARCpuID*A*CCHARCpuStep*C*KPROC

用户评论(0)

0/200

精彩专题

上传我的资料

每篇奖励 +1积分

资料评分:

/27
0下载券 下载 加入VIP, 送下载券

意见
反馈

立即扫码关注

爱问共享资料微信公众号

返回
顶部

举报
资料