【js逆向】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.locationnavigator.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逆向依托于浏览器,技术点特别多,我们需要基于现有知识储备,不断探索新的方案,从而实现目标。

📖 参考资料

**ps:**文章中内容仅用于技术交流,请勿用于违规违法行为。

  • 0
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜猫逐梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值