手工构造典型PE文件.doc_第1页
手工构造典型PE文件.doc_第2页
手工构造典型PE文件.doc_第3页
手工构造典型PE文件.doc_第4页
手工构造典型PE文件.doc_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

2009-06-08 11:38:40 来源:黑客防线一直以来都在学习PE文件结构,从不敢轻视,但是即使如此还是发现自己在这方面有所不足,于是便想到了用纯手工方式打造一个完整的可执行的PE文件。在这期间我也查了大量资料,但是这些资料都有一个通病就是不 .一直以来都在学习PE文件结构,从不敢轻视,但是即使如此还是发现自己在这方面有所不足,于是便想到了用纯手工方式打造一个完整的可执行的PE文件。在这期间我也查了大量资料,但是这些资料都有一个通病就是不完整,看雪得那个只翻译了一部分,加解密技术内幕介绍的更是笼统,而且是打造一个只有180字节的PE文件,是高手们茶余饭后的怡情小游戏。鉴于此,心想为什么不自己摸索着手工打造一个完整些的呢?一是加强一下自己对于PE文件的了解,二是写出一篇参考性比较强的文章,给有志于在此发展的朋友们铺一铺路,也算是干了一件利国利民的好事。对于手工打造PE文件,我个人认为至少要分为三篇文章来阐述,每篇相对独立,合起来形成一个相对的体系。第一篇文章(也就是本文)用来介绍怎样用手工打造一个最典型、最简单的PE文件,而后两篇文章的问世还要引用潘爱民先生的一句话“还需要时日与机缘”。本文介绍的PE文件手工编辑方式,是本着以下三个原则所写的,望读者注意:1、完整性:对于手工打造PE文件所不需注意的字段也进行了必要的介绍,因此整文可能显得非常臃肿。2、典型性:完全按照典型的PE文件结构构造,因此对于某些不常见的PE文件结构有一定差距。3、易学性:对于字段之间的逻辑关系进行了比较细致的介绍,因此对于一部分底子比较好的读者来说可能显得有些啰嗦。为了方便各位阅读与查阅,我将文章分成了三各部分,以便各位读者各取所需,不用把宝贵的精力浪费在查找上。1、PE文件整体信息,提供了一个剖析PE文件的图表,以便于读者对于PE文件有一个整体的了解,并监督自己的工作进度。2、对于重点字段的介绍,以及字段之间的逻辑关系,建议首先从这里开始看。3、手工构造PE文件字段清单,此清单包含构造一个完整PE文件的每一个字节,跟着这个清单走就可以构造一个PE文件。对于第一次手工打造PE文件的朋友们来说,你们可以以“一、整体性息”为大纲,并参考第三部分一块一块的慢慢打造,如果有不懂的地方就去看第二部分。选读:为什么要手工打造PE文件?我们知道,往往从一个系统可执行文件结构上,就可以看整个操作系统的一些特性。也就是说PE里有Windows操作系统结构与运行机理的影子。由此可见,PE文件必然是一个非常庞杂且逻辑复杂的结构,那么为什么我们还要“自取其辱”来手工制造一个PE文件呢?这就要从PE文件的重要性说起了。我们现今组成Windows大家庭的主要成员就是PE文件了,里面包括EXE、DLL、OCX、SYS等一切最有价值的文件都是PE文件格式,出于对版权的考虑或对某种技术的渴求,任何一种与Windows系统相关的行为最终都要归集到这里-PE文件。特别是对于想学习加壳、破解、搞虚拟机的朋友们来说,熟知PE文件结构更是必不可少的基本功!但也正是由于PE文件的复杂性,我们才要采取一些特别的办法来攻克它,其中手工打造PE文件就是一条捷径。你可以想像一下,如果你都可以手工打造PE文件的话,那么对于PE文件的了解更是可见一斑了。但是我还想提醒一下各位读者,即便是如此,我们所了解的也仅仅是一部分,不过一般情况下已经足够了。一、整体性息这部分以图表的形式表示PE文件的整体结构。-*-*| DOS Header(IMAGE_DOS_HEADER) | -64 ByteDOS头部 -| DOS Stub | -112 Byte-*-*| PE00 (Signature) | -4 Byte-| IMAGE_FILE_HEADER | -20 BytePE文件头 -| IMAGE_OPTIONAL_HEADER32 | -96 Byte-| 数据目录表 | -128 Byte-*-*| IMAGE_SECTION_HEADER | -40 Byte-块表 | IMAGE_SECTION_HEADER | -40 Byte-| IMAGE_SECTION_HEADER | -40 Byte-*-*|.text | -512 Byte-块 |.rdata | -512 Byte-|.data | -512 Byte-*-*| COFF行号 | -NULL-调试信息 | COFF符号表 | -NULL-| Code View 调试信息 | -NULL-*-*这部分内容的意义有二:1、对于PE文件有一个整体的认识。2、方便审查自己的构造进度。这里我们重点介绍怎样用其审查自己的构造进度,首先希望各位读者明白我们将要手工构造的一个体积为2560字节的这个小家伙,对于初次上手的读者们来说并不是一件小的工程,因此有必要知道自己现在正做什么,以及做到哪里了。记得我少年学画时老师教我们构图就要从整体到局部,后来自学编程仍然是先实现大的框架再去解决每一个细节问题。OK,现在到了这里,很显然我们仍然需要本着从整体到局部的思想来构造我们的PE文件。那好,我们先搞明白第一个问题“我们的文件体积是怎么计算出来的呢”。首先我们要知道,PE文件自始至终都是以一种节的思想来构造的,那么我们就要从节开始。对于本文所讲述的PE文件来讲总共有三个区块(节),他们分别用来存放可执行代码、输入表信息以及全局变量,接触过PE文件的朋友对于区块的概念应该不陌生,我们知道Windows下的很多应用程序的文件对齐粒度,也就是大名鼎鼎的FileAlignment字段的值多为200h Byte,也就是十进制的512 Byte。我们同样应该知道,对于不足512字节的区段,余下部分要用00h填充到512字节大小,对与超过部分(例如513字节的区段)我们就要在多分配给他512字节个空间。当然,这些基础知识我想有一部分读者应该比较熟悉,那么对于PE文件头部分呢?也是如此吗?例如本例中的PE头就占用了544个字节,但是很显然这要使其填充到1024(400h)字节处才能开始第一个区段.text段。正是如此,我们整个文件的体积就是PE头+3个区段的体积之和,也就是PE头(512*2)+3个区段(512*3)=2560,这也就是我们所构造的PE文件的最终大小了。其次我们提前搞清楚一些字段与区段的偏移量也是比较重要的,这里对于计算方式不再多说,请大家直接看下面的表:1、PE头开始处 000000B0h2、IMAGE_OPTIONAL_HEADER32开始处 000000C8h3、数据目录表开始处 00000128h4、块表开始处 000001A8h5、.text块开始处 00000400h6、.rdata块开始处 00000600h7、.data块开始处 00000800h当然,上面的那些Offset只是针对本文件而言,并不绝对,具体情况还要具体分析。到此,本段就告一段落了,剩下的两段为了提高效率我并没有加以润色,全都是干货,希望各位读者能吃下这两块营养丰富的压缩饼干二、重点字段介绍这里只对需手工构造的字段进行着重介绍,详细的PE文件结构字段清单请见第三部分。1、DOS头部1-1 DOS Header1-1-1 e_magic WORD -4D 5A (* DOS可执行文件头标记)注释:此处值总是为MZ的16进制码。1-1-19 e_lfanew DWORD -B0 00 00 00 (* 指向PE文件头的偏移量。0xB0=64+112)注释:此处的值正好为为DOS头部的大小,因为DOS头部后面就是PE文件头部分了。2 PE文件头2-1 PE002-1-1 Signature DWORD -50450000h (* PE文件头标记)注释:此处的值总是为PE的16进制值加0000h。2-2 IMAGE_FILE_HEADER2-2-1 Machine WORD -4C 01 (* 可执行文件的目标CPU类型)注释:此PE文件可以运行于哪个CPU下,其标志就为相应的值。*-*| 机器 | 标志 |-| Intel i386 | 14Ch |-| MIPS R3000 | 162h |-| MIPS R4000 | 166h |-| Alpha AXP | 184h |-| Power PC | 1F0h |*-*2-2-2 NumberOfSections WORD -03 00 (* 区块数目)注释:此值决定此PE文件的区块数目,本文件为3个区块。2-2-6 SizeOfOptionalHeadr WORD -E0 00 (* PE头(IMAGE_OPTIONAL_HEADER32)大小)注释:此值表示PE文件头的大小。2-2-7 Characteristics WORD -0F 01 (* 文件属性)注释:此值为文件的执行属性。EXE文件此值一般为010Fh,DLL文件此值一般为0210h。2-3 IMAGE_OPTIONAL_HEADER322-3-1 Magic WORD -0B 01 (* 标记字)注释:此处是一个标记字,用于描述次PE文件的映像类型。ROM映像为0107h;普通可执行映像010Bh;PE32+则是020Bh。2-3-7 AddressOfEntryPoint DWORD -00 10 00 00 (* 程序执行入口RAV)注释:通俗的说就是指向可执行代码区块(例如.text)的首地址。2-3-10 ImageBase DWORD -00 00 40 00 (* 程序默认装入基地址)注释:是指文件在内存中首选的装入地址。2-3-11 SectionAlignment DWORD -00 10 00 00 (* 内存中区块对齐值)注释:PE文件被装入内存中时的块对齐大小,也叫做块粒度。其默认的对其尺寸是CPU的页尺寸。2-3-12 FileAlignment DWORD -00 02 00 00 (* 文件中区块对齐值)注释:磁盘上PE文件的区块对齐大小。这个值必须是2的幂,并且最小为200h。2-3-17 MajorSubsystemVersion WORD -04 00 (* 运行所需最低子系统主版本号)注释:要求最低的子系统主版本号,一般情况下都为4。2-3-18 MinorSubsystemVersion WORD -00 00 (* 运行所需最低子系统次版本号)注释:要求最低的子系统次版本号,一般情况下都为0。2-3-20 SizeOfImage DWORD -00 40 00 00 (* 映像装入内存后的总尺寸)注释:指的是装入文件从Image Base到最后一个区块的总大小。2-3-21 SizeOfHeaders DWORD -00 40 00 00 (* DOS头、PE头、区块表的总大小)注释:指的是DOS头、PE头与区块表的总大小,并且所有这些项目都出现在PE文件中任何代码或数据块之前。此值遵守文件对齐粒度。2-3-23 Subsystem WORD -03 00 (* 文件子系统)注释:标明可执行文件所期望的子系统(用户界面类型)。*-*-*| 值 | 子系统 |*-*-*| 0 | 未知 |-| 1 | 不需要子系统(如驱动程序) |-| 2 | 图形接口子系统(GUI) |-| 3 | 字符子系统(CUI) |-| 5 | OS/2字符子系统 |-| 7 | POSIX字符子系统 |-| 8 | 保留 |-| 9 | Windows CE图形界面 |*-*-*2-3-30 NumberOfRvaAndSizes DWORD -10 00 00 00 (* 数据目录标的项数,默认总为16)注释:数据目录的项数。这个字段字NT系统发布以来就一直是16。2-4 数据目录表2-4-2 Import Table注释:输入表2-4-2-1 VirtualAddress DWORD -10 20 00 00 (* 数据块的起始RAV)注释:输入表的起始地址,要去除IAT所占空间,直接从第一个IID开始。2-4-2-2 Size DWORD -3C 00 00 00 (* 数据块的长度)注释:从第一个IID到最后一个IMAGE_IMPORT_BY_NAME的总长度。3 块表3-1 IMAGE_SECTION_HEADER (1 .text)3-1-1 Name BYTE -2E 74 65 78 74 00 00 00 (* 8个字节的块名)注释:此区块的名称,限制在8字节以内。3-1-2 VirtualSize DWORD -26 00 00 00 (* 被实际使用的区块大小)注释:此区块包含数据的大小。3-1-10 Characteristics DWORD -20 00 00 60 (* 该区块的读写、执行属性)注释:*-*| 字段值 | 用 途 |-| 00000020h | 包含代码,常与10000000h一起设置 |-| 00000040h | 包含已初始化数据 |-| 00000080h | 包含未初始化数据 |-| 02000000h | 可以被丢弃 |-| 10000000h | 共享块 |-| 20000000h | 可执行 |-| 40000000h | 可读 |-| 80000000h | 可写 |-4 块4-1 .text (* 此区段是一段汇编代码的16进制形式,功能是弹出一个MessageBox提示框)-HEX6A 00 68 00 30 40 00 68 07 30 40 00 6A 00 E8 0700 00 00 6A 00 E8 06 00 00 00 FF 25 08 20 40 00FF 25 00 20 40 00注释:这是下面汇编指令的16进制模式。-ASM00401000 6A 00 PUSH 000401002 68 00304000 PUSH first_PE.0040300000401007 68 07304000 PUSH first_PE.004030070040100C 6A 00 PUSH 00040100E E8 07000000 CALL 00401013 6A 00 PUSH 000401015 E8 06000000 CALL 0040101A FF25 08204000 JMP DWORD PTR DS:00401020 FF25 00204000 JMP DWORD PTR DS:4-2 .rdata (* 该区块包含输入表)4-2-1 IMAGE_THUNK_DATA32 (IAT 1)注释:这里有很多人都搞不明白,其实IMAGE_THUNK_DATA32是一个联合体,可以同时代表IAT与INT。4-2-1-1 AddressOfData DWORD -76 20 00 00 (* 指向IMAGE_IMPORT_BY_NAME的RVA)注释:作为IAT时我们就会使用他的AddressOfData成员,用来存放指向IMAGE_IMPORT_BY_NAME的RVA,当程序装入内存后,只与IAT交换信息,输入表的其他部分就不再需要了。【由于本例子两个API函数引自与两个不同的DLL文件,所以要补00000000h结束。】注释:这里同样有很多人不明白,每当属于某一个DLL文件的API罗列完毕后,就要输入00加以结束。4-2-3 IMAGE_IMPORT_DESCRIPTOR (IID 1)注释:这里稍微复杂些,它的作用就是使用INT指定某个DLL文件中的API函数,并配合IAT指向相关API的地址。4-2-3-1 OriginalFirstThunk DWORD -4C 20 00 00 (* 指向输入名称表INT的RVA)注释:这里指定某个系统DLL文件中的API函数。4-2-3-4 Name DWORD -6A 20 00 00 (* 指向DLL名字的RVA与指针)注释:这里指定某个系统DLL文件。4-2-3-5 FirstThunk DWORD -08 20 00 00 (* 指向输入地址表IAT的RVA)注释:这里指定相关的IAT,并由IAT在IMAGE_IMPORT_BY_NAME中获得相应API的地址。4-2-4 IMAGE_IMPORT_DESCRIPTOR (IID 2)4-2-4-1 OriginalFirstThunk DWORD -54 20 00 00 (* 指向输入名称表INT的RVA)4-2-4-4 Name DWORD -84 20 00 00 (* 指向DLL名字的RVA与指针)4-2-4-5 FirstThunk DWORD -00 20 00 00 (* 指向输入地址表IAT的RVA)【填充20个00h空字节做结尾标记】注释:关于填充20个字节作为IID的结尾标记只是一个规律,还没找到相关资料证实。4-2-5 IMAGE_THUNK_DATA32 (INT 1)4-2-5-1 ForwarderString DWORD -5C 20 00 00 (* 指向一个转向字符的RVA)注释:直接指向相关API函数。【由于本例子两个API函数引自与两个不同的DLL文件,所以要补00000000h结束。】注释:与上面的IAT原理一样,就是这样的一个格式。4-2-7 IMAGE_IMPORT_BY_NAME ( 1 )4-2-7-2 Name BYTE -4D 65 73 73 61 67 65 42 6F 78 41 (* MessageBoxA的16进制码)注释:相关API函数的16进制代码。【后跟输出此函数的DLL名称16进制码00 75 73 65 72 33 32 2E 64 6C 6C 00 00 user32.dll】注释:相关系统的API函数罗列完毕后,通常都在最后一个API后空00h,并跟着这个DLL名称的16进制数据。总结:这里罗列了一些需要手工构建的部分结构,如果想看更加详细的请关注下面的内容。三、PE文件结构字段清单1 DOS头部1-1 DOS Header1-1-1 e_magic WORD -4D 5A (* DOS可执行文件头标记)1-1-2 e_cblp WORD -00 00 (文件最后页的字节数)1-1-3 e_cp WORD -00 00 (文件页数)1-1-4 e_crlc WORD -00 00 (重定位元素个数)1-1-5 e_cparhdr WORD -00 00 (以段落为单位的头部大小)1-1-6 e_minalloc WORD -00 00 (所需的最小附加段)1-1-7 e_maxalloc WORD -00 00 (所需的最大附加段)1-1-8 e_ss WORD -00 00 (初始的堆栈段(SS)相对偏移量值)1-1-9 e_sp WORD -00 00 (初始的堆栈指针(SP)值)1-1-10 e_csum WORD -00 00 (校验和)1-1-11 e_ip WORD -00 00 (初始的指令指针(IP)值)1-1-12 e_cs WORD -00 00 (初始的代码段(CS)相对偏移量值)1-1-13 e_lfarlc WORD -00 00 (重定位表在文件中的偏移地址)1-1-14 e_ovno WORD -00 00 (覆盖号)1-1-15 e_res WORD 4 dup -00 00 (保留字,一般都是为确保对齐而预留)1-1-16 e_oemid WORD -00 00 (OEM 标识符,相对于 e_oeminfo)1-1-17 e_oeminfo WORD -00 00 (OEM 信息,即 e_oemid 的细节)1-1-18 e_res2 WORD 10 dup -00 00 (保留字,一般都是为确保对齐而预留)1-1-19 e_lfanew DWORD -B0 00 00 00 (* 指向PE文件头的偏移量。0xB0=64+112)1-2 DOS Stub全部填00h2 PE文件头2-1 PE002-1-1 Signature DWORD -50450000h (* PE文件头标记)2-2 IMAGE_FILE_HEADER2-2-1 Machine WORD -4C 01 (* 可执行文件的目标CPU类型)2-2-2 NumberOfSections WORD -03 00 (* 区块数目)2-2-3 TimeDateStamp DWORD -00 00 00 00 (文件创建的时间与日期)2-2-4 PointerToSymbolTable DWORD -00 00 00 00 (指向符号表,用于调试)2-2-5 NumberOfSymbols DWORD -00 00 00 00 (符号表中的符号个数,用于调试)2-2-6 SizeOfOptionalHeadr WORD -E0 00 (* PE头(IMAGE_OPTIONAL_HEADER32)大小)2-2-7 Characteristics WORD -0F 01 (* 文件属性)2-3 IMAGE_OPTIONAL_HEADER322-3-1 Magic WORD -0B 01 (* 标记字)2-3-2 MajorLinkerVersion BYTE -00 (连接程序主版本号)2-3-3 MinorLinkerVersion BYTE -00 (连接程序次版本号)2-3-4 SizeOfCode DWORD -00 00 00 00 (所有含代码区块的总大小)2-3-5 SizeOfInitializedData DWORD -00 00 00 00 (所有初始化数据区块大总大小)2-3-6 SizeOfUninitializedData DWORD -00 00 00 00 (所有未初始化数据区块大总大小)2-3-7 AddressOfEntryPoint DWORD -00 10 00 00 (* 程序执行入口RAV)2-3-8 BaseOfCode DWORD -00 00 00 00 (代码区块起始RAV)2-3-9 BaseOfData DWORD -00 00 00 00 (数据区块起始RAV)2-3-10 ImageBase DWORD -00 00 40 00 (* 程序默认装入基地址)2-3-11 SectionAlignment DWORD -00 10 00 00 (* 内存中区块对齐值)2-3-12 FileAlignment DWORD -00 02 00 00 (* 文件中区块对齐值)2-3-13 MajorOperatingSystemVersion WORD -00 00 (操作系统主版本号)2-3-14 MinorOperatingSystemVersion WORD -00 00 (操作系统次版本号)2-3-15 MajorImageVersion WORD -00 00 (用户自定义主版本号)2-3-16 MinorImageVersion WORD -00 00 (用户自定义次版本号)2-3-17 MajorSubsystemVersion WORD -04 00 (* 运行所需最低子系统主版本号)2-3-18 MinorSubsystemVersion WORD -00 00 (* 运行所需最低子系统次版本号)2-3-19 Win32VersionValue DWORD -00 00 00 00 (保留值,通常为0)2-3-20 SizeOfImage DWORD -00 40 00 00 (* 映像装入内存后的总尺寸)2-3-21 SizeOfHeaders DWORD -00 40 00 00 (* DOS头 PE头 区块表的总大小)2-3-22 CheckSum DWORD -00 00 00 00 (映像效验和)2-3-23 Subsystem WORD -03 00 (* 文件子系统)2-3-24 DllCharacteristics WORD -00 00 (显示DLL特性的旗标)2-3-25 SizeOfStackReserve DWORD -00 00 00 00 (初始化堆栈总大小)2-3-26 SizeOfStackCommit DWORD -00 00 00 00 (初始化实际提交堆栈大小)2-3-27 SizeOfHeapReserve DWORD -00 00 00 00 (初始化保留堆栈大小)2-3-28 SizeOfHeapCommit DWORD -00 00 00 00 (初始化实际保留堆栈大小)2-3-29 LoaderFlags DWORD -00 00 00 00 (与调试相关,默认值为0)2-3-30 NumberOfRvaAndSizes DWORD -10 00 00 00 (* 数据目录标的项数,默认总为16)2-4 数据目录表2-4-1 Export Table2-4-1-1 VirtualAddress DWORD -00 00 00 00 (数据块的起始RAV)2-4-1-2 Size DWORD -00 00 00 00 (数据块的长度)2-4-2 Import Table2-4-2-1 VirtualAddress DWORD -10 20 00 00 (* 数据块的起始RAV)2-4-2-2 Size DWORD -3C 00 00 00 (* 数据块的长度)2-4-3 Resources Table2-4-3-1 VirtualAddress DWORD -00 00 00 00 (数据块的起始RAV)2-4-3-2 Size DWORD -00 00 00 00 (数据块的长度)2-4-4 Exception Table2-4-4-1 VirtualAddress DWORD -00 00 00 00 (数据块的起始RAV)2-4-4-2 Size DWORD -00 00 00 00 (数据块的长度)2-4-5 Security Table2-4-5-1 VirtualAddress DWORD -00 00 00 00 (数据块的起始RAV)2-4-5-2 Size DWORD -00 00 00 00 (数据块的长度)2-4-6 Base relocation Table2-4-6-1 VirtualAddress DWORD -00 00 00 00 (数据块的起始RAV)2-4-6-2 Size DWORD -00 00 00 00 (数据块的长度)2-4-7 Debug2-4-7-1 VirtualAddress DWORD -00 00 00 00 (数据块的起始RAV)2-4-7-2 Size DWORD -00 00 00 00 (数据块的长度)2-4-8 Copyright2-4-8-1 VirtualAddress DWORD -00 00 00 00 (数据块的起始RAV)2-4-8-2 Size DWORD -00 00 00 00 (数据块的长度)2-4-9 Global ptr2-4-9-1 VirtualAddress DWORD -00 00 00 00 (数据块的起始RAV)2-4-9-2 Size DWORD -00 00 00 00 (数据块的长度)2-4-10 Threda local storage(TLS)2-4-10-1 VirtualAddress DWORD -00 00 00 00 (数据块的起始RAV)2-4-10-2 Size DWORD -00 00 00 00 (数据块的长度)2-4-11 Load configuration2-4-11-1 VirtualAddress DWORD -00 00 00 00 (数据块的起始RAV)2-4-11-2 Size DWO

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论