封装伪装isTrust点击,遇到得神奇的问题
事情是这样的:之前在论坛看到有个网页点击大挑战,破解脚本触发click事件isTrust为false的问题
@cxxjackie 大佬提供思路利用劫持addEventListener,再用Proxy伪装
于是我尝试了下在实际项目里面封装并使用,但是遇到了一个让我匪夷所思的问题
```
const arrClickDoms = [];
const fakeClickEvent = {
isTrusted: true,
pointerType: "mouse",
};
const ael = EventTarget.prototype.addEventListener;
EventTarget.prototype.addEventListener = function () {
if (arguments === "click") {
if (arrClickDoms.includes(this)) {
const fn = arguments;
arguments = (e) =>
fn.call(
this,
new Proxy(e, {
get: (target, property, receiver) =>
property in fakeClickEvent
? fakeClickEvent
: Reflect.get(target, property, receiver),
})
);
}
}
return ael.apply(this, arguments);
};
//下一次点击事件 随机1-3秒
var nextClick = function (
selector,
{ minNum = 1000, maxNum = 3000 } = {}
) {
return new Promise((reslove, reject) => {
setTimeout(async () => {
try {
const = await $.get(selector);
if (!arrClickDoms.includes(btn)) {
arrClickDoms.push(btn);
}
btn.click();
arrClickDoms.splice(arrClickDoms.indexOf(btn), 1);
reslove(btn);
} catch (err) {
reject(err);
}
}, cb_randomNum(minNum, maxNum));
});
};
```
正常来说,有以下几个步骤:
1先劫持 addEventListener ,
2调用nextClick 筛选btn元素,将其加入arrClickDoms数组
3 触发btn的click
4 进入劫持后的 addEddEventListener 回调方法 判断btn是否在arrClickDoms中,如果存在,则返回伪造Proxy,否则直接正常返回
如果是在小demo中,以上封装是没问题,
但是在实际复杂项目场景的时候,却遇到很奇怪的问题
在没有触发 第2步和第3步的时候,直接先执行了第1步和第4步, 再调用click的时候,却不进入 addEddEventListener 回调。
甚至不调用nextClick,也会执行第1步和第4步,
这是反扒机制还是啥的,感觉有点颠覆了我对js的理解机制 最好是提供具体的脚本和网站来进行测试
不然很难派查发生原因的 本帖最后由 cabin 于 2023-3-29 19:39 编辑
李恒道 发表于 2023-3-29 16:09
最好是提供具体的脚本和网站来进行测试
不然很难派查发生原因的
基本所有的用vue框架生成的网站,都会 出现这种情况
这个应是涉及js底层的事件机制
我只是想象不出为啥会提前触发 addEventListener 的回调事件,
再次点击click 却不会触发 addEventListener 的回调,
但是会正常触发他自己的业务方法这太反常识了
我是想知道这种模式的理论可能在哪里
我猜测是 dom 事件机制的冒泡和capture 有影响,其他点击事件把劫持的 addEventListener 的回调事件 给提前执行了
或者有可能是业务点击按钮执行了 e.stopImmedatePropogration,导致事件中断 本帖最后由 cabin 于 2023-3-29 20:07 编辑
好像是因为很多网站对addEventListener做了特殊处理,把回调 function给删了
const ael = EventTarget.prototype.addEventListener;
EventTarget.prototype.addEventListener = function () {
console.log(arguments)
return ael.apply(this, arguments);
};
这个是简单demo的arguments
https://wxay-product-pro.oss-cn-shanghai.aliyuncs.com/demo/1.png
这个是Vue项目的arguments,可以看到所有的第二个参数都被扣走了
https://wxay-product-pro.oss-cn-shanghai.aliyuncs.com/demo/2.png
应该是框架 vue或者react把 addEventListener 二次修改了,劫持addEventListener的思路估计仅限于demo
这种情况还怎么绕过isTrusted,源码是混淆后的,没法看懂
没太看懂你的描述,猜测是事件委托的问题,一些框架会将多个元素的事件委托到一个父级元素上,然后根据e.target判断实际触发的元素来调用对应函数。你说的先触发可能是捕获阶段的事件(useCapture: true),因为捕获先于冒泡,父级会比子级先收到事件,这种的应该把监听元素放到正确的父级上才行。
删掉回调的情况我没碰见过,这种可能专门针对性的做了反劫持,得从源码入手。如果真是二次劫持的情况,说明页面劫持发生在你脚本劫持之前,应确保脚本执行于document-start。
如果你是想做一个通用的库来过验证,建议还是放弃吧,实际情况千奇百怪,而且有很多方法来反制,要做到完全通用是不现实的。 cxxjackie 发表于 2023-3-29 20:55
没太看懂你的描述,猜测是事件委托的问题,一些框架会将多个元素的事件委托到一个父级元素上,然后根据e.ta ...
是啊,我就是想按你以前发得那个思路封装库做全局伪装点击劫持,好像行不通,有一个原因应该就是我上面图发的,vue或者react框架层面会把 addEventListenner 二次修改,把arguments 事件回调方法直接删了,挂载到他们自己框架事件机制上,那劫持修改的回调事件自然也不会触发了,自然也谈不上返回伪装的proxy了
这种该怎么破解啊。。。。。。。。。。。。。。。{:4_115:} cabin 发表于 2023-3-30 10:45
是啊,我就是想按你以前发得那个思路封装库做全局伪装点击劫持,好像行不通,有一个原因应该就是我上面图 ...
有没有测试链接?还有你代码是怎么写的?按理来说arguments应该是一个数组,但你图中展示的却是一个对象,这点很奇怪,被删掉的参数至少也应该显示为undefined才对,感觉像是代码的问题。
另外react框架有特殊的处理办法,可以直接定位到事件函数,不需要劫持addEventListener,在这篇文章里有提到:
https://bbs.tampermonkey.net.cn/thread-1250-1-1.html
页:
[1]