1
头图
Pay attention to WeChat public account: K brother crawler, QQ exchange group: 808574309, continue to share advanced crawler, JS/Android reverse engineering and other technical dry goods!

statement

All the content in this article is for learning and communication only. The captured content, sensitive URLs, and data interfaces have been desensitized, and it is strictly forbidden to use them for commercial or illegal purposes. Otherwise, all consequences arising therefrom will have nothing to do with the author. Infringement, please contact me to delete it immediately!

Reverse target

  • Target: KW music search parameters
  • Homepage: aHR0cDovL3d3dy5rdXdvLmNuLw==
  • Interface: aHR0cDovL3d3dy5rdXdvLmNuL2FwaS93d3cvc2VhcmNoL3NlYXJjaE11c2ljQnlrZXlXb3Jk
  • Reverse parameters: Query String Parameters: reqId: 15c31270-32e8-11ec-a637-0b779ce474e4

The reverse goal of this time is to search for a parameter reqId of the interface. Note that this parameter is not necessary. The main purpose of this article is to introduce separate webpack, that is, how to rewrite webpack when the module loader and each module are not in the same JS file , And how to rewrite webpack through non-IIFE (immediately call function expressions, self-executing functions). This article is an extension of previous articles:

Reverse process

Packet capture analysis

When you come to the search page, you can search for a song. The interface class is aHR0cDovL3d3dy5rdXdvLmNuL2FwaS93d3cvc2VhcmNoL3NlYXJjaE11c2ljQnlrZXlXb3Jk , and there is a reqId encryption parameter in the GET request, Query String Parameters, as shown in the following figure:

01.png

Parameter reverse

Search reqId directly and globally, there are only 4 results in the app.4eedc3a.js file, as shown in the following figure:

02.png

Obviously t.data.reqId = r and t.data.reqId = n is more suspicious, try planted breakpoints in both places, you will find under the search again to refresh the page or not broken, we look at these two places, r and n definition statement var r = c()(); , var n = c()(); all by c()() get, we try planted breakpoints in both locations, re-search, can be found at successful off and c()() value is the reqId value, as shown below:

03.png

Continue to look up to see how c comes from, you can see the logic:

var l = n(109)
  , c = n.n(l)
var r = c()();

Buried breakpoints for debugging, you can see that n is actually a method in runtime.d5e801d.js, as shown in the following figure:

04.png

Observing this function d(n){} , the return statement uses the .call grammar, and there is also the exports keyword. According to the introduction of K brother's previous articles, it is easy to know that this is a webpack module loader, then e contains all modules, as shown in the figure below Show:

05.png

Let's take a look at n(109) , click to enter this function, you can find that it is separated from the front and back functions by a comma, and you can see the ] at the end of the file, which means that all the modules of webpack are encapsulated in an array, then this 109 It means that this function is the 109th function, as shown in the figure below:

06.png

Look at the c = n.n(l) statement again, select n.n click and you will find that it also comes to the module loader. Then when you deduct the code, d.n .

07.png

So to summarize the logic, the statement l = n(109) uses the module loader to load the 109th function, and the return value is assigned to l , and then c = n.n(l) calls the module loader's n method, the return value is assigned to c , and then the value of c()() NS.

webpack rewrite

In the previous articles of Brother K, we have introduced the rewriting method of webpack. This case, Brother K will introduce three methods, which can also be divided into two, one is the IIFE (immediate call function expression, self-executing function) method , It's just that the parameters passed, that is, the format of the module, are divided into two types: array and dictionary. The second is a non-IIFE method. The more conventional rewriting method seems to be easier to understand. PS: The complete code is not easy to see the entire structure clearly. You can use tools such as VSCode to fold all the code, and you can clearly see the different structure of the code under different rewriting methods.

Through the previous analysis, we know that d.n d.d and d.o are also used for actual debugging, so they must be deducted together.

In the module part, we already know that module 109 is called, and observing the code of 109, we find that modules 202 and 203 are also called, so we need to copy all three modules. When copying, we first breakpoint and run to module loading Because e stores all the modules, we can directly call e[109] , e[202] , e[203] in the Console to output, and then click to jump to the position of the original function, and then copy it down, as shown in the following figure:

08.png

IIFE transfer array

