Internet Explorer漏洞分析(三)[上]——VBScript Scripting Engine初探
字数 1494 2025-08-06 08:35:25

VBScript Scripting Engine 深入解析

环境配置

  • 操作系统: Windows 7 Service Pack 1
  • Internet Explorer版本: 8.0.7601.17514
  • vbscript.dll版本: 5.8.7601.17514

0x01 变量系统

Variant 数据结构

VBScript 中唯一的数据类型是 Variant,其结构定义如下:

typedef struct tagVARIANT {
    union {
        struct {
            VARTYPE vt;
            WORD wReserved1;
            WORD wReserved2;
            WORD wReserved3;
            union {
                LONGLONG llVal;
                LONG lVal;
                BYTE bVal;
                SHORT iVal;
                FLOAT fltVal;
                DOUBLE dblVal;
                VARIANT_BOOL boolVal;
                SCODE scode;
                CY cyVal;
                DATE date;
                BSTR bstrVal;
                IUnknown *punkVal;
                IDispatch *pdispVal;
                SAFEARRAY *parray;
                // 其他指针类型...
                VARIANT *pvarVal;
                PVOID byref;
                CHAR cVal;
                USHORT uiVal;
                ULONG ulVal;
                ULONGLONG ullVal;
                INT intVal;
                UINT uintVal;
                DECIMAL *pdecVal;
                // 其他指针类型...
            } __VARIANT_NAME_3;
        } __VARIANT_NAME_2;
        DECIMAL decVal;
    } __VARIANT_NAME_1;
} VARIANT;

变量声明与赋值

  • 显式声明:

    Dim Name, Age, Hex, Pi
    Name = "Ethon"
    Age = 27
    Hex = &h80000000
    Pi = 3.1415926
    
  • 隐式声明:

    Hello = "ABC123"
    

赋值操作对应的函数是 vbscript!AssignVar,其工作原理:

  1. 检查 pvargSrc->vt
  2. 如果不满足特定条件,执行 VariantCopyInd(&pvarDest, pvargSrc)
  3. 隐式声明变量时,pvarg 初始化为全零

0x02 数组系统

SAFEARRAY 结构

typedef struct tagSAFEARRAY {
    USHORT cDims;      // 数组维度
    USHORT fFeatures;  // 数组特性标志
    ULONG cbElements;  // 每个元素的大小
    ULONG cLocks;      // 锁定计数
    PVOID pvData;      // 数据指针
    SAFEARRAYBOUND rgsabound[1]; // 各维度边界信息
} SAFEARRAY;

SAFEARRAYBOUND 结构

typedef struct tagSAFEARRAYBOUND {
    ULONG cElements;  // 该维度元素数量
    LONG lLbound;     // 该维度下界
} SAFEARRAYBOUND, *LPSAFEARRAYBOUND;

数组操作

  1. 一维数组:

    Dim stu_name(3)
    stu_name(0) = "Alan"
    stu_name(1) = "Susan"
    stu_name(2) = "Lisa"
    stu_name(3) = "Mary"
    
  2. Array函数创建:

    Dim stu_name
    stu_name = Array("Alan","Susan","Lisa","Mary")
    

    对应函数 vbscript!MakeArray,参数:

    • cDims: 维度数(1-64)
    • VAR: 数组大小
  3. 多维数组:

    Dim stu_name(2,3)
    

    创建过程:

    • 各维大小在内存中并列存储
    • 从最高维到最低维存储
    • 调用 VAR::PvarGetTypeValrgsabound 赋值
  4. 动态数组:

    Dim MyArray()
    ReDim MyArray(3)
    

    使用 Preserve 保留元素:

    ReDim Preserve MyArray(5)
    

    对应函数 vbscript!RedimPreserveArray,最终调用 SafeArrayRedim

0x03 调试辅助函数

IsEmpty(var)

对应函数 vbscript!VbsIsEmpty,第三个参数为待检查变量:

dim a
a = &h1234
IsEmpty(a)

IsObject(var)

对应函数 vbscript!VbsIsObject,第三个参数为待检查变量:

dim a
a = &h1234
IsObject(a)

0x04 VarType函数

dim a
a = &h1234
VarType(a)

执行流程:

  1. 调用 vbscript!VbsVarType
  2. 调用 GetVarType 获取类型值
  3. GetVarType 调用 PvarGetVarVal 检查类型是否为 0x4A0x0C
  4. 0x09 比较,不匹配则直接返回对象并获取 vt
  5. VbsVarType 完成最终赋值

0x05 LenB函数

