webpack对前端js源码进行压缩打包后,一般会生成如下几个文件:
bootstrap.js 入口文件:
(function (modules) { // webpackBootstrap
// install a JSONP callback for chunk loading
var parentJsonpFunction = window["webpackJsonp"];
window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
// add "moreModules" to the modules object,
// then flag all "chunkIds" as loaded and fire callback
var moduleId, chunkId, i = 0,
resolves = [],
result;
for (; i < chunkIds.length; i++) {
chunkId = chunkIds[i];
if (installedChunks[chunkId]) {
resolves.push(installedChunks[chunkId][0]);
}
installedChunks[chunkId] = 0;
}
/*遍历数组moreModules中的模块(也就是一个一个的函数),只要moreModules含有属性moduleId,则存入全局modules数组中
moduleId就是数组的moreModules数组的下标*/
for (moduleId in moreModules) {
//hasOwnProperty()用来判断一个属性是定义在对象本身而不是继承自原型链。
//Object.prototype.hasOwnProperty 表示Object对象是否含有某个属性,在此处变成moreModules是否含有moduleId属性
if (Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
modules[moduleId] = moreModules[moduleId];
}
}
if (parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);
while (resolves.length) {
resolves.shift()();
}
if (executeModules) {
for (i = 0; i < executeModules.length; i++) {
result = __webpack_require__(__webpack_require__.s = executeModules[i]);
}
}
return result;
};
// The module cache
var installedModules = {};
// objects to store loaded and loading chunks
var installedChunks = {
8: 0
};
// The require function
function __webpack_require__(moduleId) {
// console.log('zhixing:'+moduleId);
// Check if module is in cache
if (installedModules[moduleId]) {
return installedModules[moduleId].exports;
}
// Create a new module (and put it into the cache)
var module = installedModules[moduleId] = {
i: moduleId,
l: false,
exports: {}
};
// Execute the module function
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
// Flag the module as loaded
module.l = true;
// Return the exports of the module
return module.exports;
}
/*其他代码*/
})([]);
这是一个自执行函数,当使用webpack对js文件进行功能分割时在window对象会中定义一个webpackJsonp函数,供其他模块调用,第二个参数是一个数组,里面定义大量的函数,第三个参数表示要调用哪个函数。
比如项目中可能会出现main1.js 、main2.js、about.js、download.js等等分功能的js模块文件,每一个js文件中都是类似这样的开头形式:
//第一个参数表示要依赖哪个模块先加载,第二个参数是数组,每个数组元素是一个函数,调用webpackJsonp对第二个参数中的没一个函数注册进上面的modules数组中存储起来
webpackJsonp([7], [
/* 0 */
/***/
(function (module, exports, __webpack_require__) {
var global = __webpack_require__(3);
var core = __webpack_require__(21);
//其他代码
})
]);
//或者第二个参数是一个对象形式:
//这里第三个参数[181]表示要执行modules数组中第181号函数,如果要执行多个函数块,[181,32,78]等等
//__webpack_require__表示要引入哪个函数模块
webpackJsonp([0], {
/***/
181:
/***/
(function (module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var global = __webpack_require__(3);
var core = __webpack_require__(21);
//其他代码 1
var url = new _urlParse2.default(url);
var algo = "sha256";
var digest = "hex";
var hash = (0, _createHmac2.default)(algo, url.href).update(url.query).update(url.hostname).update(url.pathname).digest(digest);
console.log(hash);
global_auth = hash;
})
},[181]);
具体到我们逆向分析的层面,当我们再chrome中调式分析到我们所关注的代码逻辑后,确定其所在哪一个序号模块中,然后修改webpackJsonp的第三个参数就ok了。
比如我这里,我分析到需要计算url的一个加密值,发现它在181号模块中,将 “其他代码 1” 这段代码块单独扣出来,删掉181号模块中其他不相关的逻辑代码,只要保证”其他代码 1“这个代码中引入的函数(如_createHmac2)能正常require进来就行
如何具体到操作层面呢?
这里以python中的pyv8为例讲解(用node执行也是一样),pyv8内嵌了google的V8 js引擎,虽说版本比较老了,但还是能用的。
但是直接在chrome浏览器上分析出来的结果,是不能全部直接丢进pyv8进行执行操作的,因为V8引擎是一个纯js执行环境,它不包含浏览器js环境中的dom window等这些对象,所以要对分析出的js文件进行适当修改。
将所有js文件整合到一个js文件中,注意顺序,首先copy boostrap.js入口文件,然后main1.js、main2.js等所有的模块代码都copy进来,最后才将需要调用的模块引入,并传入需要执行的具体模块序号,如[181],整体js代码形式如下:
var window = []; //V8没有window对象,手动定义一个全局的
var global_auth = ''; //用来接收后面计算出来的url加密值,pyv8可以获取到这个变量的值
//boostrap.js入口文件
(function (modules) { // webpackBootstrap
var parentJsonpFunction = window["webpackJsonp"];
.......
})([]);
//main1.js模块
webpackJsonp([7], [
(function (module, exports, __webpack_require__) {
.......
})
]);
//其他模块
.....
//最后目标代码所在的模块
webpackJsonp([0], {
/***/
181:
/***/
(function (module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
var _react = __webpack_require__(2);
var _react2 = _interopRequireDefault(_react);
var _reactStatic = __webpack_require__(119);
var _Meta = __webpack_require__(480);
var _Meta2 = _interopRequireDefault(_Meta);
var _Header = __webpack_require__(481);
var _Header2 = _interopRequireDefault(_Header);
var _Footer = __webpack_require__(482);
var _Footer2 = _interopRequireDefault(_Footer);
var _Thumbnails = __webpack_require__(483);
var _Thumbnails2 = _interopRequireDefault(_Thumbnails);
var _DownloadLink = __webpack_require__(507);
var _DownloadLink2 = _interopRequireDefault(_DownloadLink);
var _fuzzyTile = __webpack_require__(488);
var _fuzzyTile2 = _interopRequireDefault(_fuzzyTile);
var _createHmac = __webpack_require__(508);
var _createHmac2 = _interopRequireDefault(_createHmac);
var _icons = __webpack_require__(475);
var _icons2 = _interopRequireDefault(_icons);
var _urlParse = __webpack_require__(531);
var _urlParse2 = _interopRequireDefault(_urlParse);
var _axios = __webpack_require__(120);
var _axios2 = _interopRequireDefault(_axios);
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
url = 'https://www.youtube.com/watch?v=3_VsTMc1auM';
var url = new _urlParse2.default(url);
var algo = "sha256";
var digest = "hex";
var hash = (0, _createHmac2.default)(algo, url.href).update(url.query).update(url.hostname).update(url.pathname).digest(digest);
console.log(hash);
global_auth = hash;
})
},[181]); //执行181模块