The rewriting method of IIFE has been introduced in the previous articles of Brother K. Similarly, we first define a global variable, such as var kuwo; , and then export the module loader kuwo = d , and then combine the three modules of 109, 202, and 203 into an array Pass in IIFE, then here is no longer the 109th, 202, and 203 modules, but the 0th, 1st and 2nd modules, so when calling the module, the corresponding 109, 202, 203 should be changed to 0, 1 , 2. The complete code is as follows:

var kuwo;

!function (e){
    var t = {};

    function d(n) {
        if (t[n]) return t[n].exports;
        var r = t[n] = {
            i: n,
            l: !1,
            exports: {}
        };
        return e[n].call(r.exports, r, r.exports, d),
            r.l = !0,
            r.exports
    }

    d.n = function (e) {
        var n = e && e.__esModule ?
            function () {
                return e.default
            } :
            function () {
                return e
            };
        return d.d(n, "a", n),
            n
    },
    d.d = function (e, n, r) {
            d.o(e, n) || Object.defineProperty(e, n, {
                enumerable: !0,
                get: r
            })
        },
    d.o = function (object, e) {
            return Object.prototype.hasOwnProperty.call(object, e)
        }

    kuwo = d
}([
    function (t, e, n) {
        var r, o, l = n(1),
            c = n(2),
            h = 0,
            d = 0;
        t.exports = function (t, e, n) {
            var i = e && n || 0,
                b = e || [],
                f = (t = t || {}).node || r,
                v = void 0 !== t.clockseq ? t.clockseq : o;
            if (null == f || null == v) {
                var m = l();
                null == f && (f = r = [1 | m[0], m[1], m[2], m[3], m[4], m[5]]),
                null == v && (v = o = 16383 & (m[6] << 8 | m[7]))
            }
            var y = void 0 !== t.msecs ? t.msecs : (new Date).getTime(),
                w = void 0 !== t.nsecs ? t.nsecs : d + 1,
                dt = y - h + (w - d) / 1e4;
            if (dt < 0 && void 0 === t.clockseq && (v = v + 1 & 16383), (dt < 0 || y > h) && void 0 === t.nsecs && (w = 0), w >= 1e4) throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");
            h = y,
                d = w,
                o = v;
            var x = (1e4 * (268435455 & (y += 122192928e5)) + w) % 4294967296;
            b[i++] = x >>> 24 & 255,
                b[i++] = x >>> 16 & 255,
                b[i++] = x >>> 8 & 255,
                b[i++] = 255 & x;
            var _ = y / 4294967296 * 1e4 & 268435455;
            b[i++] = _ >>> 8 & 255,
                b[i++] = 255 & _,
                b[i++] = _ >>> 24 & 15 | 16,
                b[i++] = _ >>> 16 & 255,
                b[i++] = v >>> 8 | 128,
                b[i++] = 255 & v;
            for (var A = 0; A < 6; ++A) b[i + A] = f[A];
            return e || c(b)
        }
    },
    function (t, e) {
        var n = "undefined" != typeof crypto && crypto.getRandomValues && crypto.getRandomValues.bind(crypto) || "undefined" != typeof msCrypto && "function" == typeof window.msCrypto.getRandomValues && msCrypto.getRandomValues.bind(msCrypto);
        if (n) {
            var r = new Uint8Array(16);
            t.exports = function () {
                return n(r),
                    r
            }
        } else {
            var o = new Array(16);
            t.exports = function () {
                for (var t, i = 0; i < 16; i++) 0 == (3 & i) && (t = 4294967296 * Math.random()),
                    o[i] = t >>> ((3 & i) << 3) & 255;
                return o
            }
        }
    },
    function (t, e) {
        for (var n = [], i = 0; i < 256; ++i) n[i] = (i + 256).toString(16).substr(1);
        t.exports = function (t, e) {
            var i = e || 0,
                r = n;
            return [r[t[i++]], r[t[i++]], r[t[i++]], r[t[i++]], "-", r[t[i++]], r[t[i++]], "-", r[t[i++]], r[t[i++]], "-", r[t[i++]], r[t[i++]], "-", r[t[i++]], r[t[i++]], r[t[i++]], r[t[i++]], r[t[i++]], r[t[i++]]].join("")
        }
    }
])

function getReqId() {
    var l = kuwo(0),
        c = kuwo.n(l),
        r = c()()
    return r
}

// console.log(getReqId())

IIFE Biography Dictionary

