首页
社区
课程
招聘
[原创]文件Fuzz教程之二:Peach语法实战
2013-7-31 16:45 8708

[原创]文件Fuzz教程之二:Peach语法实战

2013-7-31 16:45
8708
RT
文件Fuzz教程第二篇

文件 Fuzz 教程之二:Peach 语法实战
Author:dragonltx

经过教程一的介绍,大家已经对 Peach 语法有了大致的了解,本篇文章将用那些语法进行实战。

实例一
typedef union {
    uint32  ctype <format=hex>; // Chunk Type
    char     cname[4];                  // character representation
} CTYPE ;


typedef struct {
    uint32  length;  // Number of data bytes (not including length,type, or crc)
    CTYPE  type;  // Type of chunk
    ubyte  data[length];  // Data (or not present)
    uint32  crc <format=hex>;  // CRC type and data (not including length or crc)
} CHUNK ;


上述结构的数据模型如下:
<Block name = "Chunk" minOccurs = "1" maxOccurs = "1024">
    <Number name = "Length" size = "32" endian="big" signed = "false">
        <Relation type = "size" of = "Data" />
    </Number>
    <Block name = "TypeAndData">
         <Blob name = "Type" length = "4" mutable="false"/>
        <Blob name = "cname" length="4"/>
    </Block>
    <Blob name = "Data" />
    <Number name = "CRC" size = "32">
        <Fixup class = "checksums.Crc32Fixup">
            <Param name = "ref" value = "TypeAndData" />
        </Fixup>
    </Number>
</Block>


详解
CHUNK:该结构可以用 Block 来表示,Block 包含 3 个属性,name 的值是“Chunk”,minOccurs 的值为“1”,表示至少出现 1 次,maxOccurs 的值为“1024”,表示最多出现1024 次。

length:该值可以用 Number 来表示,Number 包含 3 个属性,size 的值是“32”,表示是 uint32 类型,endian 的值是“big”,表示大端序,signed 的值是“false”,表示无符号。

type:该结构也用 Block 来表示,其中 ctype 用 Blob 类型,大小是 4 字节,不可变异。Cname 也是用 Blob 类型,大小是 4 字节。

data:这边 data 用 Blob 类型,data 的大小在“Length”中指定,通过 size 这个 Relation
来指定,<Relation type="size" of="Data"/>,即 data 的大小是 Length 字节。

crc:crc 的值通过 Fixup 这个类来计算

总结:这个例子主要展示了 Block、Number、Relation、Fixup 的用法。

实例二
typedef struct
{
    char id[4];
    uint32 datalen;
    if (datalen % 2)
        char data[datalen+1];
    else
        char data[datalen];
} strfHEADER;


上述结构的数据模型如下:
<DataModel name="StrfHeader">
    <Blob name="StreamFormatFourCC" value="strf" length="4" token="true" mutable="false"/>
    <Number name="cbFileSize" size="32" endian="little" signed="false"/>
    <Block name = "IsOdd" minOccurs="0" maxOccurs="1">
        <Relation type="when" when="(int(self.find('cbFileSize').getInternalValue())%2) == 1"/>
        <Blob lengthType="calc" length="int(self.find('cbFileSize').getInternalValue())+1" />
    </Block>
    <Block name = "IsEven" minOccurs="0" maxOccurs="1">
        <Relation type="when" when="(int(self.find('cbFileSize').getInternalValue())%2) == 0"/>
        <Blob lengthType="calc" length="int(self.find('cbFileSize').getInternalValue())" />
    </Block>
</DataModel>


详解
id:用 Blob 来表示,value 的值为“strf”,长度为 4,token 的值为“true”,用来作为这个数据模型的特征。

datalen:用 Number 表示,大小为 32 位,即 uint32,小端,无符号。

datalen 为奇数时:用 Block 来表示这个块,minOccurs 为 0 表示可能不出现,maxOccurs
为 1 表示最多出现一次。用到了 when 这个 Relation,这个 Block 成立的条件是
when="(int(self.find('cbFileSize').getInternalValue())%2) == 1"。data 用 Blob 表示, lengthType 的值为“calc”,表示 Blob 的大小要通过计算得到,length 的值为“int(self.find('cbFileSize').getInternalValue())+1”,表示 Blob 的大小是这样计算得来。

