李恒道 发表于 2022-6-10 23:10:35

[油猴脚本开发指南]油猴的本质以及document的处理(一)

# 开篇
之前我们曾经聊过一点点的东西
这次决定开专篇聊这个问题
但是因为我也了解不深
加上油猴闭源
说实话调的很费劲
如果cxxjackie讲这些可能效果更好
斗胆今天试一下
算作抛砖引cxxjackie了
# 开始
如果我们创建一个脚本
对脚本进行debugger
可能很多人就发蒙
因为显示的代码跟我们在管理器内写的代码不一致
![图片.png](data/attachment/forum/202206/10/224654mztas8xeljesj5x8.png)
我们可以细心读一下这里的代码
window["__p__7356196.837629042"]上赋值了一个自执行的函数
传入了一个proxy的windows叫context,powers是一些信息数据,fapply根据名字是改变this指针用的
![图片.png](data/attachment/forum/202206/10/224727jt1m8878bph1w11a.png)
我们可以看一下context
![图片.png](data/attachment/forum/202206/10/224843w8z8difk9azbubkj.png)
我们可以看一下powers
![图片.png](data/attachment/forum/202206/10/224759i77gdb6yo76aog64.png)
传入之后首先创建了一个with context,设定了一下作用域
然后将我们脚本作为一个函数,传入到上方的module中
这里可以看到我们的脚本本质上就是一个js文件
而所谓的脚本头在经过油猴管理器进行解析出来数据后
实际执行只是一个简单的注释
![图片.png](data/attachment/forum/202206/10/224953mfkf8ike7hixfkok.png)
传入函数之后将我们的脚本作为module变量
然后调用fapply
![图片.png](data/attachment/forum/202206/10/225117f0505z4zk92pd5qj.png)
然后我们追到fapply里看
可以发现fapply有三个参数,e,t,r
其中e是我们传入的的第一个参数,t是第二个参数,即context,而r则是参数
![图片.png](data/attachment/forum/202206/10/225347np1z711p041ep4cp.png)
我们看看r的参数

截图如下
![图片.png](data/attachment/forum/202206/10/225535sqgiij8qo55nigiq.png)
可以看到是传入了一堆数据以及一些gm_info等信息
具体我也不清楚是啥,哈哈哈哈哈
然后调用了
(e,t,r)=>n(o, e, t, r)
n为call函数
o为apply函数
e为脚本函数
t为context
r为powers等数组信息
这里的语法为
call(apply,脚本函数,context,arguments参数信息)
但是实际不存在这种语法的,这里我也不太清楚什么愿意
但是根据实际的调试结果
可以知道
context设置为了脚本函数的this,而arguments函数则作为了参数
在这里我们可以看到
this已经变成了经过proxy代理的window
![图片.png](data/attachment/forum/202206/10/230226z3y139o34p3koaap.png)
而且函数内window也变成了包装后的window
这时候unsafewindow没有被包装
这就是unsafeWindow与window之间的区别
![图片.png](data/attachment/forum/202206/10/230333zpuc4xzz00fcc0xp.png)
那包装后的window实际都做了什么呢?