Then for the same IIFE, we pass the dictionary composed of the three modules 109, 202, and 203 into IIFE. The keys are named 109, 202, and 203 in turn, and the value is the corresponding function. Then when the corresponding function is called Just take the key name directly, such as var c = n(203) . It should be noted that if the function name is not a number, quotes should be added when calling. For example, if the function name is f203 , the calling statement should be var c = n("f203") . The complete code is as follows:

var kuwo;

!function(e) {
    var t = {};

    function d(n) {
        if (t[n]) return t[n].exports;
        var r = t[n] = {
            i: n,
            l: !1,
            exports: {}
        };
        return e[n].call(r.exports, r, r.exports, d),
        r.l = !0,
        r.exports
    }

    d.n = function(e) {
        var n = e && e.__esModule ?
        function() {
            return e.
        default
        }:
        function() {
            return e
        };
        return d.d(n, "a", n),
        n
    },
    d.d = function(e, n, r) {
        d.o(e, n) || Object.defineProperty(e, n, {
            enumerable: !0,
            get: r
        })
    },
    d.o = function(object, e) {
        return Object.prototype.hasOwnProperty.call(object, e)
    }

    kuwo = d
} ({
    109 : function(t, e, n) {
        var r, o, l = n(202),
        c = n(203),
        h = 0,
        d = 0;
        t.exports = function(t, e, n) {
            var i = e && n || 0,
            b = e || [],
            f = (t = t || {}).node || r,
            v = void 0 !== t.clockseq ? t.clockseq: o;
            if (null == f || null == v) {
                var m = l();
                null == f && (f = r = [1 | m[0], m[1], m[2], m[3], m[4], m[5]]),
                null == v && (v = o = 16383 & (m[6] << 8 | m[7]))
            }
            var y = void 0 !== t.msecs ? t.msecs: (new Date).getTime(),
            w = void 0 !== t.nsecs ? t.nsecs: d + 1,
            dt = y - h + (w - d) / 1e4;
            if (dt < 0 && void 0 === t.clockseq && (v = v + 1 & 16383), (dt < 0 || y > h) && void 0 === t.nsecs && (w = 0), w >= 1e4) throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");
            h = y,
            d = w,
            o = v;
            var x = (1e4 * (268435455 & (y += 122192928e5)) + w) % 4294967296;
            b[i++] = x >>> 24 & 255,
            b[i++] = x >>> 16 & 255,
            b[i++] = x >>> 8 & 255,
            b[i++] = 255 & x;
            var _ = y / 4294967296 * 1e4 & 268435455;
            b[i++] = _ >>> 8 & 255,
            b[i++] = 255 & _,
            b[i++] = _ >>> 24 & 15 | 16,
            b[i++] = _ >>> 16 & 255,
            b[i++] = v >>> 8 | 128,
            b[i++] = 255 & v;
            for (var A = 0; A < 6; ++A) b[i + A] = f[A];
            return e || c(b)
        }
    },
    202 : function(t, e) {
        var n = "undefined" != typeof crypto && crypto.getRandomValues && crypto.getRandomValues.bind(crypto) || "undefined" != typeof msCrypto && "function" == typeof window.msCrypto.getRandomValues && msCrypto.getRandomValues.bind(msCrypto);
        if (n) {
            var r = new Uint8Array(16);
            t.exports = function() {
                return n(r),
                r
            }  
        } else {
            var o = new Array(16);
            t.exports = function() {
                for (var t, i = 0; i < 16; i++) 0 == (3 & i) && (t = 4294967296 * Math.random()),
                o[i] = t >>> ((3 & i) << 3) & 255;
                return o
            }
        }
    },
    203 : function(t, e) {
        for (var n = [], i = 0; i < 256; ++i) n[i] = (i + 256).toString(16).substr(1);
        t.exports = function(t, e) {
            var i = e || 0,
            r = n;
            return [r[t[i++]], r[t[i++]], r[t[i++]], r[t[i++]], "-", r[t[i++]], r[t[i++]], "-", r[t[i++]], r[t[i++]], "-", r[t[i++]], r[t[i++]], "-", r[t[i++]], r[t[i++]], r[t[i++]], r[t[i++]], r[t[i++]], r[t[i++]]].join("")
        }
    }
})

function getReqId() {
    var l = kuwo(109),
    c = kuwo.n(l),
    r = c()()
    return r
}

// console.log(getReqId())

Non-IIFE regular rewrite

