[ js.hook.js ]

javascript钩子; 劫持方法/伪造参数/篡改结果/还原劫持

目前为 2016-04-05 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name [ js.hook.js ]
  3. // @description javascript钩子; 劫持方法/伪造参数/篡改结果/还原劫持
  4. // @namespace js.hook.js
  5. // @version 0.0.3
  6. // @author vc1
  7. // ==/UserScript==
  8. /*
  9. *
  10. * [ js.hook.js ]
  11. *
  12. * javascript钩子
  13. *
  14. * * 劫持方法
  15. * * 伪造参数
  16. * * 篡改结果
  17. * * 还原劫持
  18. *
  19. * * 2016-04-02
  20. * * vc1
  21. *
  22. */
  23. (function(name, factory) {
  24. if (typeof define === "function" && define.amd) {
  25. define(name, factory);
  26. } else if (typeof module === "object" && module.exports) {
  27. module.exports = factory();
  28. } else {
  29. this[name] = factory();
  30. }
  31. })('hook', function() {
  32. /*
  33. * 入口方法
  34. *
  35. * hook(alert)
  36. * hook('window.alert')
  37. * hook(window, 'alert')
  38. * hook('MyOjbect.User.info.edit')
  39. */
  40.  
  41. function hook() {
  42. 'use stric'
  43. if (this instanceof hook) return this;
  44.  
  45. var fn_real, // 原始方法正身
  46. fn_name, // 被劫持的方法名
  47. fn_object_name,
  48. fn_object; // 被劫持的方法所在对象
  49. // 'window.alert'
  50. // 'alert'
  51. // alert
  52. // window, 'alert'
  53. var args = Array.prototype.slice.call(arguments),
  54. arg = args.pop();
  55. fn_object = args.pop() || root;
  56. fn_name = arg.name;
  57. if (typeof arg === 'string') {
  58. arg = arg.split('.');
  59. fn_name = arg.pop();
  60. fn_object_name = arg.join('.');
  61. fn_object = eval(fn_object_name || fn_object);
  62. }
  63. fn_real = fn_object[fn_name];
  64.  
  65. if (!(fn_object && fn_name && fn_real)) {
  66. console.error(arguments);
  67. throw new Error('hook fail');
  68. }
  69.  
  70. var storage;
  71. if (fn_object_name) {
  72. storage = hook.prototype.storage[fn_object_name] = hook.prototype
  73. .storage[fn_object_name] || {};
  74. } else {
  75. Object.defineProperties(fn_object, {
  76. '__hook__': {
  77. value: {},
  78. enumerable: false,
  79. configurable: true
  80. }
  81. });
  82. storage = fn_object.__hook__;
  83. }
  84.  
  85. // 已经劫持过了,返回已有的钩子
  86. if (storage[fn_name]) {
  87. return storage[fn_name].exports;
  88. }
  89.  
  90. var h = new hook();
  91. // 原始方法正身
  92. h.fn_real = fn_real;
  93. // 被劫持的方法名
  94. h.fn_name = fn_name;
  95. // 被劫持的方法所在对象,默认 window
  96. h.fn_object = fn_object;
  97. // 所在对象名称
  98. h.fn_object_name = fn_object_name;
  99. // 伪造传入参数
  100. h.fakeArgFn = null;
  101. // 伪造返回结果
  102. h.fakeRstFn = null;
  103. // 对外暴露的功能
  104. h.exports = {
  105. fake: h.fake.bind(h),
  106. fakeArg: h.fakeArg.bind(h),
  107. fakeRst: h.fakeRst.bind(h),
  108. off: h.off.bind(h),
  109. offArg: h.offArg.bind(h),
  110. offRst: h.offRst.bind(h),
  111. data: {
  112. fn_real: fn_real,
  113. fn_name: fn_name,
  114. fn_object_name: fn_object_name,
  115. fn_object: fn_object,
  116. get fn_puppet() {
  117. return h.fn_puppet;
  118. },
  119. get fakeArgFn() {
  120. return h.fakeArgFn;
  121. },
  122. get fakeRstFn() {
  123. return h.fakeRstFn;
  124. }
  125. }
  126. };
  127.  
  128. // 保存当前钩子
  129. storage[fn_name] = h;
  130.  
  131. return h.exports;
  132. }
  133.  
  134. hook.prototype.storage = {};
  135. var root = window || global,
  136. eval = root.eval;
  137.  
  138. /*
  139. * 替换原始方法
  140. *
  141. * 作用等于 temp=alert; alert=function(){// your function}
  142. *
  143. * fakeFn(arguments, data)
  144. * 接收到的参数列表, 原始方法信息, 对象实例或原对象, 执行时的作用域
  145. * flag为false,等于x=fn
  146. */
  147. hook.prototype.fake = function(fakeFn, flag) {
  148. var data = this.exports.data;
  149. var puppet = eval("(function " + this.fn_real.name + "() {" +
  150. "data.scope = this;" +
  151. (flag === false ?
  152. "return fakeFn.apply(this, arguments)" :
  153. "return fakeFn.call(this, arguments, data)"
  154. ) +
  155. "})");
  156. for (var prop in Object.getOwnPropertyNames(this.fn_real)) {
  157. puppet[prop] = this.fn_real[prop];
  158. }
  159. puppet.toLocaleString = puppet.toString = function() {
  160. return 'function () { [native code] }';
  161. };
  162.  
  163. this.fn_puppet = puppet;
  164. this.fn_object[this.fn_name] = puppet;
  165. return this.exports;
  166. };
  167.  
  168. /*
  169. * 在原方法前,劫持传入的参数
  170. *
  171. * fakeArg('直接替换为要传入的参数', ...)
  172. * fakeArg(function(原参数,){
  173. * //
  174. * return [修改后的参数1,2,3]
  175. * })
  176. *
  177. * 无返回则采用原始参数
  178. */
  179. hook.prototype.fakeArg = function(arg) {
  180. 'use stric'
  181. this.__fakeArgRst__();
  182. this.fakeArgFn = this.__getFun__(arguments);
  183. return this.exports;
  184. };
  185.  
  186. /*
  187. * 在原方法后,劫持返回的数据
  188. *
  189. * fakeRst('直接替换为要传入的参数')
  190. * fakeRst(function(原返回值){
  191. * //
  192. * return 修改后的返回值
  193. * })
  194. */
  195. hook.prototype.fakeRst = function(arg) {
  196. 'use stric'
  197. this.__fakeArgRst__();
  198. this.fakeRstFn = this.__getFun__(arg);
  199. return this.exports;
  200. };
  201.  
  202.  
  203. /*
  204. * 开启劫持arg/rst
  205. */
  206. hook.prototype.__fakeArgRst__ = function() {
  207. 'use stric'
  208. if (typeof this.fn_puppet === 'function') return;
  209. var t = this;
  210. var fakeArgRstFn = function(args, data) {
  211. var faked_arg = data.fakeArgFn ? data.fakeArgFn.apply(
  212. this, args) || args : args;
  213. typeof faked_arg !== 'string' && Array.prototype.slice.call(
  214. faked_arg).length === 0 && (faked_arg = [
  215. faked_arg]);
  216. var real_rst = data.fn_real.apply(this, faked_arg);
  217. var faked_rst = data.fakeRstFn ? data.fakeRstFn.call(
  218. this, real_rst) : real_rst;
  219. return faked_rst;
  220. };
  221. this.fake(fakeArgRstFn);
  222. };
  223.  
  224. /*
  225. * 关闭劫持
  226. *
  227. * 传入参数为空:关闭前后所有劫持 hook(alert).off()
  228. * 传入字符串 "arg" 或 "rst":关闭对应劫持 hook(alert).off('arg')
  229. * 传入方法:关闭对应劫持
  230. *
  231. * 前后劫持全部关闭后,还原被 hook 的方法
  232. */
  233. hook.prototype.off = function(filter) {
  234. 'use stric'
  235. if (!filter) {
  236. delete this.fakeArgFn;
  237. delete this.fakeRstFn;
  238. } else {
  239. (this.fakeArgFn === fn || filter === 'arg') && delete this.fakeArgFn;
  240. (this.fakeRstFn === fn || filter === 'rst') && delete this.fakeRstFn;
  241. }
  242.  
  243. if (!this.fakeArgFn && !this.fakeRstFn) {
  244. this.fn_object[this.fn_name] = this.fn_real;
  245. this.fn_puppet = undefined;
  246. //delete this.storage[this.fn_object_name][this.fn_name];
  247. }
  248.  
  249. return this.exports;
  250. };
  251.  
  252. /*
  253. * 关闭前面的参数劫持
  254. *
  255. */
  256. hook.prototype.offArg = function(filter) {
  257. 'use stric'
  258. filter = filter || 'arg';
  259. this.off(filter);
  260. return this.exports;
  261. };
  262.  
  263. /*
  264. * 关闭后面的结果劫持
  265. *
  266. */
  267. hook.prototype.offRst = function(filter) {
  268. 'use stric'
  269. filter || 'rst';
  270. this.off(filter);
  271. return this.exports;
  272. };
  273.  
  274.  
  275. /*
  276. * 直接修改参数或返回结果
  277. */
  278. hook.prototype.__getcloser__ = function(args) {
  279. 'use stric'
  280. return function() {
  281. return args;
  282. };
  283. };
  284. hook.prototype.__getFun__ = function(arg) {
  285. 'use stric'
  286. return typeof arg[0] == 'function' ? arg[0] : this.__getcloser__(
  287. arg);
  288. };
  289.  
  290. return hook;
  291. });