首页
论坛
课程
招聘
[原创] #30天写作挑战#CVE-2020-0729:Windows LNK远程代码执行漏洞分析(一)
2020-9-15 14:57 1326

[原创] #30天写作挑战#CVE-2020-0729:Windows LNK远程代码执行漏洞分析(一)

2020-9-15 14:57
1326

备注说明:该漏洞分析内容实在有点多,打算分开发,本次没有附带动态调试。后续会把详细的动态调试部分拿上来,大家先消化下背景知识和静态流程。

一、漏洞信息

1. 漏洞简述

  • 漏洞名称:Microsoft Windows LNK Remote Code Execution Vulnerability
  • 漏洞编号:CVE-2020-0729
  • 漏洞类型:Memory Corruption
  • CWE-098:Use of Uninitialized Resource
  • 漏洞影响:Code Execution
  • CVSS评分:7.5
  • 利用难度:Medium
  • 基础用户:需要

2. 组件概述

Windows与其他OS一样,支持link的使用,link主要用于存储一个位置(或路径)的调用。在UNIX系统中,称为符号链接。在Windows中,这些二进制对象被定义为"shell link",文件名后缀为".LNK"。这是Shell Link Binary File Format的规范,是一种数据对象,其中包含可用于访问另一个数据对象的信息。

 

Shell link通常用于支持应用程序启动和链接方案,例如对象链接和嵌入(OLE),但也可以由需要存储对目标文件的引用的功能的应用程序使用。

3. 漏洞利用

该漏洞主要是由于对LNK文件的错误解析造成,远程攻击者可以诱惑目标用户浏览包含特制LNK文件的文件夹或者下载一个LNK文件。成功的利用可以实现在当前用户的安全上下文中进行任意代码执行。

4. 漏洞影响

• Microsoft Windows 7 SP1<br>
• Microsoft Windows 8.1<br>
• Microsoft Windows 10(1607-1909)<br>
• Microsoft Windows RT 8.1<br>
• Microsoft Windows Server 2008 SP2<br>
• Microsoft Windows Server 2008 R2 SP1<br>
• Microsoft Windows Server 2012<br>
• Microsoft Windows Server 2012 R2<br>
• Microsoft Windows Server 2016<br>
• Microsoft Windows Server 2019<br>
• Microsoft Windows Server version 1803 (Server Core Installation)<br>
• Microsoft Windows Server version 1903 (Server Core Installation)<br>• Microsoft Windows Server version 1909 (Server Core Installation)<br>

5. 解决方案

微软官方针对该漏洞已发布安全更新补丁,补丁地址:

 

https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-0729

二、漏洞复现

1. 环境搭建

  • 靶机:Windows 10 1803 x64

  • 靶机操作:在任意位置创建文件夹,将poc文件放入文件夹中

2. 复现过程

直接双击打开包含poc文件的文件夹(无需双击poc文件,只需双击包含poc的文件夹即可),explorer.exe崩溃重启。

三、漏洞分析

1. 基本信息

  • 漏洞文件:StructuredQuery.dll
  • 漏洞函数:StructuredQuery1::ReadPROPVARIANT()
  • 漏洞对象:VT_VARIANT PropertyVariant元素创建的一个24字节的数据缓冲区

2. 背景知识

(限于篇幅问题,此处不对.LNK的完全结构做详细记录,而只是介绍一个合法的最小化的结构,感兴趣的同学可以到参考文献中的链接1进行详细的结构学习。结构介绍中所有图片均以BaiduNetdisk.exe的link文件为样例。)

1. Shell Link Binary File Format

LNK格式可以表达如下:

1
2
SHELL_LINK = SHELL_LINK_HEADER [LINKTARGET_IDLIST] [LINKINFO]
              [STRING_DATA] *EXTRA_DATA

SHELL_LINK_HEADER:一个ShellLinkHeader结构,包含了确认信息,时间戳,以及指明一些可选结构是否存在的flags。

 

LINKTARGET_IDLIST:一个可选的LinkTargetIDList结构,指定了link的target。

 

