▒ 目录 ▒
- 🛫 导读
- 需求
- 1️⃣ 普通函数
- 2️⃣ 对象方法(Class.prototype)
- 3️⃣ 对象属性(Object.defineProperty)
- 4️⃣ Proxy
- 5️⃣ 批量hook示例
- 🛬 文章小结
- 📖 参考资料
🛫 导读
需求
除了通过
chrome devtool
提供的各种方案分析js以外,其实js本身就是一个编程语言,我们可以根据编程语言的逻辑,进行各种hook来方便分析代码和逻辑(可以想象成C++、java等hook)。
今天就通过js语法特性,对js的hook进行分类实践。
ps:
小肩膀
的课程,关于js逆向是很全面的了,大家可以在bilibili上看视频教程,也可以看其书籍《反爬虫AST原理与还原混淆实战》进行系统学习。
ps2:不少库都是用了hook的概念,比较有名的网络请求库ajax、axios,其自身提供hook基址,是不错的参考。除此之外,vue等大型的框架也大量使用的了hook。
1️⃣ 普通函数
js作为动态一种弱语言,直接将函数
赋值
即可覆盖原有逻辑,也是最简单的hook。示例如下:
window.alertMy = window.alert
window.alert = function(s) {
console.log('Alert: ' + s);
if (false) { // 自定义判断条件
window.alertMy(s)
}
}
2️⃣ 对象方法(Class.prototype)
对象的静态方法,可以当做普通函数进行hook。
对象的非静态方法,需要考虑上下文content
,也就是对象的指针this
。所以不能像普通函数一样直接赋值,不过js提供了原型prototype
模型,我们以localStorage.getItem
为例,代码如下:
var getItemMy = Storage.prototype.getItem
Storage.prototype.getItem = (key) => {
console.log('Storage.prototype.getItem', key)
return getItemMy.call(localStorage, key)
}
localStorage.getItem('AEGIS_ID')
执行效果如下:
3️⃣ 对象属性(Object.defineProperty)
对于对象属性,js提供了方法
Object.defineProperty
,该方法可以拦截并修改对象属性。我们以document.domain
为例,做如下修改:
Object.defineProperty(document, 'domain', {
// 改为可修改属性!!!
configurable: true,
enumerable: true,
get: function() {
return this._domain || location.host;
},
set: function(value) {
this._domain = value;
}
});
效果如下:
不过
document.domain
的这种方法只影响使用Javascript获取的数据,不会影响浏览器发送请求时带上的浏览器标识。
事实上,有多很多系统对象都是不允许使用Object.defineProperty修改的,例如:window.location
、navigator.userAgent
等。
4️⃣ Proxy
Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如
属性查找、赋值、枚举、函数调用
等)。参考MDN:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy
由于Proxy是一个比较新的概念,所以只有高版本浏览器才支持该功能。
我们依然以
localStorage.getItem
为例进行演示,需要注意的是,最后将localStorage.getItem = proxy1
。代码如下:
const proxy1 = new Proxy(localStorage.getItem, {
// 1.目标对象
// 2.目标对象的上下文对象(this)
// 3.目标对象的参数数组
apply(target, object, args) {
console.log(target, object, args)
return target.call(object,...args);
}
})
// 需要将方法设置为
localStorage.getItem = proxy1
localStorage.getItem('AEGIS_ID')
效果如下:
5️⃣ 批量hook示例
js逆向过程,往往需要对各种关键函数进行hook,下面是找到的
油猴
脚本,直接复制后在控制台运行即可,可以在变量var source
中增加自己关注的函数进行监控。
以函数
JSON.stringify
为例,说明下面脚本流程。
- let item = source[i]; //
获取某项(字符串),即"JSON.stringify"
- let realCtx = getRealCtx(ctx, item); //
获取函数所在的对象(类),即JSON
- let realName = getRealName(item); //
获取函数名,即"stringify"
- let originFunc = realCtx[realName]; //
获取函数,即JSON.stringify
- hook(realCtx, realName, level, originFunc); //
执行hook,即将JSON.stringify赋值给自己定义的一个函数,内部调用originFunc实现原有逻辑
// ==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 item = source[i];
let realCtx = getRealCtx(ctx, item);
let realName = getRealName(item);
let originFunc = realCtx[realName];
hook(realCtx, realName, level, originFunc);
}
}
test(window, 1);
})();
🛬 文章小结
上面各种方案中,
Proxy
可以实现各种hook,可以说是一劳永逸的方案。而且代码耦合性更低,实现hook更简单明了。
js逆向依托于浏览器,技术点特别多,我们需要基于现有知识储备,不断探索新的方案,从而实现目标。
📖 参考资料
- JavaScript常用的Hook脚本 https://www.cnblogs.com/xiaoweigege/p/14954648.html
- 爬虫从入门到精通(11) | JS逆向hook详解 https://blog.csdn.net/qq_40558166/article/details/123525365
- js逆向:无所不能的 hook 钩子函数 https://blog.csdn.net/qq_36078992/article/details/114484218
- 浅谈Javascript中的Hook技术 https://cloud.tencent.com/developer/article/1639578
- 刚学的油猴脚本hook住js https://www.jianshu.com/p/1bf123b3c8bf
- 爬虫从入门到精通(11) | JS逆向hook详解 https://blog.csdn.net/qq_40558166/article/details/123525365
**ps:**文章中内容仅用于技术交流,请勿用于违规违法行为。