JS逆向关于网页的异步调试(实战案例)

一.前置的JS基础。

请参考我创作文章的JS基础

JS逆向爬虫需要掌握的最基础JS知识_js逆向需要什么基础-优快云博客

只能说够用,着重理解定时器,promise,ansinc/await

二.实战案例

案例一:中国五矿中国五矿集团有限公司供应链管理平台

接口:https://ec.minmetals.com.cn/open/homepage/zbs/by-lx-page

发现是载荷加密

1.搜索关键词

发现此方法有很多数,故不采用

2.hook

前置知识:JS逆向的常见hook技术(实战案例)_js逆向hook载荷里面的参数-优快云博客

(function() {
    var _stringify = JSON.stringify;
    JSON.stringify = function(ps) {
        console.log("Hook JSON.stringify ——> ", ps);
        debugger;
        return _stringify(ps);  // 不改变原有的执行逻辑 
    }
})();

轻松找的加密位置

3.搜索url关键词

发现也找到加密的位置

会发现以上几种方法很容易就找到加密的位置,一般来说这样的网站没难度,接下来讲xhr调试异步跟栈。

4.XHR 

跳到最后一个栈,发现异步

 function s(A) {  Dn(a, n, r, s, i, "next", A)  }

往异步跟栈,发现执行的位置是这里

  i.done ? e(o) : Promise.resolve(o).then(n, r)s

 干货来了!

也就是       i.done ? e(o) : Promise.resolve(o).then(n, r)

执行   function s(A) {  Dn(a, n, r, s, i, "next", A)  }

n 就相当于函数s(A)

A相当于o

下断点,重新跟栈

o为pending状态,即还没运行完毕

 

        function Dn(A, e, t, n, r, a, s) {
            try {
                var i = A[a](s)
                  , o = i.value
            } catch (g) {
                return void t(g)
            }
            i.done ? e(o) : Promise.resolve(o).then(n, r)

o从哪里来?

仔细观察,o = i.value,即o从i里出来,i从A里出来

下断点重新触发

 进去函数

 

 

方法为

(function(e) { return this._invoke(t, e) })

在进去函数

        

这个函数会出现在大多数网站上,比较难的是对这个逻辑进行混淆 ,不管三七二十一看return,看var l = d(e, t, n);

   return function(o, i) {
                        if (r === p)
                            throw new Error("Generator is already running");
                        if (r === m) {
                            if ("throw" === o)
                                throw i;
                            return z()
                        }
                        n.method = o,
                        n.arg = i;
                        while (1) {
                            var a = n.delegate;
                            if (a) {
                                var s = O(a, n);
                                if (s) {
                                    if (s === v)
                                        continue;
                                    return s
                                }
                            }
                            if ("next" === n.method)
                                n.sent = n._sent = n.arg;
                            else if ("throw" === n.method) {
                                if (r === h)
                                    throw r = m,
                                    n.arg;
                                n.dispatchException(n.arg)
                            } else
                                "return" === n.method && n.abrupt("return", n.arg);
                            r = p;
                            var l = d(e, t, n);
                            if ("normal" === l.type) {
                                if (r = n.done ? m : f,
                                l.arg === v)
                                    continue;
                                return {
                                    value: l.arg,
                                    done: n.done
                                }
                            }
                            "throw" === l.type && (r = m,
                            n.method = "throw",
                            n.arg = l.arg)
                        }
                    }

找return的位置

   return {
                                    value: l.arg,
                                    done: n.done
                                }

value为 一开始i的值,也是o的值

然后找l的值

 

       var l = d(e, t, n);下断点进去,

 

e.call(t,n)相当于函数e(e,n)进去e函数

也就是相当于       var l = d(e, t, n);d函数d是调用e函数传参e和n参数

进去函数e,控制流,这个模板也常出现,和混淆一起出现,就这个控制流,如果你调试出现错误,或者重复调试执行,可以进去很多次控制流,控制流出现的方式不一样,就这个e.call(t,n),执行好几次,可以经过不同的控制流。

A.next = 2 相当于执行case  2:

A.sent 相当于y(e)返回的值,别问为什么,这是经验!!!

如果你重复调试,会出现以下错误结果,这玩意没有用

 

 这个是继续调试的结果

 

                return c.a.wrap((function(A) {
                    while (1)
                        switch (A.prev = A.next) {
                        case 0:
                            return A.next = 2,
                            y(e);
                        case 2:
                            return t = A.sent,
                            A.abrupt("return", Xn.post("/open/homepage/zbs/by-lx-page ", {
                                param: t
                            }));
                        case 4:
                        case "end":
                            return A.stop()
                        }
                }

往y下断点,跟过去,发现以往的断点重新执行,断点是可以重复执行的


再进去p

注意这个

 发现流程跟以上一样

要重新走一遍

 

这个第二次e调用返回的值就是o = i.value,进去e方法,进去又一个控制流结果显而易见了

加密的位置显而易见了,非对称加密

值得一提这网站需要先请求一次获取密钥

 三.总结

这个网站可以说是异步的入门,非常简单,本案例只是梳理一些异步的流程,以后实战中不需要一步一步跟,找好关键断点,比如  var l = d(e, t, n),A.sent 相当于y(e)返回的值,打这个几个断点,调试即可。但是以后会跟混淆结合,所以还是得好好实战。

干货总结:

1.var l = d(e, t, n)找.call(t,n)可以要进去很多遍

2.A.sent 相当于y(e)返回的值

3.A.next = 2相对于跳转case 2

4.可以适当搜索url关键词

5. i.done ? e(o) : Promise.resolve(o).then(n, r)

下一个栈是执行  这个函数

function s(A) {  Dn(a, n, r, s, i, "next", A)  }

n 就相当于函数s(A),A相当于o

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值