上一主题 下一主题
ScriptCat,新一代的脚本管理器脚本站,与全世界分享你的用户脚本油猴脚本开发指南教程目录
返回列表 发新帖

【高难度】如何将脚本注入到DedicatedWorkerGlobalScope作用域中?

[复制链接]
  • TA的每日心情

    2024-4-3 16:40
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    1

    主题

    6

    回帖

    7

    积分

    助理工程师

    积分
    7
    发表于 2024-4-3 16:39:00 | 显示全部楼层 | 阅读模式
    悬赏40油猫币未解决

    本帖最后由 qq1063823095 于 2024-4-4 00:32 编辑

    本帖最后由 qq1063823095 于 2024-4-4 00:25 编辑

    需求:
    想劫持其中一个叫做“d365”的请求上的参数,但是调试了半天发现,好家伙,这个请求不是从主页上面发起的请求,是一个叫做“YCIy5nf-CXdG.js”文件中发起的。

    更加离谱的是,这个请求发起的地方,不在window的作用域,而是叫一个DedicatedWorkerGlobalScope作用域

    脚本中引入了ajaxhook,首页的请求都可以拦截到,就是"d365"这个请求拦截不到

    bing查了很久,加上GPT问了半天,没搞懂Worker这个东西,有知道的大佬破局吗?

    脚本注入的网页地址为 Azure的存储账户中的存储浏览器(如图)(隐私信息已打码)
    image.png

    附上调试过程(隐私信息已打码):
    image.png

    附上脚本(部分)(代码中使用了 grant none 让其注入到全局window):

    // ==UserScript==
    // @match        *://portal.azure.cn/*
    // @match        https://hosting.azureportal.chinacloudapi.cn/*
    // @match        https://b2ccrminterfacesaprd.blob.core.chinacloudapi.cn/*
    // @require      https://unpkg.com/ajax-hook@3.0.3/dist/ajaxhook.js
    // @grant        GM_cookie
    // @grant        none
    // @connect      chinacloudsites.cn
    // @connect      portal.azure.cn
    
    // ==/UserScript==
    (function () {
      // 'use strict';
      HookFetch();
      window.aaa = 111;
    
      function HookFetch() {
        ah.proxy({
          //请求发起前进入
          onRequest: (config, handler) => {
            console.log(config.url);
            handler.next(config);
          },
          //请求发生错误时进入,比如超时;注意,不包括http状态码错误,如404仍然会认为请求成功
          onError: (err, handler) => {
            console.log(err.type);
            handler.next(err);
          },
          //请求成功后进入
          onResponse: (response, handler) => {
            // console.log(response.response)
            handler.next(response);
          },
        });
      }
    })();
    

    2024-4-4 00:18:39 更新(补充实例代码,就是模拟了原网页的一个demo)

    index.html

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
        <script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.8.0/jquery-1.8.0.js"></script>
      </head>
      <body></body>
    </html>
    <script>
      // 实例化一个Web Worker
      var worker = new Worker("./worker.js");
      worker.postMessage({
        url: "http://example.com/api",
        method: "GET",
        headers: {
          "Content-Type": "application/json",
        },
      });
    
      // 这里发起一次ajax请求
      $.ajax({
        url: "/?name=index.html",
        type: "Get",
      });
    </script>
    

    worker.js

    self.onmessage = function (event) {
        // 这里发起一次http请求
        var xhr = new XMLHttpRequest();
        xhr.open('GET', '/?name=worker', true);
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && xhr.status === 200) {
                self.postMessage(xhr.responseText);
            }
        };
        xhr.send();
    };

    脚本(和原来没变化,只加入了run-at)

    // ==UserScript==
    // @name         hook web worker
    // @namespace    http://tampermonkey.net/
    // @version      2024-04-03
    // @description  try to take over the world!
    // @author       You
    // @match        *://*/*
    // @require      https://unpkg.com/ajax-hook@3.0.3/dist/ajaxhook.js
    // @grant        GM_cookie
    // @grant        none
    // @connect      chinacloudsites.cn
    // @connect      portal.azure.cn
    // @run-at       document-start
    
    // ==/UserScript==
    (function () {
      // 'use strict';
      HookFetch();
      window.aaa = 111;
    
      function HookFetch() {
        ah.proxy({
          //请求发起前进入
          onRequest: (config, handler) => {
            console.log(config.url);
            handler.next(config);
          },
          //请求发生错误时进入,比如超时;注意,不包括http状态码错误,如404仍然会认为请求成功
          onError: (err, handler) => {
            console.log(err.type);
            handler.next(err);
          },
          //请求成功后进入
          onResponse: (response, handler) => {
            // console.log(response.response)
            handler.next(response);
          },
        });
      }
    })();

    运行结果
    image.png

    通过上述运行结果看到,还是只有index.html注入成功了,而worker.js中没有注入成功(如果worker.js也注入了的话,控制台会打印name=worker这个请求)

    demo和原网页稍微有一点区别的地方在于,Azure中的worker有window对象,demo没有(只有self),不过对象类型是一样的(通过打印self可以看到是一样的)

  • TA的每日心情
    慵懒
    2024-10-28 07:07
  • 签到天数: 193 天

    [LV.7]常住居民III

    712

    主题

    5999

    回帖

    6784

    积分

    管理员

    非物质文化遗产社会摇传承人

    积分
    6784

    荣誉开发者喜迎中秋油中2周年生态建设者

    发表于 2024-4-3 20:04:15 | 显示全部楼层
    没账号进不去

    不过感觉你这个可能更像没加run-at导致没提前注入上
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

    入驻了爱发电https://afdian.net/a/lihengdao666
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
    回复

    使用道具 举报

  • TA的每日心情

    2024-4-3 16:40
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    1

    主题

    6

    回帖

    7

    积分

    助理工程师

    积分
    7
    发表于 2024-4-3 23:07:11 | 显示全部楼层
    李恒道 发表于 2024-4-3 20:04
    没账号进不去

    不过感觉你这个可能更像没加run-at导致没提前注入上

    注入到首页了,也有相应的拦截数据,只不过在“YCIy5nf-CXdG.js”文件的“DedicatedWorkerGlobalScope”作用域下没有注入成功,并且打印了对应window,和全局的window不一样,这里就涉及到了Worker的东西了(我就不太清楚了)
    回复

    使用道具 举报

  • TA的每日心情

    2024-4-3 16:40
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    1

    主题

    6

    回帖

    7

    积分

    助理工程师

    积分
    7
    发表于 2024-4-4 00:54:33 | 显示全部楼层
    盲猜一下应该要hook原生的Worker函数,然后通过注入特定代码来实现劫持,不过检索了一下许多hook库,貌似都没有hook Worker相关的功能
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    2024-10-28 07:07
  • 签到天数: 193 天

    [LV.7]常住居民III

    712

    主题

    5999

    回帖

    6784

    积分

    管理员

    非物质文化遗产社会摇传承人

    积分
    6784

    荣誉开发者喜迎中秋油中2周年生态建设者

    发表于 2024-4-4 01:04:23 | 显示全部楼层

    改了下例子,目前Worker封闭性还是比较强的
    我利用Worker初始化自己的Js然后通过ImportScript实现的共享作用域
    不过由于破坏了原有的引用,所以XHR在你的例子里会失效
    但是看你网页截图的代码也是blob
    所以如果改掉例子应该是可以实现hook的

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
        <script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.8.0/jquery-1.8.0.js"></script>
      </head>
      <body></body>
    </html>
    <script>
      const hookCode = `self.onmessage = function (event) {
        const xhrOpen = XMLHttpRequest.prototype.open;
       XMLHttpRequest.prototype.open = function () {
          console.log('hook success',this);
          return xhrOpen.apply(this, arguments);
       };
      if (event?.data?.init) {
        importScripts(event.data.url);
      }
    };
    `;
      const acturalCode = `self.onmessage = function (event) {
      var xhr = new XMLHttpRequest();
      xhr.open("GET", "http://example.com/api", true);
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4 && xhr.status === 200) {
          self.postMessage(xhr.responseText);
        }
      };
      xhr.send();
    };
    
    `;
      const blob = new Blob([hookCode], { type: "application/javascript" });
      const acturaclBlob = new Blob([acturalCode], {
        type: "application/javascript",
      });
      const originWorker = Worker;
      window.Worker = function (url) {
        const eneity = new originWorker(URL.createObjectURL(blob));
        eneity.postMessage({
          init: true,
          url: url,
        });
        return eneity;
      };
      // 实例化一个Web Worker
      var worker = new Worker(URL.createObjectURL(acturaclBlob));
      worker.postMessage({
        url: "http://example.com/api",
        method: "GET",
        headers: {
          "Content-Type": "application/json",
        },
      });
    
      // 这里发起一次ajax请求
      $.ajax({
        url: "/?name=index.html",
        type: "Get",
      });
    </script>
    
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

    入驻了爱发电https://afdian.net/a/lihengdao666
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    2022-3-8 11:41
  • 签到天数: 2 天

    [LV.1]初来乍到

    22

    主题

    883

    回帖

    1381

    积分

    荣誉开发者

    积分
    1381

    荣誉开发者卓越贡献油中2周年生态建设者油中3周年挑战者 lv2

    发表于 2024-4-4 23:47:58 | 显示全部楼层
    劫持Worker,读取文件内容为字符串,再通过拼接/替换字符串来实现请求的劫持,然后生成blob,再URL.createObjectURL生成一个blob链接,最后调用原Worker来实例化。实现起来还挺复杂的,可能需要用到同步xhr来读取文件(因为实例化过程是同步的)。
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    17 小时前
  • 签到天数: 822 天

    [LV.10]以坛为家III

    31

    主题

    553

    回帖

    1564

    积分

    荣誉开发者

    积分
    1564

    荣誉开发者新人进步奖油中2周年生态建设者新人报道挑战者 lv2油中3周年喜迎中秋

    发表于 2024-4-5 00:52:20 | 显示全部楼层
    回复

    使用道具 举报

    发表回复

    本版积分规则

    快速回复 返回顶部 返回列表