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

[油猴脚本开发指南]XHR劫持的第二种格式

[复制链接]

189

主题

1472

帖子

763

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
763
发表于 2021-11-1 09:45:39 | 显示全部楼层 | 阅读模式

前言

本文来自cxxjackie的代码,进行剖析

来源为

https://bbs.tampermonkey.net.cn/forum.php?mod=viewthread&tid=1062&extra=&page=1

开始

其实之前proxy劫持还是相对复杂的,这节课根据cxxjackie的代码我们抄出来一个更简单的劫持方案。

我们先输出一下xhr看看

图片.png

可以看到xhr的response和responseText等在原型链prototype上

图片.png

并且这两个属性都是只有get没有set,代表我们只可以获取他而不可以设置他的内容

所以我们书写代码如下

    const xhrOpen = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function() {
      if (arguments[1] == '/1.xml') {
        const xhr = this;
        const getter = Object.getOwnPropertyDescriptor(XMLHttpRequest.prototype, 'response').get;
        Object.defineProperty(xhr, 'responseText', {
          get: () => {
            let result = getter.call(xhr);
            //这里可以修改result
            return result+'6648848';
          }
        });
      }
      return xhrOpen.apply(xhr, arguments);
    };

首先我们对xhr的open函数进行劫持

const xhrOpen = XMLHttpRequest.prototype.open;

open是初始化xhr的内容,send是发送数据,这里我们在初始化内容的时候进行劫持。(我们其实可以在任何一个我们满足劫持需求的地方进行劫持)

我们对地址进行判断,如果需要我们进行劫持,则进入劫持

        const xhr = this;
        const getter = Object.getOwnPropertyDescriptor(XMLHttpRequest.prototype, 'response').get;

这里保存了this到xhr变量,方便接下来的操作

然后获取response的操作符,如果你想要劫持responseText就需要改为responseText

getOwnPropertyDescriptor获取的是一个对象上属性的相关的描述符

可以拿到get set等等。

图片.png

获取到了get描述符我们就可以开始劫持了

        Object.defineProperty(xhr, 'response', {
          get: () => {
            let result = getter.call(xhr);
            //这里可以修改result
            return result+'6648848';
          }
        });

这里对xhr的response属性做了一个defineProperty,当触发xhr.response的时候会访问对应的get,而get调用我们之前获取的getter函数,注意修改this指向,获取原返回内容,进行一定的修改,返回新的修改内容

为什么设置到xhr上而不是xhr的原型链上

因为这样可以形成对某一个xhr进行劫持,如果设置到原型链上相当于对所有的xhr进行了一次劫持,如果你的劫持get内有大量的回调代码会严重拖慢运行的速度

为什么我没有对原型链的response进行劫持,却成功劫持了?

因为查找response的属性的时候是按顺序查找的,首先在xhr上查找是否有response,然后在xhr的proto也就是构造函数的prototype上查找response属性,如果找不到就一层一层往上找,这里我们进行了劫持之后会直接在xhr自身找到,甚至不会找到xhr的proto上的response。

代码

那么我们最后回忆一下代码

    const xhrOpen = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function() {
      if (arguments[1] == url) {
        const xhr = this;
        const getter = Object.getOwnPropertyDescriptor(XMLHttpRequest.prototype, 'response').get;
        Object.defineProperty(xhr, 'response', {
          get: () => {
            let result = getter.call(xhr);
            //这里可以修改result
            return result;
          }
        });
      }
      return xhrOpen.apply(xhr, arguments);
    };

结语

撒花

混的人。

99

主题

1034

帖子

759

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
759

猫咪币纪念章热心会员活跃会员突出贡献三好学生中秋纪念章国庆纪念章

发表于 2021-11-1 11:05:39 | 显示全部楼层
cxxjackie大佬快给你剖完了
上不慕古,下不肖俗。为疏为懒,不敢为狂。为拙为愚,不敢为恶。/ 微信公众号:一之哥哥
回复

使用道具 举报

189

主题

1472

帖子

763

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
763
发表于 2021-11-1 11:18:47 | 显示全部楼层
王一之 发表于 2021-11-1 11:05
cxxjackie大佬快给你剖完了

cxxjackie大佬天天被我骗代码
混的人。
回复

使用道具 举报

14

主题

251

帖子

2266

积分

开发者

Rank: 6Rank: 6

积分
2266

猫咪币纪念章活跃会员三好学生热心会员中秋纪念章国庆纪念章

发表于 2021-11-1 11:21:49 | 显示全部楼层
加油加油,努力学习
布[
回复

使用道具 举报

8

主题

173

帖子

254

积分

开发者

Rank: 6Rank: 6

积分
254

活跃会员热心会员突出贡献三好学生猫咪币纪念章中秋纪念章国庆纪念章

发表于 2021-11-1 11:37:32 | 显示全部楼层
cxxjackie小弟快给你剖完了
回复

使用道具 举报

5

主题

120

帖子

48

积分

注册会员

Rank: 2

积分
48

中秋纪念章猫咪币纪念章活跃会员热心会员三好学生

发表于 2021-11-1 13:21:31 | 显示全部楼层
此代码多一字显肥,少一字显瘦,妍姿妖艳,心旌神摇
回复

使用道具 举报

189

主题

1472

帖子

763

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
763
发表于 2021-11-1 14:53:15 | 显示全部楼层
cxxjackie 发表于 2021-11-1 11:37
cxxjackie小弟快给你剖完了

快!掏代码!我要剖!呜呜呜呜
混的人。
回复

使用道具 举报

189

主题

1472

帖子

763

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
763
发表于 2021-11-1 16:14:37 | 显示全部楼层
脚本体验师001 发表于 2021-11-1 13:21
此代码多一字显肥,少一字显瘦,妍姿妖艳,心旌神摇

安排!
混的人。
回复

使用道具 举报

发表回复

本版积分规则

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