Peach3 元素详细解析(一)

1. Peach Pits文件

Peach Pits是一些xml 文件,包含Peach执行fuzzing所需的所有信息。当你使用Peach进行fuzzing时,需要创建一个Peach Pits文件,它主要包含以下几项内容:通用配置,数据模型,状态模型,代理和监控以及测试配置。

 容器类元素
     Block:组合容器,把多个元素组合起来便于被引用
     Flags:装载Flag元素的容器,以bit为单位的元素(flag)的集合
     Stream: 除含有streamName和streamAttribute外和Block的形式相同;多用于zip、audio/video文件类的fuzz。
 元数据类元素
     String:字符串
     Number:数字
     Blob:主要用于包含非结构化的数据,如字节数组和原始二进制数据等
     Flag:用于bit单位的元素数据,结合Flags形成标志位的数据建模
     Padding:用0来填充数据以达到对齐或指定长度的效果
 关系类元素
     Size-of Relation:
     Count-of Relation:
     Offset-of Relation: Relative offset & Relative to offset
 功能类元素
     Fixups:其对其他数据做相应功能运算得出一结果值,如计算校验和或哈希值。
     Transformers:对其父元素做相应功能运算得出特定格式的结果,如对数据加解密、压缩和解压缩、特定编码和解码等

2.通用配置

Peach Pits文件的第一部分是通用配置。这里是包含其他peach pits文件的位置,比如外部引用接口、默认属性设置、python模块路径配置和自定义代码导入等。

2.1 Include

Include元素允许把其他pit文件包含到当前pit文件的名称空间中使用。当引用被包含的Pits文件时,用命名空间前缀和冒号的格式来命名。格式:Foo:DataModel/StateModel块,如下所示:

属性:
ns------必须的。名称空间前缀
src-----必须的。源码URL,用“file:”前缀来命名文件名。

2.2 Defaults

Defaults—用来设置Data元素的默认属性,比如字节顺序。(注:目前该元素的详细内容,官网打不开)。

2.3 PythonPath

PythonPath元素是一个顶层元素,它添加一个被python模块搜索的路径,主要作用是延伸Peach和包含自定义代码的位置。

属性:
Path—必须的。要添加的路径。

2.4 Import

Import元素允许在pit文件中导入自定义的python模块来使用。它就像python的关键字import一样。(注意,目前Peach 3不支持from属性)

属性:
Import–必须的。和python的关键字import一样。

3.数据模型

Peach Pit文件包含至少一个DataModel元素,也可以更多。DataModel描述的数据包括类型信息、关系信息(大小、数目、偏移)和其他让模糊器执行智能变异的信息。DataModel能被其他的DataModel重用和引用,允许将复杂的定义分解为可读部分。

3.1 DataModel

DataModel是Peach根元素的子元素之一,它通过添加子元素(比如Number、Blob或者String)的方式定义了数据块的结构。

(1)属性
Name----必须的。当引用模型或者调试时,友好的DataModel名字是非常有用的。
ref--------可选的。引用一个DataModel模板。

(2)子元素:
Block、Choice、Custom、Flag、Flags、Number、Padding、String、XmlAttribute、XmlElement、Relation、Fixup、Transformer、Placement。

(3)例子:
一个Peach文件中可以指定任意多个DataModel元素,但每个DataModel的名字必须唯一。通过DataModel可以将复杂的格式按照逻辑分解为更小的模型,使数据模型更易阅读、调试和重用。

(4)引用(ref属性):
当一个引用(ref属性)被提供时,被引用DataModel元素的内容将被复制,并已次为基础来创建新的DataModel元素。新DataModel的任何子元素将覆盖具有相同名字的基础元素。一般的例子中,自定义的子模块中包含一个名字为Key的字符串,它的值将会覆盖没有值的父字符串“Key”。

当一个DataModel被解析时,自定义DataModel看起来像是两个数据模型的组合。

3.2 Blob

Blob元素是DataModel或Block的一个子元素。Blob元素常常用于代表缺少类型定义或格式的数据。

