WeChat official account: brother K crawler, QQ exchange group: 808574309, keep sharing crawler advance, JS/ Android reverse technology dry cargo!
statement
All contents in this article are for learning and communication only. The packet capturing content, sensitive website and data interface have been desensitized. It is strictly prohibited to use them for commercial and illegal purposes, otherwise all the consequences have nothing to do with the author. If there is infringement, please contact me and delete them immediately!
Reverse target
-
Objective: KW music search parameters
-
Home page: ahr0cdovl3dy5rdxdvlmnulw==
-
Interface: ahr0cdovl3dy5rdxdvlmnul2fwas93d3cvc2vhcmnol3nlyxjjae11c2ljqnlrzxlxb3jk
-
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 paper is to introduce the separated webpack, that is, how to rewrite the webpack when the module loader is not in the same JS file with each module, and how to use non IIFE (immediately call function expressions and self executing functions) This article is an extension of previous articles:
- Crawler reverse foundation, understand JavaScript modular programming, webpack
- [JS reverse hundred examples] webpack rewrites the actual combat, and RSA encryption of a game in G
Reverse process
Packet capture analysis
Go to the search page and search for songs casually. Grab the package and find that the interface class is ahr0cdovl3dy5rdxdvlmnul2fwas93d3cvc2vhcmnol3nlyxjjae11c2ljqnlrzxlxb3jk. There is a reqId encryption parameter in the Query String Parameters, as shown in the figure below:
Parameter inversion
Directly search reqId globally. There are only four results in app.4eedc3a.js file, as shown in the following figure:
Obviously, t.data.reqId = r and t.data.reqId = n are suspicious. If you try to bury breakpoints in these two places, you will find that it is impossible to refresh the web page or search again. Let's observe the definition statements var r = c() var n = c()(); Both are obtained by C () (). We try to bury breakpoints at these two locations and search again. We can find that the breakpoints are successfully broken, and the value of C () () is the value of reqId, as shown in the following figure:
Continue to look up and see how c comes from. You can see the logic:
var l = n(109) , c = n.n(l) var r = c()();
Bury breakpoints for debugging. You can see that n is actually a method in runtime.d5e801d.js, as shown in the following figure:
Observe the function d(n) {}. The return statement uses the. call syntax and the exports keyword. Through the introduction of brother K's previous articles, it is easy to know that this is a webpack module loader, so e includes all modules, as shown in the following figure:
Let's take another look at n(109). Click to enter this function. It can be found that the functions before and after are separated by commas and marked to the end of the file. You can see the] symbol, which indicates that all modules of webpack are encapsulated in an array. Then this 109 represents that this function is the 109th function, as shown in the following figure:
Take another look at the c = n.n(l) statement. Select n.n and click it to find that you also come to the module loader. Then you can deduct d.n when you deduct the code.
To summarize the logic, the statement l = n(109) uses the module loader to load the 109th function, assign the return value to l, and then c = n.n(l) calls the n method of the module loader, assign the return value to c, and then execute c()() to get the value of reqId.
webpack rewrite
In the previous articles of brother K, we have introduced the rewriting method of webpack. In this case, brother K will introduce three methods, which can also be divided into two methods. One is IIFE (immediate call function expression and self-executing function), but the passed parameters, that is, the format of the module, are divided into array and dictionary. The second is non IIFE, which is a more conventional rewriting method, It seems easier to understand. PS: the complete code is not very good-looking. You can use tools such as VSCode to fold all the codes. You can clearly see the different structures of the codes under different rewriting methods.
Through the previous analysis, we know that d.n is used in the module loader, and d.d and d.o are also used in the actual debugging, so they should be deducted together.
In the module part, we already know that the module 109 was called, but we found that the code of 109 also called modules 202 and 203, so we need to copy these three modules. When copying, we first run to the module loader at the breakpoint. Since e stores all modules, we can directly call e[109], e[202] and e[203] in the Console Output and click to jump to the position of the original function, and then copy down, as shown in the following figure:
IIFE pass through array
Brother K has introduced the rewriting method of IIFE in previous articles. Similarly, we first define a global variable, such as var kuwo;, Then export the module loader kuwo = d, and then transfer the array composed of 109, 202 and 203 modules to IIFE, so it is no longer the 109th, 202 and 203 modules, but the 0, 1 and 2 modules. Therefore, when calling the module, the corresponding 109, 202 and 203 should also be changed to 0, 1 and 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 dictionary
For the same IIFE, we pass the dictionary composed of 109, 202 and 203 modules into IIFE, and the keys are named 109, 202 and 203 in turn. The value is the corresponding function. When calling the corresponding function, 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, quotation marks should be added when calling, For example, if the function name is f203, the calling statement should be var c = n("f203"), and 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 routine override
Through the previous analysis, we know that e contains all modules in the module loader of webpack. Then we define global variables to export the module loader, and then call the modules in E in turn. In fact, we can not use IIFE. Just like our regular function calls, we first define the three modules used directly outside, Then package the three modules into a dictionary or array, assign the dictionary or array to e, and then directly take out the original module loader function d(n) {}. The parameter n indicates which function in e to call, and pass in the corresponding name or subscript. 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())