js-hooker

June 2, 2026 · View on GitHub

English | 简体中文

一个轻量、简洁的 适用于浏览器环境的JavaScript Hook库

Github

NPM

简介

支持对函数、访问器、构造函数进行hook 并实现阻止执行、修改执行参数、修改返回值等功能

适用于网页脚本(如TamperMonkey脚本 浏览器扩展ContentScript)开发 需要对函数功能进行修改的情况

使用方法可参考项目https://github.com/NativeStar/Kyouka

使用方法

安装

npm i js-hooker

导入并创建实例

import {Hooker} from "js-hooker"
const hooker=new Hooker();

使用示例

//阻止alert弹窗
hooker.hookMethod(window,"alert",{
    beforeMethodInvoke(args, abortController) {
        abortController.abort();
    }
});
// 打印fetch请求数据
hooker.hookAsyncMethod(window,"fetch",{
    beforeMethodInvoke(args, abortController) {
        console.log(args)
    }
});
//阻止设置script元素的src属性
hooker.hookAccessor(HTMLScriptElement.prototype, "src", {
    beforeSetterInvoke(arg, abortController) {
        abortController.abort();
    },
});
//拦截new Function操作并替换为执行空代码
hooker.hookObject(window,"Function",{
    beforeConstruct(_args, abortController, tempObject, originConstruct) {
        abortController.abort();
        tempObject.current = originConstruct("");
    },
});

文档

构造函数

originReference:设置默认方法引用 仅建议在需要多个Hooker实例时使用

enableBypassDefault:是否默认启用绕过hook检测

internalTagSymbol:设置用于判断方法hook的内部symbol 仅建议在需要多个Hooker实例时使用

Hooker.getOriginReference() (静态方法)

获取目前的原始方法引用快照 用于创建新Hooker实例时使用 亦可留作脚本自用

hookMethod(parent, methodName, hookOption)

对指定的同步方法执行hook

parent:目标方法所在的的父对象

methodName:目标方法名

hookOption:执行hook的设置:

  • enableBypass?:hook时是否执行检测绕过 该项优先级高于enableBypassDefault
  • descriptor?:设置hook代理时使用的描述符 仅在对方法首次hook时生效
  • id?:唯一标识 如无需unhook或检查hook状态可忽略
  • beforeMethodInvoke?:在方法调用前触发的回调:(arg, abortController, thisArg, tempMethodResult, originMethod)

args:方法执行时传入的参数 可以进行修改

abortController:中断执行控制器 调用abort将中断方法执行

thisArg:方法执行时的this指向

tempMethodResult:可修改的临时返回值 注意这里的返回值设置仅在中断执行时生效

originMethod 原始方法 可调用(部分方法执行时注意this指向)

  • afterMethodInvoke?:在方法调用后触发的回调:(args, tempMethodResult, thisArg, originMethod)

args:方法执行时传入的参数 此时修改参数已基本无意义

tempMethodResult:可修改的预期返回值

thisArg:方法执行时的this指向

originMethod:原始方法 可调用(部分方法执行时注意this指向)

  • onInvokingError?:当执行方法发生异常时调用:(args, throwAbortController, tempError, tempResult,thisArg, originMethod)

args:方法执行时传入的参数 此时修改参数已基本无意义

throwAbortController:中断异常抛出控制器 调用abort将中断异常抛出并正常返回tempResult中的值

tempError:抛出的异常实例 可修改并影响最终抛出内容

tempResult:可修改的临时返回值 将在中断抛出后正常返回

thisArg:方法执行时的this指向

originMethod 原始方法 可调用(部分方法执行时注意this指向)

hookAsyncMethod(parent, methodName, hookOption)

对指定的异步方法执行hook 使用方法和hookMethod方法一致

hookAccessor(parent, target, hookOption)

对指定的访问器执行hook

parent:目标访问器所在的的父对象

methodName:目标访问器名

hookOption:执行hook的设置:

  • enableBypass?:hook时是否执行检测绕过 该项优先级高于enableBypassDefault
  • descriptor?:设置hook代理时使用的描述符 仅在对方法首次hook时生效
  • id?:唯一标识 如无需unhook或检查hook状态可忽略
  • beforeGetterInvoke:在getter方法执行前触发:(abortController, thisArg, tempMethodResult)

abortController:中断执行控制器 调用abort将中断方法执行

thisArg:方法执行时的this指向

tempMethodResult:可修改的临时返回值 注意这里的返回值设置仅在中断执行时生效

  • afterGetterInvoke:(tempMethodResult, thisArg)

tempMethodResult:可修改的预期返回值

thisArg:方法执行时的this指向

  • beforeSetterInvoke:(arg, abortController, thisArg)

arg:方法执行时传入的参数 可以进行修改

abortController:中断执行控制器 调用abort将中断方法执行

thisArg:方法执行时的this指向

hookObject(parent,objectName,hookOption)

对指定的可实例化对象执行hook

parent:目标对象所在的的父对象

methodName:目标对象名

hookOption:执行hook的设置:

  • enableBypass?:hook时是否执行检测绕过 该项优先级高于enableBypassDefault
  • descriptor?:设置hook代理时使用的描述符 仅在对方法首次hook时生效
  • id?:唯一标识 如无需unhook或检查hook状态可忽略
  • afterGet:尝试获取对象内属性时触发:(prop, tempResult)

prop:获取的参数名称

