v8 JIT fuzz

浏览器安全 1年前 (2022) admin
888 0 0

最近看到有两篇关于js engine jit fuzz 的论文 “JIT-Picking: Differential Fuzzing of JavaScript Engines” 和”FuzzJIT: Oracl-Enhanced Fuzzing for JavaScript Engine JIT Compiler”,两者都采用了差分测试的方法来检测JIT 的bug,并且都是基于fuzzilli 工具,也是采用fuzzilli 变异方式,抽空看了下两篇,做下记录

FuzzJIT 

国人写的,我看完后总结起来就是”一个模版走天下”,下面是一个生成的testcase

 function classOf(object) {     var string = Object.prototype.toString.call(object);   return string.substring(8, string.length - 1); }
function deepObjectEquals(a, b) {  var aProps = Object.keys(a);  aProps.sort();  var bProps = Object.keys(b);  bProps.sort();  if (!deepEquals(aProps, bProps)) {    return false;  }  for (var i = 0; i < aProps.length; i++) {    if (!deepEquals(a[aProps[i]], b[aProps[i]])) {      return false;    }  }  return true;}function deepEquals(a, b) {  if (a === b) {    if (a === 0) return (1 / a) === (1 / b);    return true;  }  if (typeof a != typeof b) return false;  if (typeof a == 'number') return (isNaN(a) && isNaN(b)) || (a!=b);  if (typeof a == 'string') return a.length == 55 && a.toString().search(" GMT") !== -1;  if (typeof a !== 'object' && typeof a !== 'function' && typeof a !== 'symbol') return false;  var objectClass = classOf(a);  if (objectClass !== classOf(b)) return false;  if (objectClass === 'RegExp') {    return (a.toString() === b.toString());  }  if (objectClass === 'Function') return false;  if (objectClass === 'Array') {    var elementCount = 0;    if (a.length != b.length) {      return false;    }    for (var i = 0; i < a.length; i++) {      if (!deepEquals(a[i], b[i])) return false;    }    return true;  }  if (objectClass !== classOf(b)) return false;  if (objectClass === 'RegExp') {    return (a.toString() === b.toString());  }  if (objectClass === 'Function') return true;  if (objectClass == 'String' || objectClass == 'Number' ||      objectClass == 'Boolean' || objectClass == 'Date') {    if (a.valueOf() !== b.valueOf()) return false;  }  return deepObjectEquals(a, b);}function opt(opt_param){const v2 = new Int16Array(54725);const v3 = v2.__proto__;let v4 = 0;do {    const v6 = Int16Array & v2;    const v7 = v3.matchAll;    const v8 = v4++;} while (v4 < 8);return v3;}let jit_a0 = opt(false);opt(true);let jit_a0_0 = opt(false);%PrepareFunctionForOptimization(opt);let jit_a1 = opt(true);%OptimizeFunctionOnNextCall(opt);let jit_a2 = opt(false);if (jit_a0 === undefined && jit_a1 === undefined) {    opt(true);} else {    if (jit_a0_0===jit_a0 && !deepEquals(jit_a0, jit_a2)) {        fuzzilli('FUZZILLI_CRASH', 0);    }}

作者针对JIT 优化过程中的几个pass 着手,设计了一份用于检测细微差异的模版,其中opt 函数由fuzzilli 来生成,其他代码用于检测

v8 JIT fuzz

检测方法直接比对优化前和优化后执行的结果,包括对象的一些属性值的检测。

成果

成果这边我比较关注的是v8 ,作者列出了5个bug,不过看下bug,属于安全漏洞的应该有11977 和1276923

v8 JIT fuzz

JIT-Picking 

这里作者采用了probe 的方式来检测无法通过segmentation fault 和sanitizer 的方式来探测bug,即检测js engine 在jit 关闭和打开的情况下的执行情况。

 

v8 JIT fuzz

具体的,作者修改了v8 的源码,增加了fuzzillihash builtin 来计算对象hash,在生成testcase 时插入该builtin 来记录对象的hash。

+ transitioning javascript builtin FuzzilliHash(+    js-implicit context: NativeContext, receiver: JSAny)(obj: JSAny): Undefined {++  let curVal: Smi = *NativeContextSlot(ContextSlot::FUZZILLI_HASH_INDEX);+  typeswitch (obj) {++    case (Null): {+      curVal += 1;+    }+    case (True): {+      curVal += 2;+    }+    case (False): {+      curVal += 4;+    }+    case (Undefined): {+      curVal += 8;+    }+    case (String): {+      curVal += 16;+    }+    case (s: Smi): {+      curVal += 32;+      let doubleValue: float64 = SmiToFloat64(s);+      if (Float64IsNaN(doubleValue)) {+        doubleValue = 1.0;+      }+      const lWord: uint32 = data_view::Float64ExtractLowWord32(doubleValue);+      const hWord: uint32 = data_view::Float64ExtractHighWord32(doubleValue);+      curVal += SmiFromUint32(lWord);+      curVal += SmiFromUint32(hWord);+    }+    case (n: HeapNumber): {+      curVal += 32;+      let doubleValue: float64 = Convert<float64>(n);+      if (Float64IsNaN(doubleValue)) {+        doubleValue = 1.0;+      }+      const lWord: uint32 = data_view::Float64ExtractLowWord32(doubleValue);+      const hWord: uint32 = data_view::Float64ExtractHighWord32(doubleValue);+      curVal += SmiFromUint32(lWord);+      curVal += SmiFromUint32(hWord);+    }+    case (Object): {+      curVal += 64;+    }+  }++  curVal = (curVal << 30) | ((curVal >> 1) & 0x3fffffff);+  *NativeContextSlot(ContextSlot::FUZZILLI_HASH_INDEX) = curVal;++  return Undefined;+}

该builtin 针对Smi, HeapNumber 类型做了具体的hash 处理,其他类型按统一的方式处理。成果方面并没发现v8 jit bug,不过在其他两款js engine 上检测到比较多bug。

个人看法

Fuzzjit 在检测对象方面做了更多的处理,并且是针对性的fuzz jit 的一些pass。不过,个人认为还可以更深入检测一些,并对变异策略,以及初始化corpus 获取更多信息。

 

 

原文始发于微信公众号(Exploit10Day):v8 JIT fuzz

版权声明:admin 发表于 2022年11月13日 下午3:34。
转载请注明:v8 JIT fuzz | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...