LINKINFO:一个可选的LinkInfo结构,指明了处理link target必需的信息。

 

STRING_DATA:0个或多个StringData结构,用于传递用户接口和路径标识信息。

 

EXTRA_DATA:0个或多个和ExtraData结构。

 

备注:

  • Shell Link Binary File Format的结构可以在固定长度字段中定义字符串。 在固定长度的字段中,字符串必须为非null。 如果字符串小于包含它的字段的大小,则终止空字符之后的字段中的字节是不确定的,并且可以具有任何值。未定义的字节不能使用。
  • 有一些Shell Link Binary File Format的结构包含size字段,例如ShellLinkHeader结构中的HeaderSize字段,以及LinkInfo结构中的LinkInfoSize字段。 除非另有说明,否则这些大小字段包含的值包括大小字段本身的大小。
1. ShellLinkHeader

ShellLinkHeader是每个shell link文件必须包含的结构,其结构如下:

Offset Size(bytes) Field Description
0x0000 4 HeaderSize must be 0x0000004c(76)
0x0004 16 LinkCLSID class identifier(must be 00021401-0000-0000-C000-000000000046)
0x0014 4 LinkFlags 可选和必须结构的相关信息
0x0018 4 FileAttributes FileAttributesFlags结构,指定link target的相关信息
0x001c 8 CreationTime FILETIME结构,指明link target创建时间
0x0024 8 AccessTime FILETIME结构,指明link target访问时间
0x002c 8 WriteTime FILETIME结构,指明link target写时间
0x0034 4 FileSize link target的大小,字节为单位。如果link target文件大于0xFFFFFFFF,则此值指定链接目标文件大小的最低有效32位。
0x0038 4 IconIndex 给定图标位置中图标的索引
0x003c 4 ShowCommand 指定app启动时窗口的状态,须为SW_SHOWNORMAL(0x00000001), SW_SHOWMAXIMIZED(0x00000003),SW_SHOWMINOACTIVE(0x00000007)中的其中一个
0x0040 2 HotKey 指定启动app的hotkeys
0x0042 2 reserved MUST be zero
0x0044 4 reserved MUST be zero
0x0048 4 reserved MUST be zero
 

 

以上所有结构除特殊说明外,均为小端序。

 

LinkFlags字段指定了是否存在可选结构以及各种选项,例如shell link中的字符串是否以Unicode编码,其结构如下:

1
2
3
4
5
                  1                  2                    3
0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|0|0|0|0|0|
                                                |A|

在大多数情况下设置的一个标志HasLinkTargetIDList由位置“ A”表示,即LinkFlags字段的第一个字节的最低有效位,如果已设置,则LinkTargetIDList结构必须紧跟Shell Link Header。一个例子的该字段的详细结构如下:

 

2. LinkTargetIDList

LinkTargetIDList结构指定了link的target,其结构如下:

Offset Size Field Description
0x0000 2 IDListSize IDList字段的大小,字节为单位
0x0002 var IDList 包含item ID list的IDList结构
 

 

如上图所示,首先是IDListSize结构,然后跟了6个ItemID结构(详细结构稍后介绍)的IDListIDList数组指定了一个持久化的item ID list的结构:

Offset Size Field Description
0x0000 var(x) ItemIDList 一个ItemID结构的数组
0x0000+x 2 TerminalID 指定item ID的结尾,必须为0
 

ItemIDList的作用实际上与文件路径的作用相同,其中的每个ItemID结构对应于类似路径的层次结构中的一个路径组件。ItemID可以引用实际的文件系统文件夹,例如“控制面板”或“保存的搜索”之类的虚拟文件夹,或充当执行特定功能的“快捷方式”的其他形式的嵌入式数据。

 

通常情况下,ItemID的结构如下所示:

Offset Size Field Description
0x0000 2 ItemSize IDList字段的大小,字节为单位
0x0002 1 ItemType Item类型
0x0003 1 Unused
0x0004 var var 基于指定的ItemID结构填充不同的字段
 

 