(1)属性
Name
Value
length-------Blob的大小,单位为字节
ref
valueType—值的表示格式,默认是string也可以是hex
minOccurs—该Blob元素必须发生变化的最小次数,默认为1
maxOccurs–该Blob元素能够发生变化的最大次数,默认为1
Token---------当解析时元素应该作为一个令牌来信任,默认是假。即是解析时的关键字
lengthType–长度的单位默认是byte
constraint----指定满足表达式的值是数据才会变异
Mutable-------Blob元素是否可变异,默认为真
(2)子元素:
anayzers
(3)例子
一个简单的Blob。这个Blob中,任何类型或长度的数据都会破解(carck into)到这个blob中

<Blob name="Unknown1" />

一个有默认值的blob

<Blob name="Unknown1" valueType="hex" value="AA BB CC DD" />

3.3 Block

Block元素是DataModel或Block的子元素。Blocks用于将一个或多个数据元素(例如Number或String)组合到一个逻辑结构中。 Block和DataModel非常相似,唯一的区别是它们的位置。 DataModel是顶级元素,Blocks是DataModel的子元素。 Block和DataModel元素都可以用作其他Blocks或DataModel的“模板”。

<Block name="HelloWorld">
  <String value="Hello world!" />
</Block>

(1)属性(除非声明,所有的属性都是可选的):

Name—Block的名字。

Ref—引用一个数据模型来作为Block的模板。。

minOccurs—该Block必须发生变化的最小次数。

maxOccurs–该Block可以发生变化的最大次数。

Mutable—元素是否可变异,默认为真。

(2)子元素:
Blob、block、Choice、Custom、Fixup、Flag、Flags、Number、Padding、Placement、Relation、Seek、String、Transformer、XmlAttribute、XmlElement。

(3)例子
空block
最简单的block定义是一个空block。这种定义将不会产生输出。

<DataModel name="BlockExample1">
 <Block>
 </Block>
</DataModel>

嵌套Block
Block可以根据需要嵌套。 Block有助于创建逻辑结构,并且不会更改其中包含的数据。

<DataModel name="BlockExample2">
<Block>
  <Block>
    <Block>
      <String value="1" />
    </Block>

    <Block>
      <String value="2" />
    </Block>

    <String value="3" />
  </Block>
  <String value="4" />
</Block>
</DataModel>

这种嵌入式定义下的Block将会产生如下输出:

1234

Naming A Block
给Block一个友好的命名可使它们更容易理解和调试。

<DataModel name="BlockExample2">
 <Block name="HeaderDef">
  <String name="Header" />
  <String name="Colon" value=":"/>
  <String name="Val"/>
 <Block>

 <Block name="DataDef">
   <Number name="Type"  size="8" value="4"/>
   <Number name="Data" size="8" value="32"/>
 </Block>
 </DataModel>

Referencing A Block
使用reference元素(ref属性)会把被引用的DataModel或者Block的内容复制过来以作为构建新Block的基础。新Block中的任何子元素将覆盖已存在的具有相同名称的元素。

<DataModel name="OtherDataModel">
   <String value="Hello World"/>
 </DataModel>

 <DataModel name="ThisDataModel">
    <Block name="MyName" ref="OtherDataModel"/>
 </DataModel>

Block “MyName” 将被引用块“OtherDataModel”覆盖。 在解析它时,数据结构看起来像这样。

<DataModel name="ThisDataModel">
   <Block name="MyName">
    <String value="Hello World"/>
   </Block>
 </DataModel>

Reference允许构建功能强大的模板。 这是一个Key:Value \ r \ n的模板。

<DataModel name="Template">
  <String name="Key" />
  <String value=": " token="true" />
  <String name="Value" />
  <String value="\r\n" token="true" />
</DataModel>

引用此模板:

<DataModel name="OtherModel">
  <String value="Before Block\r\n" />

  <Block name="Customized" ref="Template">
    <String name="Key" value="Content-Length" />
    <String name="Value" value="55"/>
  </Block>
</DataModel>

输出为:

Before Block\r\n
Content-Length: 55\r\n

这里发生了两件重要事情。 在分析时,”Customized Block”将用”Template”的DataModel替换它的结构。 添加“:”和“\ r \ n”的字符串值。

同时,“Customized”Block重写了Key和Value的String元素的值。 将它们替换为“Content-Length”和55.最终的DataModel将被解析为如此。

<DataModel name="OtherModel">
  <String value="BeforeBlock" />

  <Block name="Customized" ref="Template">
    <String name="Key" value="Content-Length" />
    <String value=": " token="true" />
    <String name="Value" value="55" />
    <String value="\r\n" token="true" />
  </Block>
