CVE-2018-5996 7zip学习笔记

2018-04-21  本文已影响0人  413x

CVE-2018-5996 7zip学习笔记

前置知识

Range encoding

顾名思义,就是把一个字符串流根据字符出现的频率,转化成一个范围(阈值)

https://en.wikipedia.org/wiki/Range_encoding

简介

原文
https://landave.io/2018/01/7-zip-multiple-memory-corruptions-via-rar-and-zip/#fn:2

可触发堆溢出和栈溢出

PPMd是压缩算法RAR3压缩算法的实现

bug

对于每个RAR版本,最多创建一个coder。如果同一个版本有多个实例,就使用同一个coder。
调用code可能返回失败S_FALSE,而且被创建的coder下次仍然会使用。我们找到一个能让它返回
S_FALSE的函数。

CInBufferException,当从输入流中读入时,这个异常可能会被抛出,我们可以用一个RAR3实例
来触发这个异常,抛出S_FALSE

一旦RAR3在PPMd更新时抛出异常,会让PPMd模型处于不稳定状态,同样的coder会被用作下个实例,
即使在CInBufferException已经抛出S_FALSE的异常码

RAR3解码器维持PPMd模型的状态,PPMd模型只有在一个item显示要求时才会重新初始化,
这意味着我们可以这样做:

PPMd Preliminaries

PPMd压缩算法是建立有限阶D的马尔科夫模型,模型状态实质是一个256元的上下文树,最大深度为D。
从根到上下文节点的路径将被解释为字节符号序列,父关系将被理解为后缀关系。除此之外,每一个
上下文结点保存与后继节点相关的后继符号的统计频率。

使用以下名为CPpmd7_Context的结构体来表示一个上下文结点

typedef struct CPpmd7_Context_ {
  UInt16 NumStats;              //Stats array中元素个数
  UInt16 SummFreq;
  CPpmd_State_Ref Stats;
  CPpmd7_Context_Ref Suffix;
} CPpmd7_Context;
typedef struct {
  Byte Symbol;
  Byte Freq;
  UInt16 SuccessorLow;
  UInt16 SuccessorHigh;
} CPpmd_State;
  1. 第一个RAR3实例创建的同时,一些上下文节点也同时被创建,Ppmd7_DecodeSymbol将p->MinContext
    向上移动一次,知道找到相应的符号为止。解码器方法会因为CInBufferException失败。
  2. 由于下一个RAR3实例并没有重置位,我们会继续使用之前创建的PPMd模型。
  3. Ppmd7_DecodeSymbol使用一个新的范围解码器,并且p->MinContext!=p->maxContext
    它在p->MinContext中寻找对应的符号,但这个符号事实上已经在p->MaxContext和p->MinContext之间
    的上下文,当UpdateModel函数被调用,这个符号就会被重复添加到State数组

栈溢出和堆溢出

state指针数组固定大小且存放在栈中,并且在向其中添加新state指针时不会检查长度,故能构建栈溢出
state内容存放在堆中,溢出原理和上述相同

上一篇下一篇

猜你喜欢

热点阅读