从偏移量0x0004开始的两个字节的值与ItemSizeItemType结合使用来帮助确定ItemID的类型。例如,如果ItemSize的值为0x14,ItemType的值为0x1f,在0x0004的2个字节的值如果大于ItemSize,那么就认为ItemID的剩余部分由一个16字节的GUID组成,这通常是LNK文件中指向标准文件的第一个ItemID的结构;如果ItemSize的值大于包含GUID所需的值,但是小于0x0004偏移处的值,那么在GUID的后面会跟 一个ExtraDataBlock,block开始为一个2字节的size,后续包含VersionSignature

 

更多关于ItemIDListItemID的详细信息可以参见参考文献中的ItemID部分。下面的示意图可以更好地理解以上的完整结构:

 

 

从图中可以明显看出各种结构的具体的值,与前面的结构相符合。比如Header中的GUID值为{00021401-0000-0000-C000-000000000046}LinkFlags字段的HasLinkTargetIDList设置为1,所以在Header后面紧跟了多个LinkTargetIDList结构,每个结构指向一个target,第一个结构的Value为MyComputer,往后依次为D:\Program File(x86)等等,最后一个为BaiduNetdisk.exe,而所有的LinkTargetIDList组合起来,为该LNK文件指向的实际的application的绝对路径。而第一个LinkTargetIDList时一个虚拟的文件系统文件夹,后面的均为实际的文件系统文件夹。在所有LinkTargetIDList结构的末尾是一个2字节大小的TerminalID,其值为0。

3. Windows中的搜索查询的快捷方式

1. 2种不同的搜索查询

Windows允许用户以2种方式来保存或创建搜索查询的快捷方式。第一种方式是将查询保存为一个XML文件,扩展为".search-ms",该种格式只有一部分内容以文档形式进行了公开。第二种方式是将".search-ms"文件进行序列化然后直接嵌入到LNK文件中,最终的文件包含一个IDList结构,该结构以一个Delegate Folder ItemID开始,后面跟一个User Property View ItemID用于指定搜索查询。

 

第一种方式:

 

 

而打开保存的文件内容可以看到都是xml元素:

 

 

第二种方式:

 

 

点击前面的搜索图标,会显示保存为一个.search-ms文件,然后按住红框中的图标,直接拖拽到一个路径下,会创建一个LNK文件。而该LNK文件的作用与第一种方式的作用相同,都保存了一样的搜索操作。

 

 

查看文件内容,是一个标准的LNK文件:

 

2. Delegate Folder ItemID

Delegate Folder ItemID的0x0004偏移处的2个字节是一个表示其余结构的大小的字段,总体结构如下:

Offset Size Field
0x0000 2 ItemSize(n)
0x0002 1 ItemType
0x0003 1 Unused
0x0004 2 DataSize
0x0006 4 Signature(0x23a3dfd5)
0x000a 2 PropertyStoreSize(y)
0x000c 2 IdentifierSize(x)
0x000e x IdentifierData(if x > 0)
0x000e + x y PropertyStoreData(if y > 0)
0x000e + x + y 6 Unkown(0x0)
0x0014 + x + y 16 Delegate GUID ({5E591A74-DF96-48D3-8D67-1733BCEE28BA})
0x0024 + x + y 16 Item GUID
0x0034 + x + y n - (0x0034 + x + y) ExtraDataBlock
 

LNK文件中的所有GUID均以RPC IDL形式进行存储,即GUID的前3个段均以小端序存储(例如DWORD,WORD等),后2个段均以独立字节存储。例如,GUID{01234567-1234-ABCD-9876-0123456789AB}的二进制表示为:\x67\x45\x23\x01\x34\x12\xCD\xAB\x98\x76\x01\x23\x45\x67\x89\xAB

 