</DataModel>

3.4 choice

Choice元素是DataModel或Block的子元素。 Choice元素用于指示任何子元素都是有效的,但只能选择一个。 很像编程语言中的switch语句。

<Choice name="ChoiceBlock">
  <Block name="Type1">
    <!-- ... -->
  </Block>
  <Block name="Type2">
    <!-- ... -->
  </Block>
  <Block name="Type3">
    <!-- ... -->
  </Block>
</Choice>

(1)属性(除非声明,所有的属性都是可选的):

Name—choice元素的名字。

minOccurs—该Choice必须发生改变的最小次数。

maxOccurs—该Choice能发生改变的最大次数。

Occurs—该choice能发生改变的迭代次数。

(2)子元素:

Block、Choice、String、Number、Blob、Flags、Fixup、Transformer、XmlAttribute、XmlElement。

(3)例子:
一个基本的Choice Block。 该Choice示例将破解或使用类型为1,2,3的数据。 就像常规的switch语句一样,需要在标记上做出决定。
如果前8位值为1,则剩余数据被视为一个32位的数。 如果前8位值为2,则剩余数据被视为一串长度为255个字节的二进制数据。 如果前8位值为3,则剩余数据被视为一个8字节的字符串。
当进行模糊化测试时Peach会选择三种类型之一,将其模糊为8位数字输出,并且接着输出相应的类型。 Peach将尝试全部三种类型。

<DataModel name="ChoiceExample1">
 <Choice name="Choice1">

  <Block name="Type1">
    <Number name="Str1" size="8" value="1" token="true" />
    <Number size="32"/>
  </Block>

  <Block name="Type2">
    <Number name="Str2" size="8" value="2" token="true" />
    <Blob length="255" />
  </Block>

  <Block name="Type3">
    <Number name="Str3" size="8" value="3" token="true" />
    <String length="8" />
  </Block>
 </Choice>
</DataModel>

An array of Choices
第一个例子适合做出单一选择,但如果有很多Type1 Type2和Type3块都相互连接,会怎么样呢? 设置minOccurs,maxOccurs或occurs以指定Choice应该被重复。

<DataModel name="ChoiceExample1">
 <Choice name="Choice1" minOccurs="3" maxOccurs="6">

  <Block name="Type1">
    <Number name="Str1" size="8" value="1" token="true" />
    <Number size="32"/>
  </Block>

  <Block name="Type2">
    <Number name="Str2" size="8" value="2" token="true" />
    <Blob length="255" />
  </Block>

  <Block name="Type3">
    <Number name="Str3" size="8" value="3" token="true" />
    <String length="8" />
  </Block>
 </Choice>
</DataModel>

3.5 Flag

Flag元素在Flags容器中定义了一个特定的位区域。

(1)属性:

Name—可选的。元素的名字。

Size—必须的。大小,以位为单位为

Position—必须的。Flag的开始位置(以0位基础)。

Value—带有Blob的默认值。

valueType—格式的默认值(hex,string,literal)。

Mutable—可选的。数据元素是否变异,默认为真(peach 2.3)。

(2)子元素:

Relation。

3.6 Flags

Flags定义了一组Flag的大小。
在这里插入图片描述
(1)属性:

Name—可选的。元素的名字。

Size—必须的。大小,以位为单位。

Mutable—可选的。元素是否可以变异,默认为真。

(2)子元素:

Fixup、Flag、Placement、Relation、Transformer。

3.7 Number

该元素定义了长度为8,16,24,32,或64位长度的二进制数。它是DataModel、Block或者Choice的子元素。

(1)属性:

Name—必须的。Number的名字。

Size—必须的。Number的大小,以位为单位。有效值为1到64。

Value—分配给Number的默认值。

valueType—可选的。value的表现方式。有效选项为string(字符串)和hex(十进制)。

Token—当解析的时候,该元素被视为一个令牌,默认值为假。有效选项为真和假。

Endian—Number的字节顺序。默认为小端。有效选项为大端、小端和网络。网络一样是大端。

Signed—Number是否为有符号数据。默认为真。有效选项为真和假。

Constraint—一个以Python表达式为形式的约束。用于数据破解。

Mutable—元素是否可改变(fuzzing时是否可变异),默认为真。有效选项为真和假。