Through the previous analysis, we already know that in the module loader of e , 061848c99ad7f4 contains all modules, and then define global variables to e the module loader, and then call the modules in 061848c99ad7f5 in turn. In fact, it is not necessary to use the IIFE method, just Like our regular function call, first define the three modules used directly outside, then encapsulate the three modules into a dictionary or array, assign the dictionary or array to e , and then load the original module function d(n){} directly out parameters n said to call e which function inside, passing the corresponding name or label to the next. The complete code is as follows:

var f109 = function(t, e, n) {
    var r, o, l = n(1),
    c = n(2),
    h = 0,
    d = 0;
    t.exports = function(t, e, n) {
        var i = e && n || 0,
        b = e || [],
        f = (t = t || {}).node || r,
        v = void 0 !== t.clockseq ? t.clockseq: o;
        if (null == f || null == v) {
            var m = l();
            null == f && (f = r = [1 | m[0], m[1], m[2], m[3], m[4], m[5]]),
            null == v && (v = o = 16383 & (m[6] << 8 | m[7]))
        }
        var y = void 0 !== t.msecs ? t.msecs: (new Date).getTime(),
        w = void 0 !== t.nsecs ? t.nsecs: d + 1,
        dt = y - h + (w - d) / 1e4;
        if (dt < 0 && void 0 === t.clockseq && (v = v + 1 & 16383), (dt < 0 || y > h) && void 0 === t.nsecs && (w = 0), w >= 1e4) throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");
        h = y,
        d = w,
        o = v;
        var x = (1e4 * (268435455 & (y += 122192928e5)) + w) % 4294967296;
        b[i++] = x >>> 24 & 255,
        b[i++] = x >>> 16 & 255,
        b[i++] = x >>> 8 & 255,
        b[i++] = 255 & x;
        var _ = y / 4294967296 * 1e4 & 268435455;
        b[i++] = _ >>> 8 & 255,
        b[i++] = 255 & _,
        b[i++] = _ >>> 24 & 15 | 16,
        b[i++] = _ >>> 16 & 255,
        b[i++] = v >>> 8 | 128,
        b[i++] = 255 & v;
        for (var A = 0; A < 6; ++A) b[i + A] = f[A];
        return e || c(b)
    }
};
var f202 = function(t, e) {
    var n = "undefined" != typeof crypto && crypto.getRandomValues && crypto.getRandomValues.bind(crypto) || "undefined" != typeof msCrypto && "function" == typeof window.msCrypto.getRandomValues && msCrypto.getRandomValues.bind(msCrypto);
    if (n) {
        var r = new Uint8Array(16);
        t.exports = function() {
            return n(r),
            r
        }
    } else {
        var o = new Array(16);
        t.exports = function() {
            for (var t, i = 0; i < 16; i++) 0 == (3 & i) && (t = 4294967296 * Math.random()),
            o[i] = t >>> ((3 & i) << 3) & 255;
            return o
        }
    }
};
var f203 = function(t, e) {
    for (var n = [], i = 0; i < 256; ++i) n[i] = (i + 256).toString(16).substr(1);
    t.exports = function(t, e) {
        var i = e || 0,
        r = n;
        return [r[t[i++]], r[t[i++]], r[t[i++]], r[t[i++]], "-", r[t[i++]], r[t[i++]], "-", r[t[i++]], r[t[i++]], "-", r[t[i++]], r[t[i++]], "-", r[t[i++]], r[t[i++]], r[t[i++]], r[t[i++]], r[t[i++]], r[t[i++]]].join("")
    }
};

var e = [f109, f202, f203];

function d(n) {
    var t = {};
    if (t[n]) return t[n].exports;
    var r = t[n] = {
        i: n,
        l: !1,
        exports: {}
    };
    return e[n].call(r.exports, r, r.exports, d),
    r.l = !0,
    r.exports
}

d.n = function(e) {
    var n = e && e.__esModule ?
    function() {
        return e.
    default
    }:
    function() {
        return e
    };
    return d.d(n, "a", n),
    n
},
d.d = function(e, n, r) {
    d.o(e, n) || Object.defineProperty(e, n, {
        enumerable: !0,
        get: r
    })
},
d.o = function(object, e) {
    return Object.prototype.hasOwnProperty.call(object, e)
};

function getReqId() {
    var l = d(0),
        c = d.n(l),
        r = c()()
    return r
}

// console.log(getReqId())


K哥爬虫
166 声望146 粉丝

Python网络爬虫、JS 逆向等相关技术研究与分享。