爬虫js逆向基础——05`HOOK`

本文详细介绍了JavaScript中的Hook技术,包括如何寻找和修改函数、属性的入口,以及Hook的目的和潜在问题。通过示例展示了如何Hook eval、对象属性以及原型链上的方法。同时,讨论了Hook的优缺点,并提供了实际的油猴脚本注入示例,揭示了Hook在分析JS逻辑和解决特定问题(如内存泄露)中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

步骤

  • 寻找Hook
  • 编写hook逻辑
  • 调试

公式

old_func = func
func = function(){
	my task;
    return func.apply(argument)
}
// 修改原生的方法,伪装没有被hook,比如toString方法
func.prototype······  = ······

hook对象中的属性

hook对象中的属性
old_attr = obj.attr
Object.defineProperty(obj, 'attr', {
    get:function(){
        console.log(cookie_cache);
        return old_attr
    },
    set:function(val){
        return ·······
    }
})

关于hook

  1. 如果能修改源码,那么一般来说源码修改比hook方便
  2. 系统/框架API无法轻松通过源码修改来实现我们的目的
  3. js由于是解释型语言,代码 == 二进制,一般使用源码修改修改方法
  4. js语言由于是解释型语言,无法通过全局root定位到js所有方法定义,现代js为了避免变量污染大多对js代码进行多层js函数包装,故很难通过框架自动化寻找hook点。

为什么能实现hook

客户端拥有js的最高解释权,可以决定在任何时候注入js而服务器无法左右,只能通过检测和混淆手段令hook难度加大,但是却无法阻止。

hook的目的

js hook目的是找到函数入口以及一些参数变化,便于分析js逻辑,但是hook的能力远不及此,只能借助其寻找函数入口。

hook的弊端和缺陷

函数hook一般不会出现hook失败的情况,只有可能是__proto__模拟的不好被检测到了

属性hook当所有网站逻辑都采用Object.defineProperty绑定后,属性hook就会失效

还有一种叫做局部hook,只不过需要在当进入作用域的那一刻进行hook

hook插件(油猴脚本注入)

//run-at document-start
(function(){
    alert('hook success');
    var eval_bk = eval;
    eval = function(val){
        console.log(val)
        return eval_bk(val);
    };
    eval.toString = function(){
        return "function eval(){[native code]}"
    };
    eval.length = 1;
})();

例子:

// ==UserScript==
// @name         万能hook eval函数
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  eval-everything
// @author       xiaosheng
// @include      *
// @grant        none
// @run-at      document-start
// ==/UserScript==


(function() {
    alert('hook success');
    var eval_bk = eval;
    eval = function(val){
       console.log(val)

       return eval_bk(val);
    };
    eval.toString = function(){
         return "function eval() { [native code] }"
    };
    eval.length = 1;
})();

原型链相关的hook

a = "加密逻辑"
按常规的hook方式,hook   a.split
a.split = function(){
    debugger;
}
这种方式重写不了
 得用原型链   ---  :因为a.split方法是通过原型链来的,其实是 String.prototype.split

String.prototype.split = function(){
    debugger;
}
/*
改进一下,为了让hook之后的代码也能正常执行,下面这样写是错误的
x下面这样写 会导致 递归 栈溢出
String.prototype.split = function(val){
    str = this.toString()
    debugger;
    return str.split(val) 
}
再改进一下,
下面这样不行,因为,return str.split_bk(val) 找的是str里面的split_bk方法,
而不是自己重写的这个方法
split_bk = String.prototype.split
String.prototype.split = function(val){
    str = this.toString()
    debugger;
    return str.split_bk(val) 
}
*/
String.prototype.split_bk = String.prototype.split
String.prototype.split = function(val){
    str = this.toString()
    debugger;
    return str.split_bk(val) 
}
这样也能被检测到,比如通过toString
String.prototype.split.toString = function(){
    return "function split() { [native code] }"
}
XMLHttpRequest.prototype.setRequestHeader = function(){
    debugger;
}

hook对象
思考题:比如ob混淆的内存泄露,他是通过依靠正则完成的,那么是否能hook正则,然后让test的检测逻辑发生变化(恒为true, 或者取反,由此处理内存泄露的问题)

RegExp.prototype.test_bk = RegExp.prototype.test
RegExp.prototype.test = function(val){
	t = this
	debugger;
	return !t.test_bk(val)
};
RegExp.prototype.test.toString = function(){return "function test() { [native code] }"}

两个常用hook函数

Object.defineProperty(document, "cookie", {
    get:function(){
        console.log('getting cookie')
    },
    set:function(val){
    	if(val.indexOf('sign')!=-1){
            debugger;
            return val;
        }
}
})
Function.prototype.constructor_bk = Function.prototype.constructor
        Function.prototype.constructor = function(){
            if (arguments[0]=="debugger"){

            }else{
                return Function.prototype.constructor_bk.apply(this, arguments)
            }
        }
### 爬虫逆向工程技术及其实现方法 #### Hook 技术概述 Hook 技术是一种用于拦截和修改程序运行过程中某些特定行为的技术。它可以通过挂钩函数调用链来捕获目标应用程序的行为并对其进行控制或重定向[^1]。在爬虫逆向工程中,这种技术可以用来监控网络请求、解密数据流以及绕过反爬机制。 #### 常见类型的 Hook 技术 常见的 Hook 类型包括 API Hook 和 Inline Hook。API Hook 主要针对操作系统提供的标准库函数进行替换操作;而 Inline Hook 则是在内存层面直接修改指令序列以达到同样的目的。这两种方式都可以帮助开发者深入了解目标系统的内部工作流程,并据此调整自己的抓取策略。 #### 实战应用案例 当面对复杂的现代 Web 应用时,仅仅依靠传统的 HTML 解析已经不足以获取所需的数据资源。此时就需要借助更高级别的手段——即所谓的 “爬虫逆向”。例如,在处理经过加密保护或者动态加载的内容方面,“爬虫逆向” 提供了一系列工具和技术支持,比如 JavaScript 反混淆算法研究、SSL/TLS 握手过程跟踪等等[^2]。 以下是基于 Python 的简单示例代码片段展示了如何使用 `mitmproxy` 来截获 HTTPS 流量: ```python from mitmproxy import http def request(flow: http.HTTPFlow) -> None: if flow.request.pretty_url.startswith("https://example.com/api"): original_payload = flow.request.content.decode('utf-8') modified_payload = modify_request(original_payload) flow.request.content = bytes(modified_payload, 'utf-8') def response(flow: http.HTTPFlow) -> None: decrypted_data = decrypt_response(flow.response.content) flow.response.text = str(decrypted_data) def modify_request(payload): # 自定义逻辑修改请求参数 pass def decrypt_response(encrypted_content): # 使用适当的方法解码响应体 pass ``` 上述脚本实现了对指定 URL 下所有 POST 请求载荷的篡改功能,同时还具备基本的应答消息解密能力。 #### 总结 综上所述,掌握好 Hook 技巧对于从事互联网数据采集工作的人员来说至关重要。通过合理运用这些知识不仅能够有效应对各类新型防护措施带来的阻碍,而且还能进一步挖掘隐藏于表面之下的宝贵信息源。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值