minOccurs—Number必须发生改变的最小次数,默认为1。有效选项为正整数值。

maxOcuurs—Number能够发生改变的最大次数,没有默认值。有效选项为正整数值。

(2)有效子元素:

Anayzers、Fixup、Relation、Transformer、Hint。

(3)例子

一个简单的例子,它将产生一个32位(4字节)Number,默认值为5

在这里插入图片描述
为了只使用16位(2字节),改变size的值为16

在这里插入图片描述
有符号。为了表明这是一个无符号数据元素,设置signed属性等于“false”。默认为真。

在这里插入图片描述
ValueType。值类型定义了怎么解释Value的属性。有效选项为string和hex,默认为string。
将值1000分配给Hi5。

在这里插入图片描述
将43981以十六进制形式分配给Hi5。

在这里插入图片描述
大端。为了改变Number 的字节顺序,请设置endian属性。如下输出的字节顺序为:AB CD

在这里插入图片描述
小端,如下输出的字节顺序为:CD AB

在这里插入图片描述

3.8 Padding

padding元素用来填充大小变化的块或数据模型。

(1)属性:

Name—必须的。Number 元素的名字。
Aligned—将父元素对齐到 8 字节边界,默认为假。
Alignment—对齐到这个位边界,比如(8、16 等),默认为 8。
alignedTo—基于我们要填充的元素名字。 Lengthcalc—计算结果为整数的脚本表达式。
Constraint—一个以 Python 表达式形式的约束。用于数据破解。指定满足表达式的值是数据才会变异 。
Mutable—元素是否可变异,默认为真,有效选项为真和假。

(2)有效子元素:

Fixup、Relation、Transformer、Hint。

(3)例子:

在这里插入图片描述

3.9 String

该元素定义了一个单字节或者双字节的字符串,它是DataModel或者Block的子元素。如果为了指定这是一个数值的字符串,请用 NumericalString 元素。

<String value="Hello World!"/>
<String value="Null terminated string" nullTerminated="true"/>

(1)属性

Name—可选的,数据模型的名字。
Length—可选的,字符串的长度。
lengthType—可选的,Length 属性的单位。
Type—可选的。字符编码类型,默认为“ASCII”,有效选项为 ASCII、utf7、utf8、utf6、 utf6be、utf32。
nullTerminated—可选的。是否为以空字节结尾的字符串(真或者假)。
padCharacter—可选的。根据 length 参数填充字符串的字符,默认为(0x00)。
Token—可选的。当解析的时候,该元素应该被视为一个令牌,默认为假。
Constraint—一个脚本表达式形式的约束。用于数据破解。
Mutable—可选的。元素是否可变异,默认为真。
Minoccurs—可选的。这个块必须发生改变的最小次数,默认为 1。
Maxoccurs—可选的。这个块会发生改变的最大次数,默认为 1。

(2)有效子元素

Analyzer、Fixup、Relation、Transformer、Hint。

(3)NumericalString:

该元素只能用于String来说明它的值是一个数字。当使用这个提示时,它激活所有的数字突变以及标准的字符串突变。请注意:如果默认情况下一个字符串的值是数字,NumericalString元素会被自动添加。

在这里插入图片描述

3.10 XMLAttribute

该元素定义了XML元素的属性。只有当父元素是XmlElement时,才有效。

在这里插入图片描述
(1)属性

Name—可选的。数据模型的名字。 Minoccurs—可选的。这个块必须发生变化的最小次数。 Maxoccurs—可选的。这个块会发生变化的最大次数。 isStatic—可选的。当解析的时候,该元素被视为一个令牌,默认为假。 Token—可选的。当解析的时候,该元素被视为一个令牌,默认为假(Peach 2.3)。 Mutable—可选的。该元素是否可变异,默认为真(Peach 2.3)。 attributeName—必须的。XML 元素的名字。 Ns—可选的。XML 名称空间。

(2)有效子元素

Block、Choice、String、Number、Blob、Flags、Fixup、Hint。

3.11 XmlElement

定义一个XML元素,XML文档的基本块构建。这用来fuzzing一个XML文档的内容,但是不包含xml解析器。XmlElement 和 XmlAttribute 产生的所有输出都将被格式化。请注意, XmlElement 和 XmlAttribute 元素不支持数据破解。如果需要破解 Xmlelement 和 XmlAttribute 中的 XML,请用挂载到一个 String 元素的 XmlAnalyzer。