On Error Resume Next
Dim length,a
a=1.12345678901235
length=LenB("Hello")
length=LenB(a)

功能:返回存储字符串的字节大小

执行流程:

  1. 参数为字符串时:

    • 调用 VAR::BstrGetVal 返回 pbstrVal
    • 调用 cbLengthBstr 返回长度
  2. 参数为变量时:

    • VAR::BstrGetVal 调用 VAR::PvarConvert 转换为字符串
    • 再进行长度计算

cbLengthBstr 函数读取字符串存储位置前4字节内容(即字符串长度)

关键数据结构总结

  1. Variant:

    • 核心数据结构,包含类型标识和值
    • vt 字段决定如何解释联合体中的值
  2. SAFEARRAY:

    • 管理数组内存布局
    • 支持多维数组
    • 包含锁定机制和安全特性
  3. SAFEARRAYBOUND:

    • 描述数组每个维度的边界
    • 包含元素数量和下界

调试技巧

  1. 使用 IsEmptyIsObject 检查变量状态
  2. 通过 VarType 获取变量类型信息
  3. 使用 LenB 检查字符串内存占用
  4. 在调试器中观察 AssignVar 函数的参数传递

安全注意事项

  1. 数组边界检查不严格可能导致越界访问
  2. 类型转换过程中的安全检查不足
  3. 动态数组重分配时的内存管理问题

以上内容涵盖了VBScript引擎的核心机制,包括变量系统、数组实现和关键函数的工作原理,为深入分析IE漏洞提供了必要的基础知识。

VBScript Scripting Engine 深入解析 环境配置 操作系统 : Windows 7 Service Pack 1 Internet Explorer版本 : 8.0.7601.17514 vbscript.dll版本 : 5.8.7601.17514 0x01 变量系统 Variant 数据结构 VBScript 中唯一的数据类型是 Variant,其结构定义如下: 变量声明与赋值 显式声明 : 隐式声明 : 赋值操作对应的函数是 vbscript!AssignVar ,其工作原理: 检查 pvargSrc->vt 值 如果不满足特定条件,执行 VariantCopyInd(&pvarDest, pvargSrc) 隐式声明变量时, pvarg 初始化为全零 0x02 数组系统 SAFEARRAY 结构 SAFEARRAYBOUND 结构 数组操作 一维数组 : Array函数创建 : 对应函数 vbscript!MakeArray ,参数: cDims : 维度数(1-64) VAR : 数组大小 多维数组 : 创建过程: 各维大小在内存中并列存储 从最高维到最低维存储 调用 VAR::PvarGetTypeVal 为 rgsabound 赋值 动态数组 : 使用 Preserve 保留元素: 对应函数 vbscript!RedimPreserveArray ,最终调用 SafeArrayRedim 0x03 调试辅助函数 IsEmpty(var) 对应函数 vbscript!VbsIsEmpty ,第三个参数为待检查变量: IsObject(var) 对应函数 vbscript!VbsIsObject ,第三个参数为待检查变量: 0x04 VarType函数 执行流程: 调用 vbscript!VbsVarType 调用 GetVarType 获取类型值 GetVarType 调用 PvarGetVarVal 检查类型是否为 0x4A 或 0x0C 与 0x09 比较,不匹配则直接返回对象并获取 vt 值 VbsVarType 完成最终赋值 0x05 LenB函数 功能:返回存储字符串的字节大小 执行流程: 参数为字符串时: 调用 VAR::BstrGetVal 返回 pbstrVal 调用 cbLengthBstr 返回长度 参数为变量时: VAR::BstrGetVal 调用 VAR::PvarConvert 转换为字符串 再进行长度计算 cbLengthBstr 函数读取字符串存储位置前4字节内容(即字符串长度) 关键数据结构总结 Variant : 核心数据结构,包含类型标识和值 vt 字段决定如何解释联合体中的值 SAFEARRAY : 管理数组内存布局 支持多维数组 包含锁定机制和安全特性 SAFEARRAYBOUND : 描述数组每个维度的边界 包含元素数量和下界 调试技巧 使用 IsEmpty 和 IsObject 检查变量状态 通过 VarType 获取变量类型信息 使用 LenB 检查字符串内存占用 在调试器中观察 AssignVar 函数的参数传递 安全注意事项 数组边界检查不严格可能导致越界访问 类型转换过程中的安全检查不足 动态数组重分配时的内存管理问题 以上内容涵盖了VBScript引擎的核心机制,包括变量系统、数组实现和关键函数的工作原理,为深入分析IE漏洞提供了必要的基础知识。