Releases: wojiaoyishang/XiaoHeiCat
Release list
1.35 (112)
- 支持每个应用独立配置脚本缓存目录,默认使用
.xhh_scripts。 - “缓存脚本到应用私有目录”默认开启,并通过 LSPosed Remote Preferences 控制是否生效。
- 自定义缓存目录不再自动使用隐藏目录名,仅默认
.xhh_scripts保持隐藏。 - 修复目标应用私有目录缓存必须由目标进程自行写入的问题,避免 XiaoHeiHook 主进程无权限写入。
- 移除
createPackageContext()兜底逻辑,修复包加载阶段递归触发 LSPosed 回调的问题。 - 新增 Root 脚本缓存同步能力,Root 可用且设置开启时由 XiaoHeiHook 直接同步到目标应用私有目录。
- Root 同步会自动设置目标目录和文件权限,目录
700,文件600,owner 为目标应用 UID/GID。 - Root 不可用或同步失败时自动回退为目标进程自缓存。
- 支持多用户、工作空间、分身环境下的目标应用数据目录搜索。
- 关闭“缓存脚本到应用私有目录”后会清理旧缓存目录。
- 新增设置项“使用 Root 同步应用私有脚本缓存”,Root 可用时默认开启。
- 脚本运行索引改为每应用独立保存,避免单应用同步覆盖其他应用索引。
- 新增每应用独立的
<packageName>_script_index_json。 - 新增每应用独立的
<packageName>_script_sync_manifest_json。 - 新增每应用独立的
<packageName>_script_hash_config_json。 - 目标进程优先读取当前应用自己的运行索引,旧全局索引仅作兼容回退。
- 修复重启后部分应用脚本不生效的问题。
- 同步单个应用时不再覆盖其他应用的脚本索引、manifest 和 hash 配置。
- 同步已启用脚本时不再每次扫描全部脚本目录,仅同步已勾选脚本。
- 仅在手动刷新脚本列表、首次无缓存或明确全量同步时扫描全部脚本。
- 修复旧 Metadata 中
settingsSchema=null导致同步崩溃的问题。 - 新增打开 XiaoHeiHook 时打印 LSPosed Remote Preferences 诊断日志。
- 诊断日志会输出已启用应用、脚本索引、hash 配置、manifest、缓存目录、Root 同步状态和缺失脚本状态。
- 新增“不记录日志”开关,默认关闭。
- 开启“不记录日志”后仅实时同步日志到 WebIDE,不再持久化保存日志文件。
- WebIDE Hook 设置窗口新增“不记录日志”选项。
- WebIDE Hook 设置区域改为右上角齿轮弹窗配置除应用总开关外的设置。
- WebIDE Hook 设置切换和保存操作新增加载动画和禁用状态。
- WebIDE 移除右侧“当前脚本 Metadata”组件。
- 修复移除 Metadata 后右侧面板底部内容被遮挡的问题。
- 更新 WebIDE 构建产物并同步到 App assets。
- 更新文档,新增 LSPosed Remote Preferences 与脚本缓存运行机制说明。
- 更新
scripts/bridge.rst的整体调用链说明,并加入到新开发说明章节的引用。
1.34 (111)
- WebIDE/MCP 都关闭且用户划掉 App 时,主进程会延迟检查并主动退出,避免无服务时后台驻留。
- 优化主界面页面加载策略,页面首次进入才初始化,已加载页面切回时复用状态。
- 优化 Apps 页加载流程,减少导航切换时的同步扫描和掉帧。
- Apps 页应用列表使用后台过滤/排序,避免主线程重计算。
- Apps 页启用状态改为缓存读取,减少每行重复查询。
- Apps 页新增 App 图标硬盘缓存,未更新应用优先读取本地缓存图标。
- App 图标缓存支持按
packageName + lastUpdateTime增量刷新。 - Apps 列表改为视口懒渲染,未进入视口附近的应用不渲染完整行内容。
- Apps 列表未进入视口项改为轻量空白卡片占位,避免视觉截断。
- Apps 列表底部 padding 优化,避免和底部导航栏背景衔接时出现被切割感。
- 底部导航栏高度提高,视觉衔接更自然。
- 底部导航页切换动画保留滑动效果,可通过
MainScreen.kt中durationMillis调整速度。
1.33 (110)
- 修复 Hook
.intercept()返回 primitive boolean 时Java.to(...)/return true兼容问题。 - 优化 Hook 返回值转换逻辑,支持显式类型包装、递归 unwrap、primitive boxed 校验。
- 移除 Hook 返回值调试日志,恢复 clean 版本。
- 修复关闭 WebIDE 时可能触发主进程前台服务超时崩溃的问题。
- 禁用主进程
MainProcessKeepAliveService,避免 ColorOS/OPlus 上反复触发 FGS 超时。 - 移除 WebIDE 关闭时主动杀
:webide进程的逻辑,改为正常停止服务。 - 移除 App 关闭时自动杀主进程逻辑,避免误判为崩溃。
- WebIDE 前台服务改为
dataSync类型,提升系统识别度。 - WebIDE 保留 WakeLock / WifiLock,降低后台冻结和断连概率。
- 新增无障碍辅助保活服务,用户可选开启。
- 设置页 MCP 卡片下方新增无障碍保活卡片。
- 支持 Root 直接开启/关闭本应用无障碍服务,无 Root 时跳转系统设置。
- WebIDE 开关仍开启但服务被系统杀掉时,主进程恢复后会尝试重新拉起。
- App 详情页打开时增加脚本软刷新,脚本数量变化时自动更新缓存。
- 手动刷新脚本时仍执行全量扫描并更新缓存。
- WebIDE 工具栏新增代码生成器。
- 代码生成器支持目标类名、方法名、参数类型、返回值类型、修改值和 Hook 点配置。
- 代码生成器支持快速 JSON 导入/导出。
- 代码生成器支持选择是否先 Hook
android.content.Context。 - 代码生成器生成临时文件,首次
Ctrl+S时提示输入文件名保存。 - 简化代码生成器输出模板,去除多余辅助函数和常量抽取。
- 代码生成器未勾选记录示例变量时,不生成相关日志和函数。
- 代码生成器 Hook 目标代码段加入分隔注释。
- 代码生成器按钮移动到运行控制按钮右侧,并单独分组。
- 新建单脚本模板移除
// @grant dex.full。 - 新建单脚本模板在脚本头后加入
// 如果需要捕获全部进程请修改 @process 字段。。 - WebIDE 关闭/刷新页面时,如存在未保存文件,会触发浏览器离开确认。
- WebIDE 标签页右键菜单新增“关闭其他文件”。
- 新建单脚本重名时提示是否覆盖,并可直接打开已有文件。
- 所有前端提示框、输入框替换为 WebIDE 自定义界面组件。
- 文件管理列表表头支持拖拽调整列宽。
- 文件管理列宽支持双击恢复默认值。
- 文件管理列宽保存到本地缓存,刷新页面后保留。
1.32 (109)
- 新增
Java.to(type, value[, options]),用于将 JS 值按目标 Java 类型显式转换。 - 新增 JS 到 Java 参数转换规则,支持基本类型、包装类型、字符串、数组、集合、Map、枚举等常见类型。
- 优化 Java Bridge 直接对象传递,Java 对象、包装对象、NativeJavaObject 不再被二次 JS 化转换。
- 优化
Method.invoke(...)参数处理,现在会按真实目标方法签名进行类型转换。 - 优化 Hook
chain.proceed(args)参数处理,现在会按被 Hook 方法的真实参数类型转换。 - 新增反射方法签名字符串支持,
getDeclaredMethod、getMethod、getDeclaredConstructor、getConstructor可直接传"int"、"java.lang.String"等类型名。 - 新增
Java.use(...)作为Java.type(...)的推荐别名。 - 新增 Java Bridge 类型转换文档,补充 JS 与 Java 数据类型边界说明。
- 新增 Rhino 兼容性说明链接,方便查询当前脚本环境支持的 JS 语法。
- 新增
dex.scanSmali(options),支持按 smali 字符串、常量字符串、invoke 特征快速扫描 dex 方法。 - 新增
dex.forEachMethod(options, callback),支持遍历 dex 方法并在 JS 回调中自定义筛选逻辑。 - 新增
view.scanSmali(options),支持在已有 dex view 上直接进行 smali 特征扫描。 - 新增
view.forEachMethod(options, callback),支持在已有 dex view 上逐方法遍历分析。 - 优化 dex dump/scan API 返回值,返回给 JS 的 Map/List/数组统一转换为 JS 友好对象。
- 修复 dex dump 返回的
paths等字段在 JS 字符串拼接或数组访问时可能出现默认值转换异常的问题。 - 新增动态 dex 扫描文档中的方法定位接口说明,改为 API 接口风格展示。
- 更新脚本示例文档,增加 Smali echo 示例说明,并链接到 GitHub 仓库中的完整
qidian_dex_search.js。 - 更新 OkHttp 示例脚本,避免主动加载不存在的
okhttp3.RealCall导致异常。 - 优化 OkHttp Hook 示例,改为优先 Hook
OkHttpClient.newCall(Request)与实际返回的 Call 对象。 - 优化 OkHttp 示例的反射调用,兼容混淆类和方法包装差异。
- 新增 Java Bridge、反射、Proxy、OkHttp 等 1.32/109 版本示例脚本。
1.31 (108)
更新至 1.31 (108)
JS Runtime 作用域修复
-
修复 Hook 回调、Java SAM 回调、
Java.proxy()回调和 MCP/RPC 回调之间无法共享 JS 顶层变量的问题。 -
每个脚本 Runtime 现在会持有长期稳定的 Rhino global scope。
-
JS 回调执行时会优先回到函数创建时所属的 scope,避免回调过程中丢失顶层变量。
-
顶层
let、var和对象字段现在可以在以下场景中正常保持状态:xposed.hook(...).intercept(function () {})handler.post(function () {})Java.proxy(...)xhh.rpc.register_method(...)
-
修复跨 Java callback 调用 JS 函数时作用域不一致的问题。
-
修复部分脚本中全局变量在 Hook 回调内修改后,RPC 回调读取不到最新值的问题。
-
修复 Rhino callback 重新进入时没有稳定使用原始 parent scope 的问题。
新增 xhh.global 全局状态接口
-
新增 Java-backed 全局状态对象:
xhh.global
-
xhh.global用于在同一目标进程内跨脚本、跨 Hook 回调、跨 RPC 回调保存运行期状态。 -
新增接口:
xhh.global.set(key, value)xhh.global.get(key)xhh.global.has(key)xhh.global.remove(key)xhh.global.clear()xhh.global.keys()xhh.global.size()xhh.global.snapshot()
-
xhh.global可以保存普通 JS 值,也可以保存 Java 运行期对象。 -
xhh.global适用于保存:- 最近一次 Hook 捕获的参数
- 目标 App 对象实例
MethodClassClassLoader- 调试状态
- 跨 RPC 调用的临时上下文
-
xhh.global只保证同一目标进程内共享,不跨进程共享。 -
明确说明不同 Android 进程之间内存隔离,不能通过
xhh.global共享Method、ClassLoader、thisObject等运行期对象。
Java Bridge JS 到 Java 参数转换优化
- 优化 JS 向 Java 传递参数时的类型边界。
- 当参数是普通 JS 值时,会继续根据目标 Java 方法签名自动转换。
- 当参数已经是 Java 对象、Java wrapper 或 Rhino 原生 Java 对象时,不再重复转换,直接传递给 Java 层。
- 修复显式传入 Java 包装类型后仍被转换成 JS number 的问题。
- 修复
Integer.valueOf(...)等 Java 返回值再次传入 Java 方法时被误转为Double的问题。 - 修复
Method.invoke(...)调用时无法按真实目标方法签名转换参数的问题。 java.lang.reflect.Method.invoke(...)现在会根据被调用方法本身的参数类型处理 JS 参数。- 修复反射调用目标参数为
int时,JSnumber被错误传递为java.lang.Double导致IllegalArgumentException的问题。 - 保留 Java 到 JS 的既有传递逻辑,不改变 Hook 参数、返回值和已有 API 的脚本读取方式。
RPC 参数对象访问优化
-
优化
xhh.rpc.register_method(name, callback)中回调参数的 JS 访问体验。 -
RPC/MCP 传入的 JSON 字典参数继续支持点访问:
params.dataparams.keyparams.ivparams.mode
-
保持兼容旧写法:
params.get("data")params.has("data")params.keys()
-
RPC 参数中的数组值支持常见 JS 访问方式:
params.items[0]params.items.lengthparams.items.get(0)
-
修复 RPC 参数直接作为 Java Map 暴露时无法使用
params.xxx点访问的问题。 -
保持 RPC 返回值继续经过 JS 友好转换,便于 WebIDE 和 MCP 客户端读取。
Java Bridge 反射调用稳定性修复
-
修复
JavaObjectWrapper调用java.lang.reflect.Method.invoke(...)时的参数展开问题。 -
修复 Java varargs 场景下 JS 参数数组与 Java
Object...参数之间的转换问题。 -
修复显式 Java 类型对象被当作普通 JS 对象继续转换的问题。
-
修复部分 Java wrapper 调用中基础类型参数匹配错误的问题。
-
优化 JS number 到 Java 基础类型的转换:
intlongfloatdoubleboolean
-
修复目标方法签名为
int,但 JS 层传入Number(...)后被映射为Double的问题。 -
修复目标方法签名为基础类型时,显式 Java boxed value 被二次转换的问题。
-
保持
Java.type()、Java.proxy()、Java.call()、Java.newInstance()等已有入口兼容。
多进程 MCP 边界说明
-
明确 MCP/RPC 方法运行在注册它的目标进程内。
-
明确 Android 不同进程之间内存隔离。
-
Method、ClassLoader、thisObject等 Java 运行期对象不能跨进程保存或调用。 -
当 Hook 生效进程与 MCP 连接进程不一致时,脚本内保存的 Java 对象不会互通。
-
新增文档说明:如果目标 App 有多个进程,应优先让 MCP 调用路由到真正加载目标类、native 库和业务上下文的进程。
-
建议后续 MCP 桥接层支持按进程选择调用目标:
packageNameprocessNamepidscriptIdmethodName
-
当多个进程注册同名 RPC 方法时,不应随机选择进程调用,应返回候选进程或显式指定进程。
Native 调用边界说明
-
补充说明:通过 MCP 远程反射调用 App 方法时,目标方法内部如果依赖 native 库,必须确保 native 库已在当前进程加载。
-
如果当前进程没有加载对应
.so,调用 native 方法会抛出:UnsatisfiedLinkError
-
新增排查建议:
- 确认 MCP 调用所在进程是否正确。
- Hook
System.loadLibrary(...)或Runtime.loadLibrary0(...)查看 native 库加载情况。 - 确认目标 native 方法是否依赖加固壳或动态注册。
- 不建议在错误进程中强行调用依赖 native 的目标方法。
-
对于加固类或壳相关类,推荐优先在 App 原始调用链路中 Hook 记录参数和结果,而不是在错误进程中直接远程调用 native 链路。
WebIDE 与设置界面优化
-
设置页新增“脚本文件夹位置”设置项。
-
用户可以在 App 设置中自定义脚本文件夹路径。
-
默认脚本目录为当前用户 Documents 下的
XiaoHeiHook目录。 -
设置保存后会同步写入脚本根目录配置,供脚本扫描、同步和
xhh.fs.scriptRoot()使用。 -
新增路径校验:
- 路径不能为空。
- 路径必须是绝对路径。
- 已存在路径必须是目录。
-
修改脚本文件夹位置后,会提示用户重新扫描并同步脚本。
-
关于页面新增外部链接按钮:
- 开源仓库
- 开放文档
-
修复关于页面字符串换行显示问题,推荐在
strings.xml中使用\n显式换行。
文件与资源 API 延续优化
- 保持
xhh.fs文件与资源桥接接口。 xhh.fs.scriptRoot()会读取用户设置中的脚本文件夹路径。- 自定义脚本根目录后,多文件脚本和 assets 资源目录会从新位置扫描。
- 保持资源复制目标必须位于目标 App 私有目录内的安全边界。
- 保持 assets API 只能访问当前脚本
assets/目录。 - 保持资源复制返回完整目标路径,便于脚本加载图片、HTML、CSS 和 JSON 等资源。
示例脚本
-
新增作用域与全局状态测试脚本。
-
测试脚本覆盖:
- 顶层
let - 顶层
var - 顶层对象字段
- Hook 回调
- Java SAM 回调
- MCP/RPC 回调
xhh.global
- 顶层
-
新增 MCP 反射调用示例,演示如何:
- 保存目标类名和方法签名。
- 在 MCP 调用时重新解析
Method。 - 处理
int等 Java 基础类型参数。 - 返回调用结果和错误信息。
-
更新多文件 assets 示例,展示应用启动时复制资源到目标 App 私有目录并尝试展示图片。
-
示例中补充多进程与 native 库加载边界说明。
文档
-
文档版本更新至
1.31 (108)。 -
更新脚本 API 文档,新增
xhh.global全局状态接口说明。 -
更新 Java Bridge 文档,说明 JS 到 Java 参数转换规则。
-
更新 MCP 文档,说明 RPC 参数对象、回调作用域和多进程边界。
-
更新边界文档,说明:
- JS Runtime 作用域边界
- Java 对象与 JS 对象转换边界
xhh.global进程边界- MCP 多进程调用边界
- native 库加载边界
-
更新示例文档,加入作用域测试、RPC 反射调用和多文件 assets 示例。
-
修复文档搜索中
ChineseStemmer is not defined导致前端搜索异常的问题。 -
调整 Sphinx 中文搜索配置,补充中文搜索 fallback。
-
修复 RST 标题层级与标题下划线长度问题,避免构建时出现
Title underline too short警告。
1.30 (107)
更新至 1.30 (107)
JS API 返回值稳定化
-
所有保留到 JS 层的主要接口统一改为返回 JS 对象 / JS 数组,避免脚本直接遍历 Java
List<Map>、Map<List>等不稳定结构。 -
新增 JS 返回值规范化工具,用于将 Java 层返回的
Map、List、数组、Throwable、File、Class等转换为 JS 可稳定读取的结构。 -
推荐脚本使用点访问和数组访问:
ret.pathsresults[i].classNamemethods[i].methodName
-
不再推荐旧写法:
ret.get("sources")sources.get(i).get("path")item.get("className")
-
sources、details等字段保留为调试信息,不建议脚本逻辑依赖。
Dex Dump 与 Dex 搜索 API
-
dex.dumpDexCookies(options)返回结构稳定化。- 新增
ok - 新增
count - 新增
outputDir - 新增
paths - 新增
dumpedPaths - 保留
sources作为调试详情
- 新增
-
dex.dumpDexCookies默认输出文件名使用cookie_前缀。- 默认格式:
cookie_<index>_<addressHex>_<fileSize>.dex - 示例:
cookie_000_71d518e000_3777364.dex
- 默认格式:
-
dex.findMethods(query)改为返回 JS 数组。 -
dex.findMethod(query)未找到时返回null。 -
dex.findMethods(query)新增 / 完善 smali 特征搜索。- 支持
smaliContains - 兼容
smaliKeywords - 兼容
smaliKeyword - 兼容
smali
- 支持
-
dex.findMethods支持仅通过 smali 特征定位方法,不再要求必须提供className、methodName或proto。 -
dex.findMethods返回结果统一包含:classNamemethodNameprotodescriptorpathscorereasonsstringsinvokessmaliHead
-
dex.inspectMethodInFile(options)严格化。path必填className必填methodName必填proto可选- 不再默认历史目标方法
- 不再承担搜索职责,只用于精确检查指定方法
-
dex.locateMethodInCookieDumps(options)严格化。className必填methodName必填proto可选- 不再默认历史目标方法
-
dex.dumpClassDex(options)返回稳定字段:okcountpathsdumpedfailed
-
dex.dumpLoadedClassDex(options)返回稳定字段:okclassNamepathpathssize
-
dex.dumpMemory(options)返回稳定字段:okcountoutputDirpathsdumped
-
dex.scanMemory(options)/dex.dumpMemoryRaw(options)增加稳定candidates字段。 -
dex.runtimeSources()改为返回 JS 数组。 -
dex.runtimeLoaders()改为返回 JS 数组。 -
dex.registerLoader(loader, path)严格化。loader必须是ClassLoaderpath必须是非空字符串- 非法参数不再兜底为默认 loader
-
dex.setLimits(options)/dex.limits()返回稳定 JS 对象。
移除 Dex 旧式过渡接口
-
移除或不再作为 JS 推荐接口暴露以下过渡 API:
dex.scanDumpDirdex.fromDumpDirdex.dumpCookieDexdex.dumpFromCookiesdex.dumpRawDexdex.traceStringsdex.inspectDumpedMethoddex.findMethodInCookieDumpsdex.dumpUnpackedDexForMethoddex.dumpTargetDexdex.dumpDexForMethod
-
新脚本应直接使用:
dex.dumpDexCookies(...)ret.pathsdex.findMethods(...)dex.inspectMethodInFile(...)
JS 对象与 Java 对象边界
-
新增对象类型判断 API:
xhh.objectKind(value)xhh.isJsObject(value)xhh.isJavaObject(value)
-
xhh.objectKind(value)返回稳定 JS 对象,包含:kindisJsObjectisJavaObjectisPrimitiveisNullisUndefinedrawClassjavaClasstext
-
文档中明确推荐使用 JS 对象 / JS 数组编写脚本逻辑。
-
Java 对象仅用于调用 Android / Xposed / App 运行时方法,不建议把 Java
Map/List当作脚本数据结构使用。
Rhino / JS 语法边界
-
JS 运行时继续基于 Rhino。
-
运行时显式启用 ES6 语言版本。
-
新增
xhh.jsEngine(),用于查看当前 JS 引擎能力。 -
发现并记录 Rhino 在循环体内
const/let词法绑定上的局限:for (...) { const path = paths[i]; }在部分 Rhino 场景可能不能可靠地每轮重新绑定。
-
取消 “ES6 词法绑定自检失败即阻断脚本启动” 的行为。
-
当检测到 Rhino 不支持可靠循环词法绑定时,脚本仍可继续运行,并通过
xhh.jsEngine()查看状态。 -
新增稳定遍历 API:
xhh.each(items, callback)
-
推荐遍历
ret.paths、results等数组时使用:xhh.each(paths, function (path, i) { ... })
-
文档中新增 “JS 脚本语法边界说明”,明确
const的适用范围与推荐通用语法。
Xposed JS API
-
xposed.e(tag, msg, any)第三参处理增强。- 支持 Java
Throwable - 支持 JS Error
- 支持普通对象
- 支持字符串
- 支持
null/undefined
- 支持 Java
-
xposed.getJavaStackTrace()返回 JS 数组。 -
xposed.getAppStackTrace()返回 JS 数组。 -
xposed.stackTrace()返回 JS 数组。 -
xposed.listRemoteFiles()返回 JS 字符串数组。 -
xposed.getFrameworkProperties()返回稳定 JS 对象。 -
xposed.getModuleApplicationInfo()返回稳定 JS 对象。 -
xposed.raw.call(...)返回值经过 JS 稳定化转换。 -
Hook 回调中的
chain.getArgs()返回 JS 数组。
XHH / RPC / MCP API
xhh.info()返回稳定 JS 对象。xhh.hasGrant(name)保持布尔返回。xhh.rpc.register_method(name, callback)返回稳定 JS 对象。xhh.rpc.unregister_method(name)返回稳定 JS 对象。xhh.rpc.unregister_all_methods()返回稳定 JS 对象。- MCP
list_methods返回methods: [],每一项为稳定 JS 对象。 - MCP
invoke_method的result尽量经过 JSON-safe / JS-safe 转换。 - RPC 回调返回值统一经过稳定化处理,减少 Java 对象泄漏到 JS/MCP 边界。
Settings / Env / Console / Java API
-
settings.get(key)返回值经过 JS 稳定化转换。 -
settings.all()返回稳定 JS 对象。 -
env文档补充常用字段说明。 -
console文档补充与xposed日志的推荐使用方式。 -
Java.type(name)文档补充 Java 对象边界说明。 -
明确 Java 对象与 JS 对象的职责划分:
- Java 对象用于反射和运行时调用。
- JS 对象用于脚本配置、返回值和业务逻辑。
示例脚本
-
更新脱壳示例为新版推荐格式:
dex.dumpDexCookies(...)ret.pathsxhh.isJsObject(ret)
-
更新 Smali 特征查找示例:
- 使用
dex.findMethods({ path, smaliContains, limit }) - 使用
xhh.each(paths, callback)遍历 - 找到第一个匹配后
return false停止搜索 - 最后输出命中的 dex 文件、类名、方法名和方法签名
- 使用
-
移除旧示例中的:
scanDumpDirfromDumpDir- Java
Map.get - Java
List.get - 正则解析
dumpRet.toString()
-
新增 / 更新 smoke test 示例,覆盖主要 JS API 返回值稳定性。
文档
- 参考 Python 文档风格重写 JS API 文档。
- API 参考改为 “一个标题一个方法” 的形式,便于查阅。
scripts/js_api.rst重写为 JS API 总参考。scripts/dynamic_dex_scan/source_api.rst重写为 Dex Source API 参考。scripts/examples.rst更新为新版推荐脚本。scripts/boundaries.rst补充 JS 语法边界、对象边界和 Rhino 限制。scripts/dynamic_dex_scan/examples.rst更新脱壳与特征查找示例。- 修复 RST 标题下划线过短导致的
Title underline too short警告。
WebIDE 运行控制优化
-
优化 WebIDE 中目标应用重启与终止逻辑。
-
“重启并同步” 现在会优先使用 Root 权限关闭并重新打开目标应用。
-
“重启同步并调试” 现在会优先使用 Root 权限关闭并重新打开目标应用,再进入调试流程。
-
当设备具备 Root 权限时,WebIDE 可通过 Root 执行
force-stop与启动命令,不再要求 XiaoHeiHook 当前处于前台。 -
当设备没有 Root 权限时,仍使用普通 Android 启动方式,此时需要 XiaoHeiHook 处于前台才能可靠拉起目标应用。
-
优化 Root 启动策略。
- 优先使用
am start启动目标应用入口 Activity。 - 无法解析入口 Activity 时,回退使用
monkey启动目标应用。
- 优先使用
-
“终止调试/运行” 按钮行为调整。
- 无论当前是否处于调试模式,都会强制终止目标应用。
- 有 Root 权限时使用 Root
force-stop。 - 无 Root 权限时使用普通终止能力。
-
WebIDE API 返回信息增加运行控制状态字段,便于前端判断执行结果。
launchModerootLaunchOkrootLaunchMessageterminatedterminate
JS Runtime Java Bridge 重构
- 重构 JS Runtime 的 Java Bridge,将原本集中在
JsHookRuntime内的桥接逻辑拆分为独立模块,提升维护性。 Java.type()现在返回 JS 友好的JavaClassWrapper,不再直接返回裸java.lang.Class。- 新增 JavaClass wrapper 语法,支持直接读取静态字段,例如
Toast.LENGTH_SHORT。 - 新增 JavaClass wrapper 静态方法调用,支持
Looper.getMainLooper()等自然写法。 - 新增 JavaClass wrapper 构造函数调用,支持
new Handler(Looper.getMainLooper())。 - 新增 JavaObject wrapper,支持 Java 实例方法直接调用,例如
handler.post(...)、toast.show()。 - 新增 Java 对象字段读取与写入的 wrapper 支持。
- 新增 raw Class 入口,支持
classObject与getRawClass()获取原始java.lang.Class。 - 新增
java.lang.Class方法透传能力,支持Application.getDeclaredMethod(...)等反射写法。 - 新增 Java varargs 参数转换,支持
getDeclaredMethod("attach", ContextClass)这类调用。 - 新增 JS function 到 Java SAM 接口的自动代理转换,支持
handler.post(function () {})。 - 新增显式
Java.proxy()支持,可用于Runnable、listener、callback 等 Java 接口实现。 - 增强
Java.proxy()对单方法接口 function 写法与多方法接口 object 写法的支持。 - 增强 Rhino Context 进入逻辑,确保 Java proxy 回调可以安全调用 JS 函数。
- 增强 Java 方法、构造器和字段解析,统一处理重载评分、参数转换和返回值包装。
- 优化数字参数重载选择,使整数 JS number 优先匹配 Java
int/long,避免误选double重载。 - 修复
StringBuilder、AtomicInteger等构造返回值被错误当作 JS 基础值的问题。 - 保留低层反射 API,包括
Java.callStatic()、Java.call()、Java.newInstance()、Java.get()、Java.set()等。 - 调整
xposed.hook()等入口,支持接收 wrapper 返回的Method、Class等对象。
文件与资源桥接 API
-
新增
xhh.fs文件与资源桥接接口。 -
新增目标 App 私有目录查询能力。
xhh.fs.appDirs(context)- 通过目标 App
Context动态读取私有目录。 - 不再要求脚本硬编码
/data/user/0、/data/data或/sdcard。 - 兼容多用户、多 profile 与目标 App 真实运行用户。
-
新增基础文件操作接口。
xhh.fs.join(...)xhh.fs.exists(path)xhh.fs.isFile(path)xhh.fs.isDirectory(path)xhh.fs.mkdirs(path)xhh.fs.readText(path[, charsetOrOptions])xhh.fs.writeText(path, text[, charsetOrOptions])xhh.fs.appendText(path, text[, charsetOrOptions])xhh.fs.readBytes(path[, options])xhh.fs.writeBytes(path, bytes[, options])xhh.fs.copy(src, dst[, options])
-
文本和二进制读取默认限制为 16MB,避免目标 App 进程因误读大文件导致 OOM。
-
读取上限可通过参数调整,适合少量配置、HTML、CSS、图片等脚本资源场景。
-
新增脚本路径查询接口。
xhh.fs.scriptRoot()xhh.fs.scriptDir()xhh.fs.assetsDir()xhh.fs.assetPath(relativePath)
-
脚本根目录默认解析为当前用户 Documents 下的
XiaoHeiHook目录。 -
脚本根目录支持通过设置修改,不再在 JS API 实现中硬编码。
-
新增脚本 assets 读取接口。
xhh.fs.readAssetText(relativePath[, charsetOrOptions])xhh.fs.readAssetBytes(relativePath[, options])
-
assets资源访问严格限制在当前脚本自己的assets/目录内。 -
禁止通过 assets API 读取脚本源码、其他脚本资源或 assets 外部文件。
-
新增资源复制到目标 App 私有目录的接口。
xhh.fs.appAssetDir(context[, options])xhh.fs.copyAssetToApp(context, assetRelativePath[, targetRelativePath[, options]])xhh.fs.syncAssetsToApp(context[, options])
-
copyAssetToApp返回值包含复制后的完整目标路径,便于脚本直接用于ImageView、WebView、本地配置文件等场景。 -
资源复制目标必须位于目标 App 私有
filesDir内。 -
复制目标子路径可由脚本指定,但必须是安全相对路径。
-
禁止复制目标路径出现绝对路径、
../目录穿越或符号链接逃逸。 -
syncAssetsToApp支持递归同步当前脚本assets/目录到目标 App 私有目录。 -
syncAssetsToApp默认覆盖已有资源。 -
clean=true时只清理当前脚本自己的资源同步目录,不会删除目标 App 其他私有文件。 -
本版本不为文件 API 增加独立 grant 权限项,保持与现有脚本权限模型兼容。
多文件脚本与 assets 资源目录
-
多文件脚本支持在脚本目录中放置
assets/目录。 -
推荐目录结构:
index.jsmain.jslib/assets/data/config.jsonassets/panel/index.htmlassets/images/icon.png
-
require()仍只用于加载 JS 模块。 -
assets/只作为资源目录,不会被当作 JS 模块目录执行。 -
脚本资源在同步时会进入 XiaoHeiHook 的脚本资源体系,目标 App 进程中可通过
xhh.fs读取或复制。 -
推荐脚本先将图片、HTML、CSS、JSON 等资源复制到目标 App 私有目录,再交给目标 App 的
ImageView、WebView或普通文件 API 使用。 -
不推荐让目标 App 直接访问脚本根目录或外部存储目录。
路径安全与运行边界
- 明确文件路径边界:脚本目录、脚本 ...
1.20 (102)
更新至 1.20 (102)
Dex 分析能力
- 新增 Android 端 Dex 分析入口:
top.lovepikachu.XiaoHeiHook.dex.DexApiFacade。 JsHookRuntime新增全局对象dex注入能力。- 新增
org.smali:dexlib2:2.5.2依赖,用于解析 Dex 字节码。 - 新增
dex.fromLoader(loader),支持从目标 App 的ClassLoader解析 Dex。 - 新增
dex.fromFile(path),支持直接解析指定 Dex / APK 文件。 - 新增
dex.findMethod(query),支持按特征定位单个方法。 - 新增
dex.findMethods(query),支持按特征批量搜索方法。 - 新增 DexFile 级 API:
classes()strings()
- 新增 Class 级 API:
methods()fields()strings()
- 新增 Method 级 API:
strings()invokes()instructions()smali()
- 新增
method.toMethod(loader),支持将 Dex 方法映射为运行时 JavaMethod。 - 支持按字符串、调用关系、类名、方法名、返回值、参数等条件搜索目标方法。
- 支持输出目标方法的 smali 片段,便于分析 Hook 点。
WebIDE
- 修复点击折叠区域时误触发断点的问题。
- WebIDE 断点点击逻辑调整为只响应行号区和 glyph margin。
示例与文档
- 新增示例脚本:
sample_scripts/xhh_dex_scan_example/index.js。 - 新增说明文档:
DEX_API_INCREMENTAL_README.md。
JS 运行时
- 修复 Rhino 正则表达式不可用的问题。
- JS 运行时已支持标准正则表达式用法。