在这里插入图片描述
(1)属性

Name—可选的。数据模型的名字。 Minoccurs—可选的。这个块必须发生变化的最小次数。 Maxoccurs—可选的。这个块会发生变化的最大次数。 isStatic—可选的。当解析的时候,该元素被视为一个令牌,默认为假。 Token—可选的。当解析的时候,该元素被视为一个令牌,默认为假(Peach 2.3)。 Mutable—可选的。该元素是否可变异,默认为真(Peach 2.3)。 attributeName—必须的。XML 元素的名字。 Ns—可选的。XML 名称空间。

(2)有效子元素

XmlElement、XmlAttribute、Block、Choice、String、Number、Blob、Flags、Fixup、Hint

3.12 Hint

Hint是变异器的扩展。它能附加到数据元素上,为Peach引擎提供更多关于被解析数据的信息。例如,当字符串包含一个数字时,只有包含在字符串mutator中的数字测试才会执行。如果你添加一个 NumericalString 提示到 String,它将附加所有的数字变异器。

在这里插入图片描述
可用的 Hints:
NumericalString、ArrayVarianceMutator-N、DWORDSliderMutator、BitFlipperMutator-N、
NumericalVarianceMutator-N 、 Telecommunications-N 、 FiniteRandomNumbersMutator-N 、 SizedVaranceMutator-N、SizedNumericalEdgeCasesMutator-N、SizedDataVaranceMutator-N、 SizedDataNumericalEdgeCasesMutator-N、type、ValidValues。

3.13 Relation

Peach 允许构建数据间的关系。关系是类似这样的东西“X 是 Y 的大小”、“X 是 Y 的 数量”、或者“X 是 y 的偏移(字节单位)”。

(1)大小关系:
在这个例子中,Number 元素的值将确定名字为 TheValue 的 string 元素的大小。请注意, 这也适用于多字节字符,如 wchar。在 Peach 未来的版本中,这将会改变,或者将包括新的 类型长度关系,以便更好地支持 UTF-8 和其他 Unicode 编码。

在这里插入图片描述
在如下例子中,我们将提供两个 python 表达式,它允许在获取或设置 size 属性的时候 修改它的大小,有两个变量可用,分别为 self 和 size。Self 是 Number 元素的一个引用,size 是一个整数。获取操作和设置操作应该是彼此的数学逆操作。在破解过程中应用获取操作, 在发布过程中应用设置操作。
expressionGet—该表达式的结果用于内部,它确定名字为 TheValue 的 String 元素读取多 少字节。如果 Peach 取 10,它将在内部存储一个 5,然后 Peach 将读取 5 个字节到 String 中。
ExpressionSet—为 publisher 生成一个值。 在以下示例中,为 TheValue 存储的 Size 的值 “5”(TheValue 的长度),因此 Peach 通过 publisher 输出的值将为“5 * 2”或 10。

在这里插入图片描述
(2)数量关系:
在这个例子中,Number 将会说明 String 列表的数目。

在这里插入图片描述
在这个例子中,我们将提供两个 python 表达式,它允许在获取或设置 size 属性的时候 修改它的大小。有两个变量可用,分别为 self 和 count。Self 是 Number 元素的一个引用,count 是一个整数。这里的让 count 可用与前面的表达式不同。虽然 self 在表达式对中始终可用, 但其他可用的变量的名字是 Relation 元素 type 属性的值。
expressionGet—该表达式的结果用于内部,它确定 String 元素将扩展到多少项。 maxOccurs 是 Peach 循环计算中遇到的最大值,由于 maxOccurs = 1024 的限制,Peach 在 CountIndicator 元素中破解时遇到的最大值是 2048。
ExpressionSet—设置要生成的值。 以下示例中,count 根据读入的 String 元素数目确定。

在这里插入图片描述

(3)偏移关系:
偏移关系是 Peach 最新增加的,它允许需修改格式,这些格式需要偏移的改变和输出变 量元素的偏移。这里有一些元素,它们是各种 String 元素偏移量的 ascii 表示。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
1、相对偏移量: 从 Peach 2.3 开始支持相对偏移的概念。 相对偏移来自附加到 relation 的数据元素。 请 考虑以下示例。当确定 StringData 的偏移量时,Peach 将根据需要,对 OffsetToString 的位 置进行加上/减去它的值,以确定正确的偏移量。

