Hook 技术介绍

  • Hook 技术中文又叫作钩子技术,它就是在程序运行的过程中,对其中的某个方法进行重写,

  • 在原有的方法前后加入我们自定义的代码。相当于在系统没有调用该函数之前,钩子程序就先捕获该消息,

  • 可以先得到控制权,这时钩子函数便可以加工处理(改变)该函数的执行行为。

  • 通俗点来说呢,比如我要 Hook 一个方法 funA,可以先临时用一个变量存一下,把它存成 A,

  • 然后呢,我再重新声明一个新的方法 funB,里面添加自己的逻辑,比如加点调试语句、输出语句等等,

  • 然后在新的方法 funB 里面再调用 A,这里调用的 A 就是之前原始的方法 funA。

  • 这样就相当于新的方法 funB 里面混入了我们自己定义的逻辑,同时又把原来的方法 A 也执行了一遍。

  • 所以这不会影响原有的执行逻辑和运行效果,但是我们通过这种改写便可以顺利在原来的 A 方法前后加上了我们自己的逻辑,这就是 Hook。

def funA():print('hello')A = funA()def funB():print('你好')funA()print('world')B = funB()
  • 上面案例就是一Hook方法的简单演示

    • 我们要寻找funA执行的位置,通过执行我们funB方法,输出 你好 以后就是执行 funA 的位置
  • 怎么使用 Hook 的方式来找到加密 id 的加密入口点呢?原理和上面一样

    • 加密 id 是一个 Base64 编码的字符串,那么生成过程中想必就调用了 JavaScript 的 Base64 编码的方法,
    • 这个方法名叫作 btoa,这个 btoa 方法可以将参数转化成 Base64 编码。
    • 当然 Base64 也有其他的实现方式,比如利用 crypto-js 这个库实现的,这个可能底层调用的就不是 btoa 方法了。
    • 所以,其实现在并不确定是不是调用的 btoa 方法实现的 Base64 编码,那就先试试吧。
    • 要实现 Hook,其实关键在于将原来的方法改写,这里我们其实就是 Hook btoa 这个方法了,
    • btoa 这个方法属于 window 对象,我们将 window 对象的 btoa 方法进行改写即可。
  • 具体使用方法如下:

(function () {'use strict';function hook(object, attr) {var func = object[attr];object[attr] = function () {console.log('hooked', object, attr, arguments);var ret = func.apply(object, arguments);debugger;console.log('result', ret);return ret;}}hook(window, 'btoa');
})()
  • 具体步骤:

    • 首先,定义了一个 hook 方法,传入 object 和 attr 参数,意思就是 Hook 的 object 对象的 attr 参数。

      • 例如我们如果想 Hook 一个 alert 方法,那就把 object 对象设置为 window,把 attr 参数设置为要 alert 方法,arguments就是alert方法接收的参数(字符串)。
      • 这里我们想要 Hook Base64 的编码方法,那么这里就只需要传入 Hook 的window 对象(object对象)和 btoa 方法(attr参数)就好了。
      • 后面的 arguments 就是传给 btoa 方法的参数, ret 就是该 btoa 方法执行后的结果,即参数经过base64 编码后的结果
    • 然后是定义一个变量, var func = object[attr],相当于先把object对象和参数赋值为一个变量,
      • 我们调用 func 方法就可以实现和原来相同的功能。
    • 接着,我们再直接改写这个方法的定义(修改该方法),直接改写 object[attr],将其改写成一个新的方法,
      • 新的方法开头加入console.log调试语句
      • 在新的方法中,通过 func.apply 方法又重新调用了原来的方法,将其赋值到一个ret变量中,新方法最后返回原来方法的执行结果
    • 这样我们就可以保证,前后方法的执行效果是不受什么影响的,之前这个方法该干啥就还是干啥的。
      • 但是和之前不同的是,我们自定义方法之后,现在可以在 func 方法执行的前后,
      • 再加入自己的代码,如 console.log 将信息输出到控制台,如 debugger 进入断点等等
    • 最后,我们调用 hook 方法,传入 window 对象和 btoa 字符串(即window对象的btoa方法)即可
  • Hook 逻辑说明:

    • hook 过程中,我们先临时保存下来了 func 方法,然后定义一个新的方法,接管程序控制权,
    • 在新方法中自定义我们想要的实现,同时在新的方法里面再重新调回 func 方法,保证前后结果是不受影响的。
    • 所以,我们达到了在不影响原有方法效果的前提下,可以实现在方法的前后实现自定义的功能,就是 Hook 的完整实现过程。
    • 最后,我们调用 hook 方法,只需要传入 window 对象和 btoa 字符串(方法的名称)即可。