Delegate Folder ItemID中的详细函数并没有进行公开,但其作用大概是在GUID字段中指定一个class,对后续的ItemID都使用GUID指定的class来进行处理,以这种方式以该class为层次结构的"root"。对于包含嵌入式数据的LNK文件来说,Item GUID{04731B67-D933-450A-90E6-4ACD2E9408FE},对应于CLSID_SearchFolder,即对Windows.Storage.Search.dll的引用。

3. User Property View ItemID

Delegate Folder ItemID后面跟一个User Property View ItemID,其结构如下:

Offset Size Field
0x0000 2 ItemSize(n)
0x0002 1 ItemType
0x0003 1 Unused
0x0004 2 DataSize
0x0006 4 Signature(0x10141981)
0x000a 2 PropertyStoreSize(y)
0x000c 2 IdentifierSize(x)
0x000e x IdentifierData(if x > 0)
0x000e + x y PropertyStoreList(if y > 0)
0x000e + x + y 6 Unkown(0x0)
0x0014 + x + y n - (0x0014 + x + y)ist ExtraDataBlock
 

在以上字段中,与漏洞关系比较大的是PropertyStoreList字段。该字段如果存在,那么会包含一个或多个序列化的PropertyStore iterm,其结构如下所示:

Offset Size Field
0x0000 4 Store Size
0x0004 4 Version("1SPS")
0x0008 16 Property Format GUID
0x0018 var Property Store Data (sequence)
 

Property Store Data字段是序列化property store中的一系列properties,在PropertyStore中的所有的properties均属于Property Format GUID标识的class。每个property通过一个数字ID进行标识,当与Property Format GUID结合使用时,该ID称为property key或者PKEY

 

如果Property Format GUID等于{D5CDD505-2E9C-101B-9397-08002B2CF9AE},那么PKEY的确定方式略有不同。每个property当作Property Bag的一部分,格式如下:

Offset Size Field
0x0000 4 Value Size(x)
0x0004 4 Name Size(y)
0x0008 1 Reserved(0x00)
0x0009 y Name (wide characters)
0x0009 + y x - y - 9 TypePropertyValue
 

Property bags通常包含类似名称为"Key:FMTID"或"Key:PID"的内容,这些名称表示了解释其他元素的特定的PKEY

 

如果Property Format GUID不是前面提到的Property Bags形式的GUID,那么每个property将会使用一个整数形式的PID进行标识,其结构如下:

Offset Size Field
0x0000 4 Size(x)
0x0004 4 Id
0x0008 1 Reserved(0x00)
0x0009 x - 9 TypePropertyValue
 

TypePropertyvalue对应于property集中的property的类型值,property集遵循 Microsoft Object Linking and Embedding (OLE) Property Set Data Structures 中的规范(详见参考文献3)。

4. PKEY_FilterInfo

各种PKEY由Windows SDK中的头文件进行定义,但是,许多文件没有记录,只能通过检查相关库的调试符号中的引用来识别。对于包含嵌入式搜索数据的LNK文件来说,User Property View ItemID中的第一个PropertyStore有一个Property Format GUID ,其值为{1E3EE840-BC2B-476C-8237-2ACD1A839B22},其结构中的Id值为2,对应于PKEY_FilterInfo

 

PKEY_FilterInfoTypedPropertyValue字段包含一个VT_STREAM属性。通常情况下,一个VT_STREAM property包含的type值为0x0042,2字节的padding,和一个IndirectPropertyNameIndirectPropertyName指明了一个备用流,该备用流或者包含simple property set存储中的PropertySetStream数据包,或者包含non-simple property set存储中的CONTENTS流数据(详细内容参考文献4)。该名称由宽字符的字符串"prop"开始,其后跟对应于PropertySet数据包中的property标识符的十进制字符串。

 

然而,因为LNK文件使用嵌入在VT_SREAM中的序列化property store,IndirectPropertyName仅仅检查是否以"prop"开头,而value本身会被忽略,这就导致TypedPropertyValue的结构变成如下形式:

Offset Size Field Description
0x0000 2 Property Type 0x0042, VT_STREAM
0x0002 2 Padding 0x0
0x0004 4 IndirectPropertyName Length x
0x0008 x IndirectPropertyName
0x0008 + a 2 Padding 0x0
0x000a + x 4 Stream Data Size y
0x000e + x y Stream Data
 