在这里插入图片描述
2、相对于偏移量: Peach 还支持相对于另一个元素的偏移。它用于以下情况,一个元素包含另外一个元素 的偏移,而被包含的偏移的元素是一个结构体的开头。 以下示例中,StringData 偏移量将通 过添加 OffsetToString 的值到 Structure 位置的方式来计算。

在这里插入图片描述
包含 expressionGet / expressionSet 当使用带有偏移关系的 expressionGet / Set 时,将提供两个变量:self 和 offset。 Self 引用了一个父元素的引用,offset 是一个整数。 包含 Placement 的偏移关系 这个模型中,将使用一个典型的模式。在这个模式中,一个偏移列表会给我们另一个元 素的位置。 使用 Placement 元素将创建的 Data 字符串移动到 Chunks 块之后。

在这里插入图片描述

3.14 Fixup

Fixup是一些代码函数,它通常操作另一个元素数据来产生一个值。校验和算法就是这样一个示例。Peach默认包含有以下fixups。
⚫Utility Fixups
  ◆ CopyValueFixup ◆ SequenceIncrementFixup ◆ SequenceRandomFixup
⚫ Check-sum Fixups
  ◆ Crc32DualFixup ◆ Crc32Fixup ◆ EthernetChecksumFixup ◆ ExpressionFixup ◆ IcmpChecksumFixup ◆ LRCFixup
⚫ Hashing Fixups
  ◆ MD5Fixup ◆ SHA1Fixup ◆ SHA224Fixup ◆ SHA256Fixup ◆ SHA384Fixup ◆ SHA512Fixup

3.15 Transformers

Transformers 在父元素上执行静态转换或编码。通常来说 Transformers 是两个方向:编 码和解码,但也不全是。 比如 ZIP 压缩,Base64 编码,HTML 编码等。与 Fixups 不同, Transformers 对父元素操作,而 Fixups 引用另一个元素的数据。

在这里插入图片描述
上述数据模型的输出为 0x01 <len(b64(Data))> <b64(Data)>
Peach3 中的默认Transformers:

⚫ Compression (压缩)
◆ Bz2CompressTransformer
◆ Bz2DecompressTransformer
◆ GzipCompressTransformer
◆ GzipDecompressTransformer

⚫ Crypto (加密)
◆ Aes128Transformer ◆ ApacheMd5CryptTransformer ◆ CryptTransformer ◆ CvsScrambleTransformer ◆ HMACTransformer ◆ MD5Transformer ◆ SHA1Transformer ◆ TripleDesTransformer ◆ UnixMd5CryptToolTransformer ◆ UnixMd5CryptTransformer

⚫ Encode (编码)
◆ Base64EncodeTransformer ◆ Base64DecodeTransformer ◆ HexTransformer ◆ HexStringTransformer ◆ HtmlEncodeTransformer ◆ HtmlDecodeTransformer ◆ HtmlEncodeAgressiveTransformer ◆ Ipv4StringToOctetTransformer ◆ Ipv4StringToNetworkOctetTransformer ◆ Ipv6StringToOctetTransformer ◆ JsEncodeTransformer ◆ NetBiosEncodeTransformer ◆ NetBiosDecodeTransformer ◆ SidStringToBytesTransformer ◆ UrlEncodeTransformer ◆ UrlEncodePlusTransformer ◆ Utf8Transformer ◆ Utf16Transformer ◆ Utf16LeTransformer ◆ Utf16BeTransformer ◆ WideCharTransformer

⚫ Type (类型转换)
◆ AsInt8Transformer ◆ AsInt16Transformer ◆ AsInt24Transformer ◆ AsInt32Transformer ◆ AsInt64Transformer ◆ IntToHexTransformer ◆ NumberToStringTransformer ◆ StringToFloatTransformer ◆ StringToIntTransformer

⚫ Misc (混杂)
◆ EvalTransformer

3.16 Placement

Placement元素告诉数据破解者,在输入流被解析之后,特定元素应该被移动。结合偏移关系是Peach支持的文件处理方式,它通过偏移来包含元素的引用。

在这里插入图片描述
属性:
以下其中之一是必须的:
After—元素移动到之后。
Before—元素移动到之前。

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值