Hook 注入代码的三种方式:

- 上面已经 hook 了 btoa 方法,接下来就是注入代码,三种注入方法:
- 直接控制台注入;
- 重写 JavaScript 代码;
- Tampermonkey 油猴注入。

Hook 注入代码方法1:控制台注入

  • 直接复制上面代码到Chrome的console控制台,然后enter执行,执行完这段代码之后

  • 相当于我们就已经把 window 对象的 btoa 方法改写为我们自定义的新方法了,

  • 此时,我们可以控制台调用下 btoa 方法,回车之后就可以看到它进入了我们自定义方法的 debugger 的位置停下了

  • 查看[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cf1kEwwV-1596948392910)(003_JavaScript混淆加密_Ajax动态请求_哔哩哔哩JS动态请求分析提取/041_JavaScript逆向实例1_Hook钩子方法_代码注入_控制台注入1.png)]

  • 查看[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dXHqvBHb-1596948392924)(003_JavaScript混淆加密_Ajax动态请求_哔哩哔哩JS动态请求分析提取/041_JavaScript逆向实例1_Hook钩子方法_代码注入_控制台注入2.png)]

  • 点击调试继续键,就会继续向下执行代码:console.log(‘result’, ret);

  • 控制台输出经过 base64 加密后的字符串

  • 查看[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AzPV6O33-1596948392934)(003_JavaScript混淆加密_Ajax动态请求_哔哩哔哩JS动态请求分析提取/041_JavaScript逆向实例1_Hook钩子方法_代码注入_控制台注入3.png)]

  • 控制台直接输入的 Hook 代码,所以页面一旦刷新就无效了,但由于我们这个网站是 SPA 式的页面,

  • 所以在点击详情页的时候页面是不会整个刷新的,所以这段代码依然还会生效。

  • 但是如果不是 SPA 式的页面,即每次访问都需要刷新页面的网站,这种注入方式就不生效了

  • 经过上面分析,我们就可以查找详情页加密ID逻辑:

    • 详情页的token 值是访问列表页的 ajax 请求就生成了,
    • 注入了上面代码,每一次base64编码都会暂停并输出编码前和编码后的结果
    • 我们注入代码目的是为了 Hook 列表页 Ajax 加载完成后的加密 id 的 Base64 编码的过程,
    • 那怎么在不刷新页面的情况下再次复现这个操作呢?很简单,注入代码,enter后,点下一页就好了。
    • 这时候我们可以点击第 2 页的按钮,但是此时还是从第一页开始的,因为所有经过 btoa 方法都会执行一遍,
    • 可以看到它确实再次停到了 Hook 方法的 debugger 处,
    • 由于列表页的 Ajax 和加密 id 都会带有 Base64 编码的操作,因此它每一个都能 Hook 到,
    • 通过观察对应的 Arguments 或当前网站的行为或者观察栈信息,我们就能大体知道现在走到了哪个位置了,
    • 从而进一步通过栈的调用信息找到调用 Base64 编码的位置。
    • 我们点击右上角调试继续按钮,如果是灰色先点击一下即可,多点击几次发现
    • 控制台和右侧调试栏都会输出相应信息,观察加密前的 arguments 只有末尾一个字符不同
    • 查看[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VyZP718e-1596948392946)(003_JavaScript混淆加密_Ajax动态请求_哔哩哔哩JS动态请求分析提取/041_JavaScript逆向实例1_Hook钩子方法_代码注入_控制台注入4.png)]
    • 我们暂停在某个加密位置,然后右侧 栈 一层层向上找,就可以找到加密前字符串的位置,然后继续向上找
    • 同时配合查看 网页返回的 json 内容,可以发现加密前的字符串是由一个写死的字符串
    • ef34#teuq0btua#(-57w1q5o5–j@98xygimlyfxs*-!i-0-mb和电影的真实ID拼接在一起的
    • 拼接后的字符串,然后进行base64编码
  • 控制台注入代码存在问题:

    • Hook 代码是在控制台手动输入的,一旦刷新页面就不生效了,这的确是个问题。
    • 而且它必须是在页面加载完了才注入的,所以它并不能在一开始就生效。
    • 上面通过点击下一页,重新发起请求完成