Stream Data中的数据取决于stream property属于的特定的PKEY。对于PKEY_FilterInfo来说,Stream Data通常包含一个嵌入的PropertyStoreList,其中包含了多个序列化的PropertyStore结构。此时,Stream Data的结构如下所示:

Offset Size Field
0x0000 4 Size(x)
0x0004 4 PropertyStoreListSize(y)
0x0008 y PropertyStoreList
0x0008 + y 4 Padding(0x0)
0x000c + y var Alignment padding
 

PKEY_FilterInfo stream 中的嵌套PropertyStoreList实际上是.search-ms文件中"conditions"标记的序列化版本。下面是一个conditions tag的样例结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<conditions>
    <condition type="andCondition">
         <attributes>
            <attribute attributeID="{9554087B-CEB6-45AB-99FF-50E8428E860D}" clsid="{C64B9B66-E53D-4C56-B9AE-FEDE4EE95DB1}"  chs="1" sqro="585" timestamp_low="2637566744" timestamp_high="30796574">
                <condition type="andCondition">
                    <attributes>
                        <attribute attributeID="{9554087B-CEB6-45AB-99FF-50E8428E860D}" clsid="{C64B9B66-E53D-4C56-B9AE-FEDE4EE95DB1}" chs="0" parsedString="size:500..1000 blah" localeName="en-US" timestamp_low="2555883479" timestamp_high="30796574" />
                    </attributes>
                    <condition type="leafCondition" property="System.Size" operator="imp" propertyType="stringarray" value="=500; =1000" valuetype="System.StructuredQueryType.Integer" localeName="en-US">
                        <attributes />
                     </condition>
                     <condition type="leafCondition" property="" operator="imp" propertyType="string" value="blah" localeName="en-US">
                         <attributes />
                     </condition>
                 </condition>
             </attribute>
         </attributes>
[......]
    </condition>
</conditions>

"attribute"标签的详细功能尚未公开,但是该标记包含一个对应于CONDITION_HISTORYGUID,一个对应于StructuredQueryCConditionHistory类的CLSID,这表示嵌套的condition和attribute结构代表着之前已保存的搜索查询记录。通常情况下,attribute标签的chs可以确定可选history是否存在(猜测)。当此结构序列化到property store中时,会将其放入
PKEY_FilterInfo PropertyStoreList中,它采用带有上述Property Format GUID的property bag的形式。特别情况下,序列化的Conditions结构包含在一个使用名称为Condition进行标识的VT_STREAM Property中。此时,PropertyStore item的结构如下:

Offset Size Field
0x0000 4 Value Size(x)
0x0004 4 Name Size(0x14)
0x0008 1 Reserved(0x00)
0x0009 20 Name("Condition")
0x001d 2 Property Type(0x0042 VT_STREAM)
0x001f 2 Padding(0x0)
0x0021 4 Indirect Propname Length (y)
0x0025 y Indirect Propname (prop *)
0x0025 + y var Condition object
 

Condition object通常是一个Leaf Condition或者Compound Condition对象,其中可以包含嵌套对象,通常包含一个或多个Leaf Condition,也可能包含其他的Compound Condition对象。2种condition object都具有以下结构:

Offset Size Field
0x0000 4 Condition size (x)
0x0004 16 Condition GUID
0x0014 4 Number of Attributes
0x0018 var Attributes
 

对于Leaf Condition来说,其Conditioin GUID{52F15C89-5A17-48E1-BBCD-46A3F89C7CC2};对于Compound Condition来说,其Conditioin GUID{116F8D13-101E-4FA5-84D4-FF8279381935}Attributes字段由几个Attributes attribute结构组成,每个对应于之前提到的search-ms文件中的attribute标签,字段结构如下:

Offset Size Field
0x0000 16 AttributeID
0x0010 16 Attribute CLSID
 