https://bbs.tampermonkey.net.cn/forum.php?mod=viewthread&tid=2461&page=1#pid27703
以及
https://bbs.tampermonkey.net.cn/thread-1080-1-1.html
都曾经涉及到过document.addeventListener的问题
我们可以研究一下到底在执行过程中发生了什么?
# document之谜
当我们在脚本写上了
console.log(document.addEventListener)
就会导致
let oldadd = EventTarget.prototype.addEventListener
的劫持不生效
那么到底发生了什么呢?
我们先思考一下document到底从哪里来的
因为这里是在脚本的作用域内
所以通常会从with内优先查找,也就是context中
![图片.png](data/attachment/forum/202206/10/230633cyr1ifqkl21foi1v.png)
context是一个proxy的windows对象
如果读取属性会触发get函数
我们可以跳进去看看
![图片.png](data/attachment/forum/202206/10/230706u2yr2noy2qejnele.png)
跳进去发现了一个属性读取的处理的函数,然后我们打上断点,等待触发document
![图片.png](data/attachment/forum/202206/10/230736a05zwdo0d8w80hqw.png)
多次的执行终于执行到了document的读取
![图片.png](data/attachment/forum/202206/10/230832nprt4k8tdh6o9fhe.png)
我们查看e可以发现是一个函数列表
![图片.png](data/attachment/forum/202206/10/230840jdmszo2t96qxnvn7.png)
然后可以看到首先获取e的列表内是否存在
如果存在,则查看是否有vlaue,有value则执行返回
有get则调用get
如果都没有则继续执行其他逻辑
document刚好是有get函数的
所以我们直接看get的部分
![图片.png](data/attachment/forum/202206/10/230853wqna5zzc96qfaq4c.png)
可以看到走到了get的处理部分
这里可以看到获取了document对象,然后执行ee函数
![图片.png](data/attachment/forum/202206/10/230954tyy1rr9v3z1r2hwx.png)
而ee函数为一个箭头函数
获取到了document分别传给了N、M、I
![图片.png](data/attachment/forum/202206/10/231106nkh7a5mxb579hb6b.png)
可以知道油猴的执行在我们脚本内读取了document进行了一定的处理~
这与我们在正常js内的执行行为是不一样的
# 结语
太长,分两篇
撒一半花




cxxjackie 发表于 2022-6-11 11:18:43

其实我也没跟的很细,当时第一反应是document上有getter,然后window.__lookupGetter__('document')直接看到了get方法,之后就从这里跟进去调试的,看到addEventListener劫持就大致理解了。至于这些混淆过的函数到底什么作用,我也没有细究哈哈{:4_109:}

李恒道 发表于 2022-6-11 11:58:35

cxxjackie 发表于 2022-6-11 11:18
其实我也没跟的很细,当时第一反应是document上有getter,然后window.__lookupGetter__('document')直接看 ...

window.__lookupGetter__('document')我打印竟然没看到get....好奇怪
我也没搞懂到底为什么要这么操作
感觉应该是为了防止网页对基础函数进行劫持?
但是为啥要走这么多处理...

李恒道 发表于 2022-6-11 12:01:20

cxxjackie 发表于 2022-6-11 11:18
其实我也没跟的很细,当时第一反应是document上有getter,然后window.__lookupGetter__('document')直接看 ...
window.__lookupGetter__('document')的问题没事了...忘了删掉none了

cxxjackie 发表于 2022-6-11 12:24:40

李恒道 发表于 2022-6-11 11:58
window.__lookupGetter__('document')我打印竟然没看到get....好奇怪
我也没搞懂到底为什么要这么操作
感 ...

就是一个沙盒概念,把window和unsafeWindow隔离开,然后部分属性和方法指向原生,部分被油猴自己托管了,从而使得对window做出的一些改动不会影响到unsafeWindow。

李恒道 发表于 2022-6-11 13:12:13

cxxjackie 发表于 2022-6-11 12:24
就是一个沙盒概念,把window和unsafeWindow隔离开,然后部分属性和方法指向原生,部分被油猴自己托管了, ...

自己托管我还理解,但是为什么还往document上赋值想不通...
感觉可能有什么特殊处理我没考虑到

cxxjackie 发表于 2022-6-11 20:49:02

李恒道 发表于 2022-6-11 13:12
自己托管我还理解,但是为什么还往document上赋值想不通...
感觉可能有什么特殊处理我没考虑到 ...

这里有作者的一些解释你可以看看,当然他这个代码经过这么多版本可能已经不太一样了:
https://github.com/Tampermonkey/tampermonkey/issues/226

李恒道 发表于 2022-6-13 14:29:18

cxxjackie 发表于 2022-6-11 20:49
这里有作者的一些解释你可以看看,当然他这个代码经过这么多版本可能已经不太一样了:
https://github.co ...
有点小感觉
但还说不清是啥
以后再看看
主要拓展我实在不怎么熟悉
也是国内资料太少了= =
搞前端每天都是感叹我国计算机还处于初级阶段
基本资料都搞不完善

页: [1]
查看完整版本: [油猴脚本开发指南]油猴的本质以及document的处理(一)