tempResult:可供修改的预期返回值

  • afterHas:通过Reflect.has或in操作符检测是否含有指定属性时触发:(prop,tempResult)

prop:获取的参数名称

tempResult:可供修改的预期返回值

  • beforeConstruct:通过new操作符等方式创建新实例前触发:(args, abortController, tempObject,originConstruct)

args:对构造方法传入的参数 可以进行修改

abortController:中断执行控制器 调用abort将中断创建实例

tempObject:临时缓存的新实例返回 可用于修改返回值 注意这里修改的返回值仅在中断执行时生效

originConstruct:原始构造方法 可实例化

  • afterConstruct:通过new操作符等方式创建新实例后触发:(args,tempObject,originConstruct)

args:对构造方法传入的参数 此时修改参数已基本无意义

tempObject:可供修改的返回值 需为一个对象

originConstruct:原始构造方法 可实例化

  • beforeSet:往对象内设置属性时触发:(prop, value, abortController, tempNewValue, tempReturnValue)

prop:属性名

value:调用时传入要设定的属性值

abortController:中断执行控制器 调用abort将中断属性设置

tempNewValue:可供修改的新属性值

tempReturnValue:可供修改的返回值 用于Reflect.set等的返回

  • beforeDelete:尝试删除对象内属性时触发:(prop, deleteController, tempReturn)

prop:要删除的属性

deleteController:中断执行控制器 调用abort将中断属性删除

tempReturn:可供修改的返回值 用于Reflect.delete等的返回

  • beforeDefineProperty:通过defineProperty类方法定义对象内属性时触发:(prop, descriptor, abortController, tempResult)

prop:属性名

descriptor:传入的属性描述符

abortController:中断执行控制器 调用abort将中断设置属性

tempResult:可修改的临时返回值 注意这里的返回值设置仅在中断执行时生效

unhook(type, parent, name, id,autoRestore)

取消指定id的hook

type:准备取消hook属性的类型

parent:准备取消hook属性的父对象

name:准备取消hook属性的名称

id:准备取消的hook id

autoRestore:当目标方法已无挂载hook时是否自动还原原始属性

restoreHook(type, parent, targetName)

还原指定方法为原始方法并移除所有hook

type:准备还原属性的类型

parent:准备还原属性的父对象

targetName:准备还原属性的名称

ensureOriginExecutable(target)

传入被hook的对象并返回其原始对象 如果传入对象未被hook则将其原路返回

target:目标对象

isHooked(target)

判断传入的对象是否已经过hook

target:目标对象

isHookedById(type, parent, target, id)

检查指定id的hook是否已挂载到指定属性上

type:被hook属性的类型

parent:准备检查hook属性的父对象

target:准备检查hook属性的名称

id:目标hook id

internalSymbol (实例属性)

返回实例内部用于标记hook方法的symbol

originReference(实例属性)

返回实例内部保存的部分方法引用 获取后可调用避免使用可能被页面污染的方法

快速Hook工具

在进行一些简单、重复的hook操作时降低代码量 均为静态方法

FastUtils.hookAbortMethodExecute(hooker,parent,methodName,methodType,onExecuteCallback,defaultReturnValue)

用于快速创建拦截方法执行的hook

hooker:Hooker实例

parent:目标方法所在父对象

methodName:目标方法名

methodType:目标方法类型,值为"async"或"sync"

onExecuteCallback?:方法执行时触发的回调

defaultReturnValue?:方法执行时返回的默认值

hookInterruptMethodExecute(hooker,parent,methodName,methodType,interruptType)

当方法执行时触发debugger断点

hooker:Hooker实例

parent:目标方法所在父对象

methodName:目标方法名

methodType:目标方法类型,值为"async"或"sync"

interruptType:中断触发类型,值为"before"(执行前触发) "after"(执行后触发) "all"(执行前后都触发)

hookPrintMethodExecuteArgs(hooker,parent,methodName,methodType)

用于快速创建打印方法参数的hook

hooker:Hooker实例

parent:目标方法所在父对象

methodName:目标方法名

methodType:目标方法类型,值为"async"或"sync"

注意事项

  • 建议只创建一个Hooker实例 如果必须创建多个实例 应尽早通过Hooker.getOriginReference方法获取原始方法引用并在创建后来的Hooker实例时将其传入 避免使用到受污染的方法
const originRef=Hooker.getOriginReference();
const hooker1=new Hooker({originReference:originRef})
const hooker2=new Hooker({originReference:originRef})

  • 如果使用多个Hooker实例 应避免两个或以上的实例同时hook同一个方法 否则会导致hook失效或其他异常
//不可多实例hook同一个方法!
//这是错误示例
const hooker1=new Hooker();
const hooker2=new Hooker();
hooker1.hookMethod(window,"alert",{});
hooker2.hookMethod(window,"alert",{});
  • 作为用户脚本或浏览器扩展使用时建议尽早注入(document-start阶段)并创建实例 避免页面保存方法引用导致hook失效或页面修改了原生方法导致异常
  • 该项目仅对Hook原生方法(alert open等)的行为进行测试 不保证在hook正常创建的方法时完全正常工作
  • 如果需要hook非原生方法 建议对该方法关闭hook隐藏(hookOption对象内传入enableBypass:false)
  • 由于eval函数的特殊性质 请谨慎对eval函数进行hook 否则某些网站会出现异常(拦截执行除外)