免责声明 本项目的所有内容仅供学习与技术交流使用,旨在帮助开发者理解移动应用的结构和工作原理。 本项目不包含任何针对特定应用的破解操作或侵权内容。 针对某些app存在的简单解包技术内容在各大技术论坛网站均大量存在,并无对这些app造成实际损害 本项目无意协助任何非法用途,包括但不限于绕过版权保护、修改应用功能或获取未经授权的数据。 请确保在使用本项目工具时遵守相关法律法规,并仅用于个人学习或研究目的。
简体中文 | English
# 欢迎使用hooker逆向工作台      hooker是一个基于frida实现的逆向工具包。旨在为安卓逆向开发人员提供一个舒适的命令行界面和一些常用的通杀脚本、自动化生成hook脚本、内存漫游探测activity和service、frida版JustTrustMe、boringssl unpinning全网app通杀 为什么你需要hooker? ================= * [1. frida版JustTrustMe,通杀全网APP,且作者一直在持续维护升级](#11-frida版JustTrustMe包括boringgssl) * [2. 自动化生成frida脚本,1秒钟生成一个脚本,脚本备注详细可扩展性强](#7-自动化生成frida脚本) * [3. 快捷设置socks5代理,无需额外安装socksdroid等三方app实现无感知代理](#10-快捷设置socks5无感代理) * [4. 整个使用过程非常舒适的命令行提示,让你享受逆向的过程](#7-自动化生成frida脚本)
---
目录
=================
* [快速开始](#快速开始)
* [1. git clone项目](#1-git-clone项目)
* [2. 安装依赖](#2-安装python3依赖)
* [3. root手机usb连接](#3-root手机usb连接PC)
* [4. 启动hooker](#4-启动hooker)
* [5. 输入调试应用包名](#5-输入调试应用包名)
* [6. 查看help信息](#6-查看help信息)
* [7. 自动化生成frida脚本](#7-自动化生成frida脚本)
* [8. 列出所有frida脚本](#8-列出应用目录所有frida脚本)
* [9. attach执行frida脚本](#9-attach执行frida脚本)
* [10. 快捷设置socks5无感代理](#10-快捷设置socks5无感代理)
* [11. frida版JustTrustMe](#11-frida版JustTrustMe包括boringgssl)
* [12. spawn执行frida脚本](#12-spawn执行frida脚本)
* [13. 取消代理设置](#13-取消代理设置)
* [14. 重启app](#14-重启app)
* [15. 获取uid和pid](#15-获取uid和pid)
* [16. pull文件](#16-pull文件)
* [17. r0capture](#16-r0capture)
* [18. hooker自动升级](#17-upgrade)
* [应用工作目录脚本](#应用工作目录脚本)
* [url.js](#urljs)
* [just_trust_me.js](#just_trust_mejs)
* [activity_events.js](#activity_eventsjs)
* [click.js](#clickjs)
* [android_ui.js](#android_uijs)
* [keystore_dump.js](#keystore_dumpjs)
* [edit_text.js](#edit_textjs)
* [hook_register_natives.js](#hook_register_nativesjs)
* [text_view.js](#text_viewjs)
* [ssl_log.js](#ssllogjs)
* [just_trust_me_for_ios.js](#just_trust_me_for_iosjs)
* [dump_dex.js](#dump_dexjs)
* [trace_init_proc.js](#trace_init_procjs)
* [hook_artmethod_register.js](#hook_artmethod_registerjs)
* [find_anit_frida_so.js](#find_anit_frida_sojs)
* [hook_jni_method_trace.js](#hook_jni_method_tracejs)
* [replace_dlsym_get_pthread_create.js](#replace_dlsym_get_pthread_createjs)
* [find_boringssl_custom_verify_func.js](#find_boringssl_custom_verify_funcjs)
* [get_device_info.js](#get_device_infojs)
* [apk_shell_scanner.js](#apk_shell_scannerjs)
* [bypass_frida_svc_detect.js](#bypass_frida_svc_detectjs)
* [bypass_root_detect.js](#bypass_root_detectjs)
* [bypass_vpn_detect.js](#bypass_vpn_detectjs)
* [hook_encryption_algo.js](#hook_encryption_algojs)
* [hook_encryption_algo2.js](#hook_encryption_algo2js)
* [webview_enable_debug.js](#webview_enable_debugjs)
* [Windows安装WSL](#windows安装wsl)
* [1. 安装wsl ubuntn24.04](#1-安装wsl-ubuntn2404)
* [2. 进入wsl,配置代理](#2-进入wsl配置代理)
* [3. 安装python3.8和frida](#3-安装python38和frida)
* [自定义frida-server](#自定义frida-server)
* [hooker命令行快捷键](#hooker命令行快捷键)
手机保证root,无需任何手动启动frida-server等一切配置,hooker会帮你搞定一切。x86架构的模拟器不兼容
# Mac/Linux配置hooker运行环境
Windows请先完成[WSL安装](#windows%E5%AE%89%E8%A3%85wsl),然后跳回到这里
### 1. git clone项目
```shell
stephen@Mac:~$ git clone https://github.com/CreditTone/hooker.git
stephen@Mac:~$ cd hooker
```
### 2. 安装python3依赖
```shell
stephen@Mac:~/hooker$ pip3 install -r requirements.txt
```
### 3. root手机usb连接PC
```shell
stephen@Mac:~/hooker$ adb devices
List of devices attached
FA77C0301476 device
```
### 4. 启动hooker
这里注意,不要用绝对路径去执行,一定要cd到hooker目录下执行python3 hooker.py
hooker启动后将收集所有可调试app的信息,字段含义如下
- PID:当前app的主进程id,如果app没有启动则为0
- APP:app的名称
- IDENTIFIER:app的包名
- EXIST_REVERSE_DIRECTORY:如果app曾经被调试过就是✅,从没被调试过就是❌
```shell
stephen@Mac:~/hooker$ python3 hooker.py
hooker Let's enjoy reverse engineering together
-----------------------------------------------------------------------------------------------
PID APP IDENTIFIER EXIST_REVERSE_DIRECTORY
0 全球上网 com.miui.virtualsim ❌
0 爱奇艺 com.qiyi.video ❌
0 红手指云手机 com.redfinger.app ❌
0 Reqable com.reqable.android ❌
0 美团 com.sankuai.meituan ✅
0 得物 com.shizhuang.duapp ❌
0 某皮 cxm.shxpxx.sg ✅
0 微博 com.sina.weibo ❌
0 今日头条 com.ss.android.article.news ✅
0 西瓜视频 com.ss.android.article.video ✅
0 懂车帝 com.ss.android.auto ✅
0 抖音火山版 com.ss.android.ugc.live ✅
0 抖音精选 com.ss.android.yumme.video ❌
0 淘宝 com.taobao.taobao ✅
0 腾讯视频 com.tencent.qqlive ❌
0 Termux com.termux ❌
0 轻奢 com.tm.bachelorparty ✅
0 WiFi ADB com.ttxapps.wifiadb ❌
0 VMOS Pro com.vmos.pro ✅
0 游戏中心 com.xiaomi.gamecenter ❌
0 小米商城 com.xiaomi.shop ❌
0 米家 com.xiaomi.smarthome ❌
0 小米有品 com.xiaomi.youpin ✅
0 小红书 com.xingin.xhs ✅
0 运满满货主 com.xiwei.logistics.consignor ✅
0 拼多多 com.xunmeng.pinduoduo ✅
0 EnvCheck com.yimian.envcheck ✅
0 check_env com.yuuki.check_env ❌
0 TikTok com.zhiliaoapp.musically ❌
0 XPrivacyLua eu.faircode.xlua ❌
0 imToken im.token.app ❌
0 SocksDroid net.typeblog.socks ❌
0 F-Droid org.fdroid.fdroid ❌
0 ProxyDroid org.proxydroid ❌
3457 手机管家 com.miui.securitycenter ✅
3509 优信拍 com.uxin.buyerphone ✅
18780 抖音 com.ss.android.ugc.aweme ✅
20174 应用商店 com.xiaomi.market ❌
20913 设置 com.android.settings ❌
30500 小爱同学 com.miui.voiceassist ❌
32163 相机 com.android.camera ✅
Please enter the identifier that needs to be reversed
hooker(Identifier):
```
***
### 5. 输入调试应用包名
- 输入调试应用包名回车后,如果是第一次调试应用,hooker将创建应用目录,应用目录名称为应用的Identifier,用于存放所有js脚本和快捷命令。
- hooker将帮你检测当前app是否启动且在手机前台,如不在启动帮你启动,如不在前台帮你切到前台
- frida通杀脚本可以在hooker交互式命令行下用attach/spawn执行,也可以手动cd到应用目录用快捷命令或原生的frida命令执行。
- 你可以修改应用工作目录下任何脚本
```shell
hooker(Identifier): cxm.shxpxx.sg
✅ App cxm.shxpxx.sg is already in the foreground
Creating working directory: cxm.shxpxx.sg
Generating frida shortcut command...
Generating built-in frida script...
pull /data/app/cxm.shxpxx.sg-L8zkrpFVICv0-hOrtmPPxA==/base.apk to cxm.shxpxx.sg/ShopeeSG_3.43.40.apk successful
Working directory create successful
just_trust_me.js empty.js keystore_dump.js
edit_text.js activity_events.js find_boringssl_custom_verify_func.js
ssl_log.js hook_register_natives.js click.js
get_device_info.js apk_shell_scanner.js dump_dex.js
object_store.js hook_artmethod_register.js replace_dlsym_get_pthread_create.js
just_trust_me_for_ios.js trace_initproc.js android_ui.js
hook_jni_method_trace.js url.js just_trust_me_okhttp_hook_finder_for_android.js
text_view.js find_anit_frida_so.js
某皮 >
```

***
### 6. 查看help信息
在使用hooker过程中,如不记得命令,可随时调出help查看操作手册。
```shell
某皮 > help
h, help show this help message
a, activitys show the activity stack
s, services show the service stack
o, object [object_id] show object info by object_id
v, view [view_id] show view info by view_id of view
gs, generatescript [class_name:method_name] specify the class name and method name to generate a frida hook java script file. For example: generatescript
okhttp3.Request$Builder:addHeader
p, proxy [socks5_proxy_server] set up a socks5 proxy for this app. For example: proxy socks5://192.168.0.100:9998
up, unproxy remove socks5 proxy for this app
trust, justtrustme quickly spawn just_trust_me.js script to kill all ssl pinning
ls list all the frida scripts of the current app
attach [script_file_name] quickly execute a frida script, similar to executing the command "frida -U com.example.app -l xxx.js". For example: attach url.js
spawn [script_file_name] quickly spawn a frida script, similar to executing the command "frida -U -f -n com.example.app -l xxx.js". For example: spawn
just_trust_me.js
restart restart this app
pid get pid of this app main process
uid get pid of this app
exit return to the previous level
某皮 >
```

***
### 7. 自动化生成frida脚本
自动化生成脚本是hooker的杀器。虽然现在AI大模型也可以写,但是我们离内存近,更快,也不需要联网。生成的脚本自带打印堆栈等信息,和一些你可能需要的扩展方法。
另外在生成脚本的过程中,命令行类名、方法名提示也可以当作搜索使用,能通过关键词快速搜索定位类方法。hooker搜索类比jadx快很多,不信就试试......

- Command语法:gs, generatescript [class_name:method_name]
- 7.1 生成指定方法的frida hook脚本:
gs okhttp3.Request$Builder:addHeader,参数部分(String, String)不是必须写的
```shell
某信拍 > gs okhttp3.Request$Builder:addHeader(String, String)
Generating frida script, please wait for a few seconds
frida hook script: okhttp3.Request.Builder.addHeader.js
某信拍 >
```
```js
//cat okhttp3.Request.Builder.addHeader.js
Java.perform(function() {
var okhttp3_Request_Builder_clz = Java.use('okhttp3.Request$Builder');
var okhttp3_Request_Builder_clz_method_addHeader_2grl = okhttp3_Request_Builder_clz.addHeader.overload('java.lang.String', 'java.lang.String');
okhttp3_Request_Builder_clz_method_addHeader_2grl.implementation = function(string, string_x2) {
var executor = this.hashCode();
var beatText = 'public okhttp3.Request$Builder okhttp3.Request$Builder.addHeader(java.lang.String,java.lang.String)';
var beat = newMethodBeat(beatText, executor);
var ret = okhttp3_Request_Builder_clz_method_addHeader_2grl.call(this, string, string_x2);
console.log("header name:" + string + " header value:" + string_x2);
printBeat(beat);
return ret;
};
});
```
***
- 7.2 生成指定类的所有成员方法的frida hook脚本:
gs okhttp3.Request$Builder
```shell
某信拍 > generatescript okhttp3.Request$Builder
Generating frida script, please wait for a few seconds
frida hook script: okhttp3.Request.Builder.allfunc.js
```
***
```js
//cat okhttp3.Request.Builder.allfunc.js
//okhttp3.Request$Builder
Java.perform(function() {
var okhttp3_Request_Builder_clz = Java.use('okhttp3.Request$Builder');
var okhttp3_Request_Builder_clz_method_header_ng3n = okhttp3_Request_Builder_clz.header.overload('java.lang.String', 'java.lang.String');
okhttp3_Request_Builder_clz_method_header_ng3n.implementation = function(string, string_x2) {
var executor = this.hashCode();
var beatText = 'public okhttp3.Request$Builder okhttp3.Request$Builder.header(java.lang.String,java.lang.String)';
var beat = newMethodBeat(beatText, executor);
var ret = okhttp3_Request_Builder_clz_method_header_ng3n.call(this, string, string_x2);
printBeat(beat);
return ret;
};
var okhttp3_Request_Builder_clz_method_cacheControl_q8q5 = okhttp3_Request_Builder_clz.cacheControl.overload('okhttp3.CacheControl');
okhttp3_Request_Builder_clz_method_cacheControl_q8q5.implementation = function(cacheControl) {
var executor = this.hashCode();
var beatText = 'public okhttp3.Request$Builder okhttp3.Request$Builder.cacheControl(okhttp3.CacheControl)';
var beat = newMethodBeat(beatText, executor);
var ret = okhttp3_Request_Builder_clz_method_cacheControl_q8q5.call(this, cacheControl);
printBeat(beat);
return ret;
};
var okhttp3_Request_Builder_clz_method_method_bjk9 = okhttp3_Request_Builder_clz.method.overload('java.lang.String', 'okhttp3.RequestBody');
okhttp3_Request_Builder_clz_method_method_bjk9.implementation = function(string, requestBody) {
var executor = this.hashCode();
var beatText = 'public okhttp3.Request$Builder okhttp3.Request$Builder.method(java.lang.String,okhttp3.RequestBody)';
var beat = newMethodBeat(beatText, executor);
var ret = okhttp3_Request_Builder_clz_method_method_bjk9.call(this, string, requestBody);
printBeat(beat);
return ret;
};
var okhttp3_Request_Builder_clz_method_head_a5nq = okhttp3_Request_Builder_clz.head.overload();
okhttp3_Request_Builder_clz_method_head_a5nq.implementation = function() {
var executor = this.hashCode();
var beatText = 'public okhttp3.Request$Builder okhttp3.Request$Builder.head()';
var beat = newMethodBeat(beatText, executor);
var ret = okhttp3_Request_Builder_clz_method_head_a5nq.call(this);
printBeat(beat);
return ret;
};
var okhttp3_Request_Builder_clz_method_headers_to5i = okhttp3_Request_Builder_clz.headers.overload('okhttp3.Headers');
okhttp3_Request_Builder_clz_method_headers_to5i.implementation = function(headers) {
var executor = this.hashCode();
var beatText = 'public okhttp3.Request$Builder okhttp3.Request$Builder.headers(okhttp3.Headers)';
var beat = newMethodBeat(beatText, executor);
var ret = okhttp3_Request_Builder_clz_method_headers_to5i.call(this, headers);
printBeat(beat);
return ret;
};
var okhttp3_Request_Builder_clz_method_post_heaq = okhttp3_Request_Builder_clz.post.overload('okhttp3.RequestBody');
okhttp3_Request_Builder_clz_method_post_heaq.implementation = function(requestBody) {
var executor = this.hashCode();
var beatText = 'public okhttp3.Request$Builder okhttp3.Request$Builder.post(okhttp3.RequestBody)';
var beat = newMethodBeat(beatText, executor);
var ret = okhttp3_Request_Builder_clz_method_post_heaq.call(this, requestBody);
printBeat(beat);
return ret;
};
var okhttp3_Request_Builder_clz_method_build_rmqx = okhttp3_Request_Builder_clz.build.overload();
okhttp3_Request_Builder_clz_method_build_rmqx.implementation = function() {
var executor = this.hashCode();
var beatText = 'public okhttp3.Request okhttp3.Request$Builder.build()';
var beat = newMethodBeat(beatText, executor);
var ret = okhttp3_Request_Builder_clz_method_build_rmqx.call(this);
printBeat(beat);
return ret;
};
var okhttp3_Request_Builder_clz_method_patch_hp9u = okhttp3_Request_Builder_clz.patch.overload('okhttp3.RequestBody');
okhttp3_Request_Builder_clz_method_patch_hp9u.implementation = function(requestBody) {
var executor = this.hashCode();
var beatText = 'public okhttp3.Request$Builder okhttp3.Request$Builder.patch(okhttp3.RequestBody)';
var beat = newMethodBeat(beatText, executor);
var ret = okhttp3_Request_Builder_clz_method_patch_hp9u.call(this, requestBody);
printBeat(beat);
return ret;
};
var okhttp3_Request_Builder_clz_method_url_0owi = okhttp3_Request_Builder_clz.url.overload('java.lang.String');
okhttp3_Request_Builder_clz_method_url_0owi.implementation = function(string) {
var executor = this.hashCode();
var beatText = 'public okhttp3.Request$Builder okhttp3.Request$Builder.url(java.lang.String)';
var beat = newMethodBeat(beatText, executor);
var ret = okhttp3_Request_Builder_clz_method_url_0owi.call(this, string);
printBeat(beat);
return ret;
};
var okhttp3_Request_Builder_clz_method_removeHeader_uzb9 = okhttp3_Request_Builder_clz.removeHeader.overload('java.lang.String');
okhttp3_Request_Builder_clz_method_removeHeader_uzb9.implementation = function(string) {
var executor = this.hashCode();
var beatText = 'public okhttp3.Request$Builder okhttp3.Request$Builder.removeHeader(java.lang.String)';
var beat = newMethodBeat(beatText, executor);
var ret = okhttp3_Request_Builder_clz_method_removeHeader_uzb9.call(this, string);
printBeat(beat);
return ret;
};
var okhttp3_Request_Builder_clz_method_url_ykbd = okhttp3_Request_Builder_clz.url.overload('java.net.URL');
okhttp3_Request_Builder_clz_method_url_ykbd.implementation = function(url) {
var executor = this.hashCode();
var beatText = 'public okhttp3.Request$Builder okhttp3.Request$Builder.url(java.net.URL)';
var beat = newMethodBeat(beatText, executor);
var ret = okhttp3_Request_Builder_clz_method_url_ykbd.call(this, url);
printBeat(beat);
return ret;
};
var okhttp3_Request_Builder_clz_method_delete_dqyl = okhttp3_Request_Builder_clz.delete.overload();
okhttp3_Request_Builder_clz_method_delete_dqyl.implementation = function() {
var executor = this.hashCode();
var beatText = 'public okhttp3.Request$Builder okhttp3.Request$Builder.delete()';
var beat = newMethodBeat(beatText, executor);
var ret = okhttp3_Request_Builder_clz_method_delete_dqyl.call(this);
printBeat(beat);
return ret;
};
//.......省略N行代码
```
***
- 7.3 生成指定类的构造方法的frida hook脚本:
gs okhttp3.Request$Builder:_ 或者gs okhttp3.Request$Builder:\
# Windows安装WSL
WSL是适用于Linux 的Windows 子系统(WSL)允许开发人员直接在Windows 上运行GNU/Linux 环境(包括大多数命令行工具、实用工具和应用程序),无需传统虚拟机或双启动设置的开销。
### 1. 安装wsl ubuntn24.04
访问:https://learn.microsoft.com/zh-cn/windows/wsl/install-manual#downloading-distributions
下载Ubuntu24.04
双击Ubuntu2404-240425.AppxBundle 安装Ubuntu
### 2. 进入wsl,配置代理
窗口输入wsl进入ubuntu命令行
- cmd
- wsl
切换到root用户
- sudo su
配置翻墙代理,如果你有
- export http_proxy="http://10.115.164.50:8080"
- export https_proxy="http://10.115.164.50:8080"
### 3. 安装python3.8和frida
- apt update
- apt install -y build-essential libssl-dev zlib1g-dev libbz2-dev
libreadline-dev libsqlite3-dev wget curl llvm xz-utils tk-dev
libffi-dev liblzma-dev
- apt install -y git
- apt install -y pyenv
- pyenv install 3.8.8
- pyenv local 3.8
# 自定义frida-server
- 将您自定义的frida-server文件拷贝到mobile-deploy文件夹下
- 修改hooker.py,default_frida_server_arm和default_frida_server_arm64变量的名字为你自定义的文件名
```python
default_frida_server_arm = "your-custom-frida-server-android-arm"
default_frida_server_arm64 = "your-custom-frida-server-android-arm64"
```
# hooker命令行快捷键
- Ctrl + U:整行清空
- Ctrl + W:删除一个单词
- Ctrl + K:从光标删到行尾