dalalen 为偶数时:情况与奇数时类似。

总结:这个例子主要展示了 when 这个 Relation 和 Blob 的用法。

实例三
while ( !FEof())
{
    ReadBytes( tag, FTell(), 4 );
        tag[4] = 0;
    count++;
    if ( header.object_version==0)
        if ( count >header.num_headers)
    break;
    switch ( tag)
    {
        case "DATA":
    DATA_CHUNKS data_chunk;
    break;
        case "PROP":
    PROP_CHUNK prop_chunk;
    break;
        case "MDPR":
    MDPR_CHUNK mdpr_chunk;
    break;
        case "CONT":
    CONT_CHUNK cont_chunk;
    break;
        case "INDX":
    INDX_CHUNKS indx_chunk;
    break;
        default:
    DEFAULT_CHUNK d_chunk;
    break;
    }
}


上述结构的数据模型如下:
<DataModel name = "Rm">
    <Block ref="RmHeader"/>
    <Choice maxOccurs="100">
        <Block ref="data_chunks"/>
        <Block ref="mdpr_chunk"/>
        <Block ref="indx_chunks"/>
        <Block ref="prop_chunk"/>
        <Block ref="cont_chunk"/>
        <Block ref="default_chunk"/>
    </Choice>
</DataModel>


详解
用 Choice 来表示 switch,Choice 的属性为 maxOccurs,值为“100”,表示最多出现 100次,每一个的选择都会从“data_chunks”“mdpr_chunk”“indx_chunks”“prop_chunk”“cont_chunk”“default_chunk”选择一个 Block,具体是选择哪一个,根据每个 Block的标志进行选择。

总结:这个例子主要展示了 Choice 的用法。

实例四
struct IMAGEDESCRIPTOR_PACKEDFIELDS {
    UBYTE LocalColorTableFlag : 1;
    UBYTE InterlaceFlag : 1;
    UBYTE SortFlag : 1;
    UBYTE Reserved : 2;
    UBYTE SizeOfLocalColorTable : 3;
} PackedFields;


上述结构的数据模型如下:
<Flags name="PackedFields" size="8">
    <Flag name="LocalColorTableFlag" position="7" size="1"/>
    <Flag name="InterlaceFlag" position="6" size="1"/>
    <Flag name="SortFlag" position="5" size="1"/>
    <Flag name="Reserved" position="3" size="2"/>
    <Flag name="SizeOfLocalColorTable" position="0" size="3"/>
</Flags>


详解
PackedFields:用 Flags 表示,name 的值为“PackedFields”,size 的值为“8”,表示大小为 8 位,即 1 字节。

LocalColorTableFlag:用 Flag 表示,name 的值为“LocalColorTableFlag”,position 的值为 7,即第 7 位,size 的值为“1”,表示大小为 1 位。其他 Flag 类似。

总结:这个例子展示了 Flags/Flag 的用法。

实例五
typedef struct
{
    uint32 nDataSize;
    char strDataType[4];
    char strVersion;
    char flags[3];
    char data[nDataSize-12]; 
} DATA_REFERENCE;


typedef struct
{
    uint32 nBoxlen; 
    char strType[4];
    char strVersion;
    char flags[3]; 
    uint32 entrycount;
    DATA_REFERENCE dr[entrycount];
} DREF;


上述结构的数据模型如下:
<DataModel name="dref">
    <Number name="nBoxlen" size="32" endian="big" signed="false"/>
    <Blob name="strType" length="4" valueType="hex" value="64726566" token="true" mutable="false"/>
    <Blob name="strVersion" length="1"/>
    <Blob name="strFlags" length="3"/>
    <Number name="entrycount" size="32" endian="big" signed="false">
        <Relation type="count" of="data_reference"/>
    </Number>
    <Block name="data_reference" maxOccurs="1024">
        <Number name="nBoxlen" size="32" endian="big" signed="false">
            <Relation type="size" of="data" expressionGet="size-12" expressionSet="size+12"/>
        </Number>
        <Blob name="strType" length="4" mutable="false"/>
        <Blob name="strVersion" length="1"/>
        <Blob name="strFlags" length="3"/>
        <Blob name="data"/>
    </Block>