Attribute的其他结构取决于AttributeIDCLSID。对于前面的attributeID{9554087B-CEB6-45AB-99FF-50E8428E860D}CLSID{C64B9B66-E53D-4C56-B9AE-FEDE4EE95DB1}CONDIOTION_HISTORY attribute来说,其剩余结构为一个ConditionHistory对象,该对象结构如下:

Offset Size Field
0x0000 4 chs
0x0004 4 parseStringWChars (x = value - 1)
0x0008 x * 2 parseString
0x0008 + (x * 2) 4 localeStringWChars (y = value -1)
0x000c + (x * 2) y * 2 localeString
0x000c + (x 2) + (y 2) 4 sqro
0x0010 + (x 2) + (y 2) 4 unknown
0x0014 + (x 2) + (y 2) 8 timestamp
0x001c + (x 2) + (y 2) 4 nested_condition (may be number of directly nested conditions)
0x0020 + (x 2) + (y 2) var Condition object( if nested_condition > 0)
 

如果nested_condition的值大于0,CONDITION_HISTORY就会有嵌套的condition object,该对象本身也可能具有具有嵌套条件的嵌套属性,依此类推。

 

在完全读取了所有的嵌套结构后,Compoound ConditionLeaf Condition结构后续就不同了。紧接Attributes字段后面,Compound Condition的结构如下:

Offset Size Field
0x0000 4 Unknown(通常为0x0)
0x0004 4 numFixedObjects
0x0008 var Conditions( if numFixedObjects > 0)
 

numFixedObjects字段指明了后续会跟多少附加conditions(通常为Leaf Conditions)。

 

而对于Leaf Condition,其结构如下:

Offset Size Field
0x0000 16 Condition Type PKEY GUID
0x0010 4 Conditioin Type Property ID
0x0014 4 Condition Operation(CONDITION_OPERATION enum)
0x0018 var PropertyVariant
var 4 valuetypeStringWChars (x = value - 1)
var x * 2 valueTypeString
var 4 localeStringWChars (y = value -1)
var y * 2 localeString
var var TokenInfomationComplete1 flag
var 4 TokenInfomationComplete1 ( if flag = 0x1 or 0x2)
var var TokenInfomationComplete2 flag
var 4 TokenInfomationComplete2 ( if flag = 0x1 or 0x2)
var var TokenInfomationComplete3
var 4 TokenInfomationComplete3 ( if flag = 0x1 or 0x2)
 

TokenInfomationComplete结构存在与否取决于前面的flag是否进行了设置,如果没有设置那么紧跟下一个flag;如果进行了设置,那么紧跟的结构如下:

Offset Size Field
0x0000 4 Unknown
0x0004 4 Unknown
0x0008 4 numWChars (x = value - 1)
0x000c x * 2 String
0x000c + (x * 2) 4 Value (flag = 2时才存在)
 

对于Leaf ConditionPropertyVariant字段,其结构大致与PROPVARIANT结构(参考文献5)相似。PropertyVariant结构包含2字节的type,其后为该type的data。重要的是要注意,由于参考文献5中指定的填充字节往往不存在,因此StructuredQuery似乎对PROPVARIANT结构进行了自定义实现。 还需要注意的是,值0x1000或VT_VECTOR与另一种类型结合使用,意味着将有多个指定类型的值。

 

简述一个具有保存的搜哦的LNK文件的最简结构如下所示(去除无关结构):

 


以上只是一个最简单的使用单个Leaf Condition结构的搜索LNK结构,真实情况种往往是从Compund Condition开始,别切包含很多嵌套结构(包括许多的Leaf Condition)。

3. 详细分析

1. 漏洞触发流程

造成该漏洞的主要原因是在处理Leaf Condition中的type为VT_VARIANTPropertyVariant结构时发生错误导致。

 

如果一个LNK文件有一个ItemID List,且其第一个ItemIDDelegate Folder ItemID,且该Delegate Folder ItemIDd的GUID表示CLSID_SearchFolder,那么首先调用Windows.Storage.Search.dll中的CDBFolder::BindToObject()函数进行处理,该函数会调用CDBFolder::GetFilterConditionForChild()函数从child ItemID中获取search filter condition。

 

