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

【油猴开发指南】关于Vue3的劫持处理初步方案

[复制链接]
  • TA的每日心情
    慵懒
    2024-10-28 07:07
  • 签到天数: 193 天

    [LV.7]常住居民III

    710

    主题

    5894

    回帖

    6713

    积分

    管理员

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

    积分
    6713

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

    发表于 2024-10-16 17:33:17 | 显示全部楼层 | 阅读模式

    测试网站https://www.bilibili.com/

    首先可以找到存在__vue_app__属性
    查看源码可以知道在 mount 函数中的

    mount(rootContainer, isHydrate, namespace) {
        if (!isMounted) {
        //省略
        rootContainer.__vue_app__ = app;
        return getComponentPublicInstance(vnode.component);
        }
    }

    还有一个_vnode 属性来自于mountElement函数的

    def(el, "__vnode", vnode, true);

    但是我们想在想进行全局劫持,势必要混入自己的代码,Vue3调用是createApp(rootComponent).mount(dom)
    rootContainer.__vue_app__ = app;是在挂接之后才能出现的
    我们要劫持势必要在初始化时劫持,于是可以顺着createApp找找思路

    function createApp(rootComponent, rootProps = null) {
            if (!isFunction(rootComponent)) {
              rootComponent = extend({}, rootComponent);
            }
             //省略
            return app;
    };

    其中可以看到初始化的时候有判断isFunction编译之后的会通过sfc将vue模板文件编译成对象,所以大概率会走到下面的extend函数,那我们看看extend是怎么实现的const extend = Object.assign;
    可以发现这部分有利用的机会!

    const assign = Object.assign
    let isRun = false
    Object.assign = function (...args) {
        if (args.length==2&&args[1]?.render !== undefined && !isRun) {
            let b=args[1]
            const originRender = b.render
            b.render = function (...args) {
                console.log("被执行了", args)
                return originRender.call(this, ...args)
            }
            isRun = true
        }
        return assign.call(this, ...args)
    }

    这里我利用了劫持assign可以得到根组件的render函数,控制render是因为渲染模板相对其他的属性来说可能对数据的暴露拥有更多的访问机会

    但是我们该怎么混入实例呢?根据逆向最后找到了renderComponentRoot函数的vnode.shapeFlag & 4分支,render模板上级调用如下

                render.call(
                  thisProxy,
                  proxyToUse,
                  renderCache,
                  true ? shallowReadonly(props) : props,
                  setupState,
                  data,
                  ctx
                )

    可以看到最后一个就是ctx!
    那我们就可以通过render最后一个参数找到appContext,根据appContext再对全局混入数据!
    理论建立完毕了!

    // ==UserScript==
    // @name         Vue3 Mixin Inject
    // @namespace    https://bbs.tampermonkey.net.cn/
    // @version      0.1.0
    // @description  try to take over the world!
    // @author       You
    // @match        https://www.bilibili.com/*
    // @run-at       document-start
    // @grant unsafeWindow
    // ==/UserScript==
    
    const assign = Object.assign
    let isRun = false
    Object.assign = function (...args) {
        if (args.length==2&&args[1]?.render !== undefined && !isRun) {
            let b=args[1]
            const originRender = b.render
            let isInject=false
            b.render = function (...args) {
                if (!isInject) {
                    args[5]['_'].appContext.mixins.push({
                        mounted() {
                            console.log("被创建了,实例数据",this.$props)
                        }
                    })
                    isInject = true
                }
                console.log("被执行了", args)
                return originRender.call(this, ...args)
            }
            isRun = true
        }
        return assign.call(this, ...args)
    }

    然后测试一下9e16664eacf77757d0fb2ea920061f7a.jpeg

    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

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

    该用户从未签到

    2

    主题

    17

    回帖

    16

    积分

    助理工程师

    积分
    16

    油中2周年新人报道

    发表于 2024-10-16 17:46:50 | 显示全部楼层
    插眼,有空研究
    回复

    使用道具 举报

    该用户从未签到

    1

    主题

    4

    回帖

    9

    积分

    助理工程师

    积分
    9
    发表于 2024-10-17 10:55:07 | 显示全部楼层
    gg牛哇,学习了学习了
    回复

    使用道具 举报

  • TA的每日心情
    开心
    10 小时前
  • 签到天数: 33 天

    [LV.5]常住居民I

    5

    主题

    20

    回帖

    50

    积分

    初级工程师

    积分
    50

    油中3周年挑战者 lv2

    发表于 5 天前 | 显示全部楼层
    新版本的vue 打包编译后根组件上不存在render方法
    回复

    使用道具 举报

  • TA的每日心情
    开心
    10 小时前
  • 签到天数: 33 天

    [LV.5]常住居民I

    5

    主题

    20

    回帖

    50

    积分

    初级工程师

    积分
    50

    油中3周年挑战者 lv2

    发表于 5 天前 | 显示全部楼层
    道哥有没有更好的方法
    回复

    使用道具 举报

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

    [LV.7]常住居民III

    710

    主题

    5894

    回帖

    6713

    积分

    管理员

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

    积分
    6713

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

    发表于 4 天前 | 显示全部楼层
    krystal 发表于 2024-11-3 16:32
    新版本的vue 打包编译后根组件上不存在render方法

    哥哥可以来个测试地址看一眼
    还有一种use劫持方法
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

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

    使用道具 举报

  • TA的每日心情
    开心
    10 小时前
  • 签到天数: 33 天

    [LV.5]常住居民I

    5

    主题

    20

    回帖

    50

    积分

    初级工程师

    积分
    50

    油中3周年挑战者 lv2

    发表于 4 天前 | 显示全部楼层
    李恒道 发表于 2024-11-4 09:20
    哥哥可以来个测试地址看一眼
    还有一种use劫持方法

    http://n1.tanyu.fun:7869/#/  两只方式都不行,遇到这种没有use的也不行
    回复

    使用道具 举报

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

    [LV.7]常住居民III

    710

    主题

    5894

    回帖

    6713

    积分

    管理员

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

    积分
    6713

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

    发表于 4 天前 | 显示全部楼层
    krystal 发表于 2024-11-4 10:49
    http://n1.tanyu.fun:7869/#/  两只方式都不行,遇到这种没有use的也不行

    这个页面也是同理的
    只是render属于setup返回
    还是会走assign,因为最后是以返回的render模板作为读取项
    可以对setup做劫持返回劫持render
    再mixin
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

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

    使用道具 举报

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

    [LV.7]常住居民III

    710

    主题

    5894

    回帖

    6713

    积分

    管理员

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

    积分
    6713

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

    发表于 4 天前 | 显示全部楼层

    krystal 发表于 2024-11-4 10:49

    http://n1.tanyu.fun:7869/#/ 两只方式都不行,遇到这种没有use的也不行

    image.png
    调试可以以weakSet作为基础API的特征
    可以直接追到rootComponent的assign的位置

    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

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

    使用道具 举报

  • TA的每日心情
    开心
    10 小时前
  • 签到天数: 33 天

    [LV.5]常住居民I

    5

    主题

    20

    回帖

    50

    积分

    初级工程师

    积分
    50

    油中3周年挑战者 lv2

    发表于 4 天前 | 显示全部楼层
    李恒道 发表于 2024-11-4 12:34
    这个页面也是同理的
    只是render属于setup返回
    还是会走assign,因为最后是以返回的render模板作为读取项

    学到了
    回复

    使用道具 举报

    发表回复

    本版积分规则

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