</DataModel> 


详解
dr:dr 用 Block 来表示,name 的值为“data_reference”,maxOccurs 的值为“1024”,必须设定 maxOccurs 的值,否则在进行数据解析时,dr 的个数会被设置为 1。dr 的个数通过 entrycount 来指定,通过 count 这个 Relation 来联系起来,即<Relation type="count"of="data_reference"/>。

DATA_REFERENCE 中 的 data : 由 于 data 的 大 小 为 nDataSize-12 , 必 须 用 到expressionGet/expressionSet。通过这样设定 data 的大小,<Relation type="size" of="data"expressionGet="size-12" expressionSet="size+12"/>。

总结:这个例子展示了 count、size 这两个 Relation 的用法,以及expressionGet/expressionSet的用法。

实例六
switch (PacketLenType)
{
    case 0:
        break;
    case 1:
        BYTE PacketLen;
        localPacketLen = PacketLen;
        break;
    case 2:
        WORD PacketLen;
        localPacketLen = PacketLen;
        break;
    case 3:
        DWORD PacketLen;
        localPacketLen = PacketLen;
        break;
}

上述结构的数据模型如下:
<Choice name="PacketLengthTypeChooser">
    <Block name="PacketLengthNONE">
        <Blob name="PacketLength" length="0" constraint="self.find('LengthTypeFlags.PacketLengthType').getInternalValue() == 0">
        </Blob>
    </Block>
    <Block name="PacketLengthBYTE">
        <Number size="8" name="PacketLengthType" constraint="self.find('LengthTypeFlags.PacketLengthType').getInternalValue() == 1"/>
    </Block>
    <Block name="PacketLengthWORD">
        <Number size="16" name="PacketLengthType" constraint="self.find('LengthTypeFlags.PacketLengthType').getInternalValue() == 2"/>
    </Block>
    <Block name="PacketLengthDWORD">
         <Number size="32" name="PacketLengthType" constraint="self.find('LengthTypeFlags.PacketLengthType').getInternalValue() == 3"/>
    </Block>
</Choice>


详解
constraint:通过 constraint 这个约束条件来完成 switch 的功能。当LengthTypeFlags.PacketLengthType 的值为 0 时,Blob 的大小为 0,当LengthTypeFlags.PacketLengthType 的值为 1 时,Blob 的大小为 8,即 BYTE,依此类推。

总结:这个例子展示了 constraint 的用法。

注:本帖由看雪论坛志愿者PEstone 重新将PDF整理排版,若和原文有出入,以原作者附件为准

[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

上传的附件:
收藏
点赞3
打赏
分享
最新回复 (3)
雪    币: 85452
活跃值: (198780)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
linhanshi 2013-8-1 13:14
2
0
+1
雪    币: 86
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
Membered 2013-8-1 17:07
3
0
<Block name = "Chunk" minOccurs = "1" maxOccurs = "1024">
<Number name = "Length" size = "32" endian="big" signed = "false">
<Relation type = "size" of = "Data" />
</Number>
<Block name = "TypeAndData">    ----->有问题吧,<Blob name = "Data" /> 应该在这个块里面!估计lz马虎了一下下.....
<Blob name = "Type" length = "4" mutable="false"/>
<Blob name = "cname" length="4"/>
</Block>
<Blob name = "Data" />
<Number name = "CRC" size = "32">
<Fixup class = "checksums.Crc32Fixup">
<Param name = "ref" value = "TypeAndData" />
</Fixup>
</Number>
</Block>
雪    币: 4083
活跃值: (3753)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
昵称好麻烦 2020-8-11 15:47
4
0
实例一确定是这么写的吗?TypeAndData里的内容是union类型,总共大小是4字节,文中成了struct类型,总共大小变8字节
游客
登录 | 注册 方可回帖
返回