第一阶段,CDBFolder::GetFilterConditionForChild()函数在进行查找时,会在child ItemID中搜索PKEY_FilterInfo property,如果找到了,在序列化property store中的包含一个property bag的VT_STREAM就会通过调用SHLoadFilterFromStream()函数进行加载,该函数会创建一个CFilterCondition对象然后提供给IUnknown_LoadFromStream()函数。该操作会调用CFIlterCondition::Load()函数,而该函数会首先将property bag复制到一个内存中的store中,然后开始校验该store的结构,通过查找名称为Name, Type,key:FMTID,Key:PID以及Condition的字符串来确认是否property bag元素。

 

第二阶段,在确认完所有元素后,调用LoadConditionFromStream()函数来读取Condition property bag中的VT_STREAM,该元素调用IUnknown_LoadKnownImplFromStream()来读取Condition GUID并从StructuredQuery.dll中创建并加载相关的condition对象。在从stream中加载condition对象的过程中,所有嵌套的对象会按照出现的顺序进行加载,包括AttributesConditions。当遇到一个Leaf Condition时,会调用StructuredQuery1::LeafCondition::Load()函数来读取所有的Attributes,然后读取Condition Type PKEYCondition Operation,然后调用StructuredQuery1::ReadPROPVARIANT()函数来读取PropertyVariant结构。

 

第三节阶段,StructuredQuery1::ReadPROPVARIANT()先读取2字节的type,然后检查VT_ARRAY(0x2000)是否进行了设置,这里主要是因为StructuredQuery不支持。然后进入到一个switch语句来根据type进行不同的处理。如果type设置为VT_VARIANT(0x000c),就会检查完整的type字段来确认是否设置了VT_VECTOR,如果没有设置,则调用CoTaskMemAlloc()来分配包含另一个PropertyVariant结构的24字节的缓冲区。在递归调用StructuredQuery1::ReadPROPVARIANT()函数以读取紧随VT_VARIANT 的type字段之后的另一个PropertyVariant结构之前,并没有对这个缓冲区进行初始化。如果下一个type字段设置为VT_CF(0x0047),则应该是一个包含一个指向剪贴板数据的指针的PropertyVariant结构,ReadPROPVARIANT()函数尝试将stream的后4个字节写入先前分配的24字节缓冲区中的8字节值所指向的位置。由于缓冲区并没有进行初始化,数据会被写入到一个未定义的位置,最终导致任意代码执行。

 

用一个简单的流程图来描述上面的流程:

 

 

2. 静态分析

首先是StructuredQuery1::LeafCondition::Load()函数:

 

 

 

StructuredQuery1::LeafCondition::Load()函数种依次读取了Condition Type PKEY,Condition Operation,然后调用StructuredQuery1::ReadPROPVARIANT()函数读取PorpertyVariant结构。

 

进入到StructuredQuery1::ReadPROPVARIANT()函数内部:

 

五、参考文献

  1. Shell Link(.LNK) Binary File Format
  2. Common Explorer Concepts, Identifying Namespace Objects)
  3. MS-OLEPS: TypedPropertyValue
  4. MS-OLEPS: IndirectPropertyName
  5. Structured Storage, Propidl.h, PROPVARIANT structure

(未完待续)
大家稍等哈,最近有活动,实在是忙不开,到时候我看看直接把震网的也一起加进来,抱歉


[公告]请完善个人简历信息,好工作来找你!

最后于 2020-9-17 14:28 被有毒编辑 ,原因:
收藏
点赞0
打赏
分享
最新回复 (2)
雪    币: 55
活跃值: 活跃值 (154)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
killpy 活跃值 2 2020-9-16 18:00
2
0
好啊
雪    币: 207
活跃值: 活跃值 (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
0
MARK一下
游客
登录 | 注册 方可回帖
返回