重写 JavaScript

  • Hook 注入代码方法2:
  • 重写 JavaScript
    • 我们可以借助于 Chrome 浏览器的 Overrides (重写)功能实现某些 JavaScript 文件的重写和保存,

    • 它会在本地生成一个 JavaScript 文件副本,以后每次刷新的时候会使用副本的内容。

    • 这里我们需要切换到 Sources 选项卡的 Overrides 选项卡,

    • 然后选择一个文件夹,比如这里进入项目文件里面新建了一个文件夹名字叫作 modify

    • 然后切换到Sources-Page-js文件夹中,随便选择一个js文件脚本,后面贴上上面 Hook 后的 btoa 代码

    • 查看[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QyF1c8F1-1596948392948)(003_JavaScript混淆加密_Ajax动态请求_哔哩哔哩JS动态请求分析提取/042_JavaScript逆向实例1_Hook钩子方法_代码注入_重写JavaScript1.png)]

    • 注意:修改代码不要格式化代码,直接原始js文件,先end 到结尾 然后换行空一行,粘贴代码,末尾可以添加上 ; 号,添加多个需要加上。

    • 右键刚刚修改的js文件名称,保存到上面新建的modify文件夹中

    • 此时可能提示页面崩溃,但是不用担心,重新刷新页面就好了,这时候我们就发现现在浏览器加载的 JavaScript 文件就是我们修改过后的了,文件的下方会有一个标识符,蓝色小点

    • 然后点击调试继续按钮,没执行到 btoa 方法就暂停一下,我们进入控制台console里面查看

    • 查看[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uhHKWUVn-1596948392952)(003_JavaScript混淆加密_Ajax动态请求_哔哩哔哩JS动态请求分析提取/042_JavaScript逆向实例1_Hook钩子方法_代码注入_重写JavaScript2.png)]

    • 最先执行了 列表页 的token加密,然后就是详情页id加密,elements里面详情页ID出现了两次,执行了两次

    • 查看[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7HwlLqMn-1596948392955)(003_JavaScript混淆加密_Ajax动态请求_哔哩哔哩JS动态请求分析提取/042_JavaScript逆向实例1_Hook钩子方法_代码注入_重写JavaScript3.png)]

    • 其实 Overrides 的这个功能非常有用,我们保存了修改后文件到本地,有了它我们可以持久化保存我们任意修改的 JavaScript 代码,

    • 所以我们想在哪里改都可以了,甚至可以直接修改 JavaScript 的原始执行逻辑也都可以的

