作者归档:Jack

ChakraCore Var数据类型指针疑惑

我最近看ChakraCore的源码做CVE分析的时候,一直不知道为什么Object Array能存储所有类型的对象。对于Native Value,它在高16位打Tag直接存进void * ,对于Object Pointer,它在void * 存入原封不动的指针。判断的时候,用SHR右移48位,看剩下的高位是否为0,若不为0,就是Tagged Native Value,否则就是Object Pointer。

今天分析CVE的时候突然想明白了48位是怎么定出来的了。因为x86_64现在的Virtual Address Size是48位。而且还有一个原因是,x86用户态的Canonical VM Address高16位是0000h开头。换个架构,这玩意貌似就不适用了。也没准随着Arch发展一下,VA Size增大一些,ChakraCore就彻底倒闭了。

注:微软不支持,应该已经倒闭了。

批量取消Youtube视频订阅方法

发现我的Youtube账号里莫名其妙多出来大量订阅,遂想取消之。批量取消JavaScript代码如下:
页面地址:https://www.youtube.com/feed/channels

buttons = document.querySelectorAll('#grid-container tp-yt-paper-button');
len = buttons.length;
index = 0;
while (index < len) {
    t = 100 * index;
    setTimeout((function(index, t) {
        return function() {
            buttons[index].dispatchEvent(new MouseEvent('click'));
            setTimeout(function() {
                cancel = document.querySelector('tp-yt-paper-dialog #confirm-button');
                cancel.dispatchEvent(new MouseEvent('click'));
                console.log(`共{len}个订阅,正在取消第{index + 1}个订阅`);
            },
            50);
        }
    })(index, t), t);
    index++;
}

论文笔记:Fuzzing JavaScript Engines with Aspect-preserving Mutation

简介

模糊测试技术(Fuzzing)是现今最具有可实施性的Bug查找技术。它被广泛应用在真实世界中的复杂程序中。

模糊测试器(Fuzzer)主要分为两类,分别称为生成性的模糊测试器(Generative Fuzzer)和变异性的模糊测试器(Mutational Fuzzer):Generative Fuzzer利用相应编程语言的语料库(Corpus)中已经分拆好的代码块,通过语言的文法或预先定义的规则将它们装拼起来作为种子文件。Mutational Fuzzer通过更改已有的PoC或测试样例中的部分代码来产生新的种子文件。

但作者认为,这两种类型的方法都不能充分利用高质量的语料库。因为上述两种方法不但没有良好的保持一些作为PoC的固有属性,反而为了代码覆盖率的因素破坏了它们。

为了解决上述问题,本文的作者创新性地提出了“方位保持变异”(Aspect-preserving mutation)的方法来保持PoC的固有属性。该理论结合了Generative和Mutational的特性,对于其中的一大部分代码保留,一小部分代码通过Generative的方法进行生成。生成时,注意维持其中的固有属性。其中,固有属性包括两种:结构保持(Structure preservation)和类型保持(Type preservation)。为了达到这一目的,作者对已有的语料库文件进行建模,形成带类型的抽象语法树(Typed Abstract Syntax Tree)模型。在语法树的基础上施加相应的变异。

作者将该理论运用进了他们最先进的JavaScript Fuzzer,DIE。他们利用DIE对ChakraCore,JavaScriptCore和V8进行了Fuzz。结果产生了48个Bug,有12个分配了对应的CVE编号。

动机

当下的Fuzzer不能够充分的探索JavaScript引擎的深层次代码及其中存在的Bug,主要的原因如下:
1、搜索空间过大:当下的Fuzzer为了触发内存损坏(Memory Corruption)错误,一味的追求代码覆盖率。但对于现今的JS引擎,这种简单错误已经减少。更多的是深层次的逻辑错误。
2、不能充分的利用已有的语料库:能够触发JIT的代码都需要有一定的前置条件,并且这些前置条件有相当多的共同点。例如,执行次数较多的for循环会触发JIT。其它类型的Fuzzer没有很好的保持这些前置条件,从而降低了产生Crash的机会。

主要方法及工作流程

Structure-preserving mutation: 保持程序的主要结构,例如控制流。这样能够增加保留触发JIT的前置条件的可能性。
Type-preserving mutation: 通过对语料库文件建模,形成带类型的抽象语法树。每次对子树对应的代码段进行更改时,始终保持它们的返回类型或值类型基本一致,以减少出现语法或类型等错误的可能性。

Workflow:
前处理部分:首先对原始的种子文件送入插桩后的引擎进行动态类型分析,得到对应的类型分析。结合静态文法识别出的AST,产生对应的Typed-AST并送入语料库。
种子生成部分:变异引擎(Mutation Engine)从语料库中选取Typed-AST加以修改,形成变异的Type-AST,再由该AST反推回JS文件,送入Fuzzing平台。
执行/反馈部分:由分布式Fuzzing系统进行执行,产生覆盖率反馈和崩溃报告。其中覆盖率反馈闭环传递至语料库,崩溃报告发送给工程师。

评估结果

1、DIE可以在现实世界的JS引擎中找到新的Bug,并且还不少。
2、本篇论文提出的“方位保持”在找到Bug方面起到了关键作用。一是“方位”(即固有属性)确实能很好的触发Bug,二是DIE确实保持了语料库中相应程序片段的“方位”。
3、DIE相对其他类型的Fuzzer,能够较好地产生在语法和语义上正确的JS程序。
4、在输入空间(代码覆盖率)及Crash产生率上,DIE相对其他Fuzzer都有优势。

展望

1、种子优先级:因为种子的质量不同,在做种子的变异时,可以对种子实现优先级的排队。
2、规则优先级:可以根据测试需要,对程序中Generative的部分的产生规则也实现优先级的排队。
3、“方位”的标注:利用人工标注代码中“方位”的特性。
4、“方位”在其它语言的推广:“方位”的思想对于其他语言也是通用的,可以将这一思想拓展到其他语言上编写Fuzzer。

引用

[0] 论文链接:https://ieeexplore.ieee.org/document/9152648/

用Visual Studio 2022编译ChakraCore遇到的Bug解决方法

由于读论文,复现CVE-2018-0840的需要。从Github官网上下载ChakraCore旧版代码[1]。代码很老了,在新版Visual Studio 2022中编译出现大量问题,特此记录如下解决方案。

  1. 首先根据Visual Studio提示将所用的解决方案及项目全部升级。
  2. 编译器报错说typeinfo.h找不到时,把对应地方的typeinfo.h全部改成typeinfo
  3. 参照[2]的说明向Build/Common.Build.Default.props中加入对应的编译器版本。

如果不加入,他会一直提示MSBuild 错误 MSB8020,但告诉你的是v143 生成工具未安装。这件事让人很迷惑,我早已经安装完了。按照3的步骤做完就不会提示了。

引用:

[1] https://github.com/chakra-core/ChakraCore/tree/e8738ca441f77b5271fedf8574858eeb8b8b7114
[2] https://github.com/chakra-core/ChakraCore/pull/6759