油猴脚本-编写笔记
在看蔡老板的文章时发现油猴hook脚本可以像数组一样遍历函数名,虽然有点碰运气但还是可以尝试。
笔记一: 蔡老板的入口文章系列 其中一个需要自己完成的hook脚本。
// ==UserScript== // @name HOOK 遍历 // @namespace http://tampermonkey.net/ // @version 0.1 // @description day day up // @author FY // @include * // @grant none // @run-at document-end // ==/UserScript== (function() { 'use strict'; !function () { 'use strict'; var source = ['DeCode','EnCode','decodeData','base64decode','md5','decode','btoa','MD5','RSA','AES','CryptoJS','encrypt','strdecode',"encode",'decodeURIComponent','_t','JSON.stringify','String.fromCharCode','fromCharCode']; console.log("开始测试是否有解密函数"); let realCtx, realName; function getRealCtx(ctx, funcName) { let parts = funcName.split("."); let realCtx = ctx; for(let i = 0; i < parts.length - 1; i++) { realCtx = realCtx[parts[i]]; } return realCtx; } function getRealName(funcName) { let parts = funcName.split("."); return parts[parts.length - 1]; } function test(ctx) { for(let i = 0; i < source.length; i++) { let f = source[i]; let realCtx = getRealCtx(ctx, f); let realName = getRealName(f); let chars = realCtx[realName]; if (chars != undefined){ console.log("发现可疑函数:", f); console.log(chars); console.log("---------------------"); }else{ console.log("未发现:", f); } } } test(window); }(); })();
开启脚本后找一个网站测试,打开控制台刷新网页后打印如下内容。
我们可以看到,脚本检测出了许多疑似加密函数的内容,我们可以把之前遇到过的类似的需要解密的函数写进一个数组里,然后依次查询是否有这样的函数。
笔记二:上一个脚本只是检测是否有加密函数,接下来完善一下,打印出加密函数的返回值,也就是直接hook到结果。
// ==UserScript== // @name HOOK ALL end // @namespace http://tampermonkey.net/ // @version 0.1 // @description day day up! // @author FY // @include * // @grant none // @run-at document-end // ==/UserScript== (function() { 'use strict'; var source = ['DeCode','EnCode','decodeData','base64decode','md5','decode','btoa','MD5','RSA','AES','CryptoJS','encrypt','strdecode',"encode",'decodeURIComponent','_t','JSON.stringify','String.fromCharCode','fromCharCode']; console.log("开始测试是否有解密函数"); let realCtx, realName; function getRealCtx(ctx, funcName) { let parts = funcName.split("."); let realCtx = ctx; for(let i = 0; i < parts.length - 1; i++) { realCtx = realCtx[parts[i]]; } return realCtx; } function getRealName(funcName) { let parts = funcName.split("."); return parts[parts.length - 1]; } function hook(ctx, funcName, level, originFunc) { ctx[funcName] = function(a){ console.log("level:" + level + " function:" + funcName,a); console.log(originFunc.toString()); console.log(originFunc.toString); debugger; return originFunc(a); }; } function test(ctx, level) { for(let i = 0; i < source.length; i++) { let f = source[i]; let realCtx = getRealCtx(ctx, f); let realName = getRealName(f); let chars = realCtx[realName]; hook(realCtx, realName, level, chars); } } test(window, 1); })();
也是循环遍历 然后打印出函数的定义和返回值。
笔记三 : 需要更直观的看出加密函数内部调用的函数名。
// ==UserScript== // @name HOOK 二层函数名 end // @namespace http://tampermonkey.net/ // @version 0.1 // @description day day up! // @author FY // @include * // @grant none // @run-at document-end // ==/UserScript== (function() { 'use strict'; var source = ['decodeData','base64decode','md5','decode','btoa','MD5','RSA','AES','CryptoJS','encrypt','strdecode',"encode",'decodeURIComponent','_t','JSON.stringify','String.fromCharCode','fromCharCode']; console.log("开始测试是否有解密函数"); let realCtx, realName; function getRealCtx(ctx, funcName) { let parts = funcName.split("."); let realCtx = ctx; for(let i = 0; i < parts.length - 1; i++) { realCtx = realCtx[parts[i]]; } return realCtx; } function getRealName(funcName) { let parts = funcName.split("."); return parts[parts.length - 1]; } function hook(ctx, funcName, level, originFunc) { ctx[funcName] = function(a){ console.log("level:" + level + " function:" + funcName,a); let regexp = / [\S]*\(.*\)\;/g; let match = originFunc.toString().match(regexp) console.log(match); debugger; return originFunc(a); }; } function test(ctx, level) { for(let i = 0; i < source.length; i++) { let f = source[i]; let realCtx = getRealCtx(ctx, f); let realName = getRealName(f); let chars = realCtx[realName]; hook(realCtx, realName, level, chars); } } test(window, 1); })();
可以看出就是多写了一个正则,匹配出加密函数内部调用的函数名。