Tampermonkey 油猴插件注入

  • Tampermonkey 油猴注入

    • 如果我们不想用 Overrides 的方式改写 JavaScript 的方式注入的话,还可以借助于浏览器插件来实现注入,
    • 这里推荐的浏览器插件叫作 Tampermonkey,中文叫作“油猴”。它是一款浏览器插件,支持 Chrome。
    • 利用它我们可以在浏览器加载页面时自动执行某些 JavaScript 脚本。
    • 由于执行的是 JavaScript,所以我们几乎可以在网页中完成任何我们想实现的效果,
    • 如自动爬虫、自动修改页面、自动响应事件等等。
    • 可以管理网上下载的一些脚本
  • 安装Tampermonkey插件

    • 官网下载:https://www.tampermonkey.net/
    • 脚本管理器:https://greasyfork.org/zh-CN
    • 一些使用的三方脚本网站:https://greasyfork.org/zh-CN/scripts
    • 网络问题,会安装失败,进入第三方地址下载解压得到crx文件安装
    • 下载地址:http://www.pc6.com/soft/FireFox_247376.html
    • 下载解压后,Chrome进入更多工具-扩展程序界面,将crx文件拖入即可安装
    • 查看[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-caJV8wJT-1596948392957)(003_JavaScript混淆加密_Ajax动态请求_哔哩哔哩JS动态请求分析提取/043_JavaScript逆向实例1_Hook钩子方法_代码注入_tampermonkey油猴js脚本管理器安装.png)]
    • 然后点击右上角,扩展程序,点击tampermonkey后面的固定,固定在工具栏
    • 安装完成之后,在 Chrome 浏览器的右上角会出现 Tampermonkey 的图标
  • 使用 Tampermonkey插件

    • 点击 Tampermonkey 插件图标,点击“管理面板”按钮,打开脚本管理页面
    • 显示了我们已经有的一些 Tampermonkey 脚本,包括我们自行创建的,也包括从第三方网站下载安装的
    • 编辑、调试、删除等管理功能,我们可以方便地对脚本进行管理。
    • 接下来我们来创建一个新的脚本来试试,点击左侧的“+”号
    • 会出来一个初始化文件脚本,版本不同可能注释内容有区别
// ==UserScript==
// @name         New Userscript
// @namespace   http://tampermonkey.net/
// @version     0.1
// @description try to take over the world!
// @author       You
// @match       https://www.tampermonkey.net/documentation.php?ext=dhdg
// @grant       none
// ==/UserScript==(function() {'use strict';// Your code here...
})();
  • 最上面是一些注释,但这些注释是非常有用的,这部分内容叫作 UserScript Header ,

    • 我们可以在里面配置一些脚本的信息,如名称、版本、描述、生效站点等等。
    • 在 UserScript Header 下方是 JavaScript 函数和调用的代码,
    • 其中 use strict 标明代码使用 JavaScript 的严格模式,
    • 在严格模式下可以消除 Javascript 语法的一些不合理、不严谨之处,减少一些怪异行为,
    • 如不能直接使用未声明的变量,这样可以保证代码的运行安全,
    • 同时提高编译器的效率,提高运行速度。
    • 在下方 // Your code here… 这里我们就可以编写自己的代码了。
  • 我们将上面 hook 后的 btoa 代码复制进去,然后保存

    • 重新访问目标网址:https://dynamic6.scrape.cuiqingcai.com/
    • 进入开发者工具,然后刷新页面,就会停留在脚本的debugger位置
    • 然后就可以点击调试工具栏继续按钮,调试断点运行,然后找到所有经过btoa编码的代码

