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

[逆向分析实战]三句话,让腾讯文档为我放下戒备

[复制链接]
  • TA的每日心情
    开心
    2024-7-30 00:00
  • 签到天数: 122 天

    [LV.7]常住居民III

    29

    主题

    601

    回帖

    542

    积分

    专家

    积分
    542

    油中2周年生态建设者油中3周年挑战者 lv2

    发表于 2021-10-7 20:02:58 | 显示全部楼层
    这还真有意思,似乎那些小概率的页面空白损坏啥的有了解释
    回复
    订阅

    使用道具 举报

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

    [LV.1]初来乍到

    22

    主题

    881

    回帖

    1379

    积分

    荣誉开发者

    积分
    1379

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

    发表于 2021-10-8 20:50:48 | 显示全部楼层
    李恒道 发表于 2021-10-7 16:39
    还是不太理解这种操作。
    想不通为什么要这样做
    等以后有机会再看看吧...

    我又仔细地跟了一下油猴和腾讯文档的代码,最终确定问题了,不是window指向的问题,而是油猴本身会对document.addEventListener进行劫持(可以随便打开一个页面,控制台输出document.addEventListener看看),而原有的函数存储于document.__addEventListener中,劫持操作完后调用这个__addEventListener进行绑定。这个函数的存储时机就在第一次读取document的时候(用Object.defineProperty实现的),而腾讯文档对addEventListener的劫持是在document-start之后,这就导致了油猴存储到的函数实际上是页面的原函数,等于破坏了腾讯文档对document的劫持,腾讯文档的劫持就是把所有事件都委托给一个函数处理(我怀疑单纯是为了反调试),油猴这波操作以后造成绑定在document上的原事件被暴露,不过腾讯文档劫持的是EventTarget,除了document的都没事,如果把EventTarget.prototype.addEventListener改成只读,甚至可以暴露出更多事件。
    回复

    使用道具 举报

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

    [LV.7]常住居民III

    712

    主题

    5961

    回帖

    6760

    积分

    管理员

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

    积分
    6760

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

    发表于 2021-10-8 20:58:29 | 显示全部楼层
    cxxjackie 发表于 2021-10-8 20:50
    我又仔细地跟了一下油猴和腾讯文档的代码,最终确定问题了,不是window指向的问题,而是油猴本身会对docu ...

    有点复杂,大概有一点感觉了,等我明天仔细研究一下哥哥!
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

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

    使用道具 举报

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

    [LV.7]常住居民III

    712

    主题

    5961

    回帖

    6760

    积分

    管理员

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

    积分
    6760

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

    发表于 2021-10-8 21:50:29 | 显示全部楼层
    cxxjackie 发表于 2021-10-8 20:50
    我又仔细地跟了一下油猴和腾讯文档的代码,最终确定问题了,不是window指向的问题,而是油猴本身会对docu ...

    看了大佬的话又研究了一下....
    我他妈还是不太懂这个问题。
    目前知道只有沙盒模式油猴会包装document.addEventListener
    但是我这里没看到document.__addEventListener

    还有一个问题就是
    我不知道我理解的对不对

    正常网页是
    函数调用addeventlistener。

    腾讯文档的操作是
    劫持addeventlistener

    函数调用addeventlistener
    虚假的addeventlistener做了一层包裹调用真实addeventlistener
    这时候真实addeventlistener发起注册

    但是这时候腾讯文档调用addEventListener的回调事件应该是包裹函数啊,包裹函数再调用原函数
    为什么会暴露出包裹前的调用我一直不怎么理解
    有点笨...我卡这个很久了
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

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

    使用道具 举报

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

    [LV.1]初来乍到

    22

    主题

    881

    回帖

    1379

    积分

    荣誉开发者

    积分
    1379

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

    发表于 2021-10-8 22:26:21 | 显示全部楼层
    李恒道 发表于 2021-10-8 21:50
    看了大佬的话又研究了一下....
    我他妈还是不太懂这个问题。
    目前知道只有沙盒模式油猴会包装document.addE ...

    跟他的事件委托机制有关,首先他绑事件都是直接addEventListener传递真实事件的,劫持addEventListener所做的操作就是把真实事件包装成一个通用的函数,然后再调用原addEventListener绑定,最后看到的效果就是所有事件都指向那个通用函数。而油猴也劫持了addEventListener,所做的就是保存原函数-劫持处理-调用原函数。在正常情况下,腾讯文档的劫持先于油猴,所以油猴保存到的原函数是被腾讯文档劫持过的,而document-start访问document会导致油猴先于腾讯文档劫持,此时保存的原函数就是没有被劫持的。之后页面中的js调用document.addEventListener的时候,会进入油猴的逻辑,传进来的是真实事件,再用真实的addEventListener绑定,就出现了这种歪打正着的效果。
    回复

    使用道具 举报

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

    [LV.7]常住居民III

    712

    主题

    5961

    回帖

    6760

    积分

    管理员

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

    积分
    6760

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

    发表于 2021-10-8 22:52:12 | 显示全部楼层
    cxxjackie 发表于 2021-10-8 22:26
    跟他的事件委托机制有关,首先他绑事件都是直接addEventListener传递真实事件的,劫持addEventListener所 ...

    我就是这里不懂
    按我的想法是

    腾讯文档是
    调用addeventlistener
    包装addeventlistener
    真实addeventlistener

    油猴提前注入就变成了

    调用addeventlistener
    包装addeventlistener
    油猴addeventlistener
    真实addeventlistener

    按道理油猴拿到的依然是包装的呀...
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

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

    使用道具 举报

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

    [LV.7]常住居民III

    712

    主题

    5961

    回帖

    6760

    积分

    管理员

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

    积分
    6760

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

    发表于 2021-10-8 22:52:42 | 显示全部楼层
    cxxjackie 发表于 2021-10-8 22:26
    跟他的事件委托机制有关,首先他绑事件都是直接addEventListener传递真实事件的,劫持addEventListener所 ...

    抱歉,大佬,我太笨了...
    就是他妈理解不了这,唉

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

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

    使用道具 举报

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

    [LV.1]初来乍到

    22

    主题

    881

    回帖

    1379

    积分

    荣誉开发者

    积分
    1379

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

    发表于 2021-10-8 23:16:31 | 显示全部楼层
    李恒道 发表于 2021-10-8 22:52
    我就是这里不懂
    按我的想法是

    我这样说明吧,假设原来的叫addEventListener,腾讯文档劫持的叫TaddEventListener,油猴劫持的叫YaddEventListener,页面中调用addEventListener的写法是XXX.addEventListener('copy', 原函数, ...args),注意这里无论什么情况都是传入原函数的。
    腾讯文档所做的:addEventListener.call(this, 'copy', 包装函数(原函数), ...args);
    油猴所做的:__addEventListener = document.addEventListener;
    document.addEventListener = function() {
      //...
      return __addEventListener.apply(this, arguments);
    }
    正常情况下,__addEventListener等于TaddEventListener,虽然油猴取得的是原函数,但他调用了__addEventListener后原函数就被包装了。提前劫持的情况下,__addEventListener等于addEventListener,此时调用__addEventListener是直接将原函数绑定在原addEventListener上。
    回复

    使用道具 举报

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

    [LV.7]常住居民III

    712

    主题

    5961

    回帖

    6760

    积分

    管理员

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

    积分
    6760

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

    发表于 2021-10-8 23:20:23 | 显示全部楼层
    cxxjackie 发表于 2021-10-8 22:26
    跟他的事件委托机制有关,首先他绑事件都是直接addEventListener传递真实事件的,劫持addEventListener所 ...

    我调了一下
    感觉像是如果劫持过
    腾讯文档就不会再进行劫持了
    这里是进行处理劫持的地方
    如果挂载了油猴会有一次Event的劫持
    如果不挂载会有两次的Event的劫持初始化
    不挂载的话会在第二次进行劫持addeventlistener
                                function e(t) {
                                    var e = P[t] && P[t].prototype;
                                    e && e.hasOwnProperty && e.hasOwnProperty("addEventListener") && (k(e, "addEventListener", (function(e) {
                                        return function(r, i, a, u) {
                                            try {
                                                i && i.handleEvent && (i.handleEvent = n.wrap(i.handleEvent))
                                            } catch (t) {}
                                            var c, s, f;
                                            return o && o.dom && ("EventTarget" === t || "Node" === t) && (s = n.S("click"),
                                            f = n.U(),
                                            c = function(t) {
                                                if (t) {
                                                    var e;
                                                    try {
                                                        e = t.type
                                                    } catch (t) {
                                                        return
                                                    }
                                                    return "click" === e ? s(t) : "keypress" === e ? f(t) : void 0
                                                }
                                            }
                                            ),
                                            e.call(this, r, n.wrap(i, void 0, c), a, u)
                                        }
                                    }
                                    ), r),
                                    k(e, "removeEventListener", (function(t) {
                                        return function(e, n, r, o) {
                                            try {
                                                n = n && (n.K ? n.K : n)
                                            } catch (t) {}
                                            return t.call(this, e, n, r, o)
                                        }
                                    }
                                    ), r))
                                }
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

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

    使用道具 举报

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

    [LV.7]常住居民III

    712

    主题

    5961

    回帖

    6760

    积分

    管理员

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

    积分
    6760

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

    发表于 2021-10-8 23:21:50 | 显示全部楼层
    cxxjackie 发表于 2021-10-8 23:16
    我这样说明吧,假设原来的叫addEventListener,腾讯文档劫持的叫TaddEventListener,油猴劫持的叫YaddEve ...

    基本懂了!
    哥哥牛逼!
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

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

    使用道具 举报

    发表回复

    本版积分规则

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