Hook 钩子技术及代码注入的 3 种方式相关推荐

  1. IoC(控制反转)的主要组件和注入的两种方式

    一.IoC的主要组件: (1).Spring框架的两个最基本和最重要的包是org.springframework.beans.factory(该包中的主要接口是BeanFactory)和org.spr ...

  2. Dagger2 知识梳理(1) Dagger2 依赖注入的两种方式

    一.资料推荐 最近这几天一直在看有关Dagger2有关的文章,感觉就是这东西真难用.真难懂,数次想要放弃,还好有网上大神的教程帮助,模模糊糊总算能把基本的几个概念跑通了. 这里首先推荐 牛晓伟 的下面 ...

  3. 依赖注入的两种方式并附上例子

    1.依赖注入:就是指程序在运行过程中,如果需要另外一个对象协助完成时,无需在代码中创建被调用者,而是依赖外部的注入获取. 2.依赖注入的两种方式: 设置注入:设置注入是通过setter方法注入被调用者 ...

  4. Spring属性注入的三种方式(超详细)

    属性注入的三种方式 使用set方法进行注入 使用有参构造函数进行注入 使用p名称空间注入 首先了解下面两个名词的含义: IOC:控制反转(Inversion of Control,缩写为IoC),是面 ...

  5. Spring系列之依赖注入的三种方式

    目录 一.依赖注入方式 1.使用属性的setXXX方法注入 2.构造函数注入 (1)按类型匹配入参type (2)按索引匹配入参index (3)联合使用类型和索引匹配入参[type和index一起使 ...

  6. 05.bean依赖注入的三种方式

    05.bean依赖注入的三种方式 1.概述 依赖注入 DI(Dependency Injection):它是 Spring 框架核心 IOC 的具体实现. 在编写程序时,通过控制反转,把对象的创建交给 ...

  7. Spring IOC (DI) 依赖注入的四种方式

    依赖注入的四种方式: set 注入 赋值,默认使用的是set() 方法,依赖注入底层是通过反射实现的 <bean id="student" class="cust. ...

  8. Spring注入的三种方式

    Spring实例注入的三种方式: 1.属性注入,即使用注解注入. 2.set方法注入. 3.构造方法注入. 1.属性注入 使用@Autowired.@Resource或@Inject注解注入. 1.1 ...

  9. spring依赖注入的三种方式以及优缺点

    spring依赖注入的三种方式以及优缺点 一.依赖注入的三种方式 1.通过构造器注入.(spring4.3之后,推荐使用) 2.通过setter注入.(spring4.3之前,推荐使用) 3通过fil ...

最新文章

  1. C语言static 具体分析
  2. 照亮云备份的“钱”途
  3. 土木工程真的这么可怕吗?
  4. 利用Java流进行类的整型字段求和的例子
  5. 浅谈Java中的==和equals
  6. 常用的优化方法-梯度下降、牛顿法、坐标下降法
  7. 新华三副总裁李立:建设智慧城市的三大误区
  8. Pandas+Pyecharts:2021中国大学综合排名分析+可视化,来围观看看你的大学上榜没
  9. Spring scope属性详解
  10. 结构张量 matlab 图像,图像处理中 结构张量(structure tensor)
  11. 金蝶K3系统如何更改已使用物料的计量单位信息
  12. 热点讨论:IT人,40岁以后能干什么?
  13. markdown如何调整行距_Markdown基础语法
  14. perl中tr的用法
  15. CorelDRAW图片导出变色,如何解决?
  16. python预测彩票模型_python预测下一期双色球号码【机器学习】
  17. linux虚拟机和电脑ping通(可上网)
  18. 20220529 pdf 分割合并软件,python tkinter
  19. 寒冬已至?四面楚歌的Android工程师该何去何从
  20. 马云的双11计算机发展史图片,双11白色系电脑想买就选它们

热门文章

  1. 多个IEXPLORE.EXE专杀方案
  2. 按键精灵学习脚本--短视频浏览脚本
  3. Java nio 异常_Java NIO写入异常问题
  4. win10关闭防火墙脚本
  5. Linux打印出netstat -anp 里的Send_Q发送堵的TCP连接
  6. yii2手动添加插件PHPExcel
  7. 为什么顶级科技公司热爱打坐冥想?
  8. Dalvik 指令集
  9. python运行启动报错解决方法_解决python运行启动报错问题
  10. 微信小程序云开发——有数据却拿不到数据