SimpleHook
这里是 SimpleHook 的 hook 部分代码
中文文档|English
simpleHook.apk(密码:simple)
TG 交流群: @simpleHook
本软件主打简单,如名字一样,如果你追求更复杂的 hook 操作,推荐使用 jsHook(你可以实现更复杂的功能)、曲境(电脑端浏览器操作);如果你追求更多的扩展功能,推荐使用算法助手等等类似应用
功能概述:自定义返回值、参数值等,记录常见各种加密算法、toast、dialog、popupwindow、JSONObject 创建增加等
1. 功能说明
页面介绍
首页
点击加号,可添加配置,点击添加配置进入下面页面
配置页面
点击‘搜索样式’图标,可进入 AppList 页面,进行选择应用
点击‘下载样式’图标,可保存配置
点击右下角加号,可在弹出窗口填写配置
有多种模式可以选择,输入类名前建议了解设置页面(smali to config),它可以简化填写
扩展页面
具体功能
点击“播放样式”按钮,可打开悬浮窗(需要授予悬浮窗权限),然后打开目标应用,可以显示一些信息(开启了打印参数值、返回值、扩展页面大部分功能)
悬浮窗
2.自定义 Hook 编写规则
下面是编写规则:(你可以下载HookTest.apk,此 App 应用了所有情况,并内附有配置)
使用前请先了解设置页【smali 转配置】,它可以简化你的操作(配合 MT 管理器等逆向分析软件)
简要的基本介绍
支持 Java 语法和 Smali 语法填写配置信息
// java me.simplehook.MainActivty // smali Lme/simplehook/MainActivity; //一定要有 --> ; <--
支持基本类型和其它类型参数
// 类型 主要用于填写参数类型和变量类型 // 基本类型你可以使用 java 语法这样填 boolean int long short char byte float double // 基本类型你也可以使用 smali 语法这样填 Z I J S C B F D // 其他类型你可以使用 java 语法这样填 java.lang.String android.content.Context // 其他类型你也可以使用 smali 语法这样填 Ljava/lang/String; Landroid/content/Context; //一定要有 --> ; <--
结果值的填写规则
此处应注意,本软件不像其他软件一样需要填写返回值、参数值类型,本软件并不需要,你只需要按照规则填写,自动判断
2.1. 基本类型
类型(java、smali) | 值的例子 | 注意事项 |
---|---|---|
布尔值(boolean、Z) | true、false | |
整数(int、I) | 1、2、3 | |
长整型(long、J) | 1l、120000L、123456l | 要注意:数字 + L |
短整型(short、S) | 1short、2short | 要注意:数字 + short |
字符(char、C) | 195c | 要注意:符合 char 类型的字符 + c |
字节(byte、B) | 2b、3b | 要注意:符合 byte 类型的字符 + b |
单浮点(float、F) | 2f、3f、3.0f | 要注意:数字 + f |
双浮点(double、D) | 2d、3d、3.0d | 要注意:数字 + d |
2.2. null
其他类型只能返回 null(字符串除外),null
2.3. 字符串
2.3.1 一般情况
不符合基本类型和 null 的全部转化为字符串类型
2.3.2 特殊情况
特殊的字符串 | 值的例子 | 注意事项 |
---|---|---|
数字 | 111s, 2002s | 常见于 "111111" 这种,但是本软件你需要在数字后面加入 s,如果你不加 s,会被转成数字,可能导致目标应用崩溃 |
布尔 | trues、falses | 常见于 "true" 、"false" 这种,但是本软件你需要在布尔值后面加入 s,如果你不加 s,会被转成布尔值,可能导致目标应用崩溃 |
null | nulls | 常见于 "null"这种,但是本软件你需要在 null 后面加入 s,如果你不加 s,会被转成 null,可能导致目标应用空指针 |
空字符串 | 英文单词'empty' 或者中文汉字'空' | 如果你直接填空,将无法保存配置,这样做是为了预防你在使用时不填修改值导致无法正常 Hook |
2.3.3 随机文本返回值
仅用于返回值,返回值填写下面 json 代码
{ "random": "abcdefgh123456789", "length": 9, "key": "key", "updateTime": 100, "defaultValue": "" }
上述 json 格式代码介绍: random:字符串,填写随机文本由哪些字符组成
length:整数,代表需要生成多长的随机文本
key:字符串,唯一识别码,可以随便填写,但是一个软件中用到多个随机返回值时需要填不一样的
updateTime:整数,代表着间隔多长时间更新一下随机文本,单位秒, -1 代表每次都更新
defaultValue:非必填项
3.具体的 hook 模式
hook 返回值
// 例如 1
import simple.example;
Class Example{
public static boolean isFun() {
boolean result = true;
...
...
return result
}
}
/*
模式选择 Hook 返回值
类名应填:simple.example.Example
方法名应填:isFun
参数类型应填:(此处留空,因为没有参数)
修改值应填:true 或者 false
*/
/*
多个参数参数类型的填法(用英语逗号分开,参数类型支持数组):
boolean,int,android.content.Context
*/
// 例如 2
import simple.example;
class Example{
public static String isFun(Sring str, Context context, boolean b) {
String result = str;
...
...
return result
}
}
/*
模式选择 Hook 返回值
类名应填:simple.example.Example
方法名应填:isFun
参数类型应填:
java 语法: java.lang.String,android.content.Context,boolean (使用参数间使用英文逗号分开,仅一个参数不需要加逗号)
smali 语法:Ljava/lang/String;,Landroid/content/Context;,Z
修改值应填:是个字符串 (应符合结果值的填写规则,不需要加引号)
*/
hook 返回值+
此功能可以将 json 转为对象(使用 Gson),你如果不知道这个对象的 Json 格式是什么样子的,可以使用【记录返回值】功能,复制返回值即可。这个功能并不是万能的,不适用所有情况,简单的数据类应该是没有问题的,暂不支持数组。
模式:hook 返回值+
返回值的类名:填返回值的类名
修改值:填 json 代码,如
{"isHook":false,"level":10000}
举个例子:
import simple.example; // 数据类 public class UserBean { private boolean isHook; private int level; public UserBean(boolean isHook, int level) { this.isHook = isHook; this.level = level; } } public class Example{ public static UserBean isFun() { UserBean userBean = new UserBean(true, 10); ... ... return userBean } } /* 假如 hook isFun 的返回值 模式:hook 返回值+ 类名:simple.example.Example 方法名:isFun 参数类型: 返回值的类名:simple.example.UserBean 结果值:{"isHook":false,"level":10000} */
hook 参数值
// 类型值同 hook 返回值类型
//特殊用法,如下面一段代码
public boolean isModuleLive(Context context, String str, int level){
retrun true
}
//如果你只想要 hook level 的值,你可以在修改值那一栏向下面这样填
,,99
//如果你只想要 hook str 的值,你可以在修改值那一栏向下面这样填
,啦啦啦,
//如果你只想要 hook str、level 的值,你可以在修改值那一栏向下面这样填
,啦啦啦,99
//如果你想要全部 hook,你可以在修改值那一栏向下面这样填
null,啦啦啦,99 // context 为 null 也许导致闪退
/*
多个参数参数类型的填法(用英语逗号分开):
android.content.Context,jave.lang.String,int
或者如下填写
Landroid/content/Context;,Ljave/lang/String;int
*/
中断执行
// 此模式会拦截方法执行
// 如 hook 返回值或者 hook 参数值一样填,不需要填写返回值、参数值
public void printString() {
System.out.println("start");
testBreakMethod();
System.out.println("end");
/*
输出结果为
start
end
test Break Mode 没有被输出
*/
}
// 假如:此方法被中断
public void testBreakMethod() {
System.out.println("test Break Mode")
}
Hook 所有同名方法
/*
Hook 一个类所有同名方法,参数类型填写 * 即可
*/
Hook 一个类中所有方法
/*
Hook 一个类所有方法,方法名填写 * 即可;参数类型可随意填写,有些 h 不可为空
*/
构造方法
// 方法名填写:<init>
import simple.example;
public class Example{
int a;
int b;
public Example(int a, boolean b) {
this.a = a;
this.b = b
}
}
// Hook 模式,根据自己的需求选择,一般为 hook 参数值/记录参数值,其他模式可能造成软件闪退
/*
方法名填写:<init>
例如修改两个参数值
类名填写:simple.example.Example
方法名填写: <init>
参数类型填写:int,int
结果值填写:88,99
*/
HOOK 静态变量
import simple.example;
public class Example{
public static boolean isTest = false;
}
import simple.example;
public class MainActivity extends Acitvity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();
}
private void initData(){
Example.isTest = false;
}
private void initView() {
//你想要修改 isTest 为 true,所以你应当再这个变量被赋值后再去 hook
System.out.println(Example.isTest);
}
}
// 具体的值只支持基本类型,和字符串
// 无需填写变量类型;要符合[结果值]填写规则
/*
模式选择 Hook 静态变量
hook 点:after/before 根据需要填写,默认 after
类名应填:simple.example.MainActivity;
方法名应填: initData
参数类型应填:(什么都是不填,因为这个方法没有参数)
变量所在类名:simple.example.Example
变量名应填:isTest
修改值应填:true/false
*/
HOOK 实例变量
import simple.example;
public class UseBean {
private boolean isHook;
private int level;
public UseBean(boolean isHook, int level) {
this.isHook = isHook;
this.level = level;
}
public boolean isHook() {
return isHook;
}
public void setHook(boolean hook) {
isHook = hook;
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
}
import simple.example;
public class MainActivity extends Acitvity {
private User user;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();
}
private void initData(){
user = new User(true, 100);
}
private void initView() {
//你想要修改 isHook、level,所以你应当再这个变量被赋值后再去 hook
System.out.println(user.isHook());
System.out.println(user.getLevel());
}
}
// 具体的值只支持基本类型,和字符串
// 无需填写变量类型;要符合[结果值]填写规则
/*
模式选择 Hook 变量
hook 点:after/before 根据需要填写,默认是 after
类名应填:simple.example.UseBean;
方法名应填: <init> // <init> 表示构造方法
参数类型应填:boolean,int
变量名应填:isHook
修改值应填:true/false
实例变量/成员变量:不支持像静态变量一样跨类 hook,只能在本类的某个方法执行后,再去 hook 变量值
*/
记录参数值
方法的参数值会被记录,前往记录页面可以查看、 若参数是数组或者 list 会被转成 json 格式
记录返回值
方法的返回值会被记录,前往记录页面可以查看 若结果是数组或者 list 会被转成 json 格式
记录参返
方法的参数值、返回值会被一同记录,前往记录页面可以查看 若结果是数组或者 list 会被转成 json 格式 若参数是数组或者 list 会被转成 json 格式
扩展 Hook
切记打开总开关 功能请前往 app 查看
4.常见问题(FAQ)
1.hook 没有效果
- 可看框架日志,是否有报错等
- 储存文件更新配置某些情况下需要手动刷新,开启、关闭、编辑保存即可刷新
- 请授予所需权限(android11 以下:储存权限,android11 及以上:ROOT 权限)
2.什么是 smali 转配置
开启此实验功能后,配置页面顶部会增加‘粘贴板’图标,点击可将应用调用代码或签名,转化为配置(防止手动输入错误),增加配置后你需要手动选择合适的模式以及结果值 调用代码例子:
iget v0, p0, Lme/duck/hooktest/bean/UseBean;->level:I invoke-virtual {v0}, Lme/duck/hooktest/bean/UseBean;->isHook()Z
方法签名、字段签名例子:
Lme/duck/hooktest/bean/UseBean;->level:I Lme/duck/hooktest/bean/UseBean;->isHook()Z
上述可在 MT 管理器导航中长按字段或方法选择复制签名或者查找调用
3.为什么目标应用运行很慢
请关闭不必要的扩展 HOOK 和记录参数、返回值功能, 例如:md5、base64 等,这些功能会产生大量的 Log
4.
5.
6.什么是 hook 点
hook 静态变量、实例变量支持手动填写 hook 点,hook 点就是在方法执行前 hook 还是在方法执行后 hook
before:方法执行前 hook; after:方法执行后 hook
7.什么是删除遗留配置
当你卸载本应用或者清除数据时,目标应用配置文件仍然可能保存在储存文件中
- /data/local/tmp/simpleHook/目标应用包名/config/
- /storage/emluated/0/Android/data/目标应用包名/simpleHook/config/
这个功能就是遍历所有的应用目录并删除无用的配置(本应用内未显示其配置)
因为需要遍历所有应用会比较慢
8.配置说明
{
"packageName": "包名",
"appName": "应用名",
"versionName": "版本名",
"description": "描述",
"configs": "配置",
"enable": true,
"id": 0
},
configs 为下列字符串形式
[
{
"mode": 0,
"className": "类名",
"methodName": "方法名",
"params": "参数类型",
"fieldName": "变量名",
"fieldClassName": "变量所在类名",
"resultValues": "返回值",
"hookPoint": "hook 点",
"returnClassName": "返回值类名",
"fieldType": "变量类型",
"enable": true
}
]
mode
0:
代表 Hook 返回值,
有效:mode、className、methodName、params、resultValues、enable
params: 多个参数为,隔开
resultValues:返回值
1:
代表 Hook 参数值,
有效:mode、className、methodName、params、resultValues、enable
params: 多个参数为,隔开
resultValues:多个参数值,隔开,留空不 hook 这个参数
2:
代表替换/拦截方法执行
有效:mode、className、methodName、params、enable
3:
代表 Hook 静态变量
有效 1:mode、className、resultValues、enable、fieldName
直接 Hook 变量:
resultValues:变量值
有效 2:mode、className、methodName、params、resultValues、enable、fieldName、fieldClassName、hookPoint
某方法 Hook 前后 hook 变量:
resultValues: 变量值
hookPoint: before、after
4:
代表 Hook 实例变量
有效:mode、className、methodName、params、resultValues、enable、fieldName、fieldClassName
5:
记录参数值
有效:mode、className、methodName、params、enable
6:
记录返回值
有效:mode、className、methodName、params、enable
7:
记录参数值和返回值
有效:mode、className、methodName、params、enable
8:
记录静态变量
有效:mode、className、methodName、params、resultValues、enable、fieldName、fieldClassName
9:
记录实例变量
有效:mode、className、methodName、params、resultValues、enable、fieldName、fieldClassNam
10
Hook 返回值+
有效:mode、className、methodName、params、resultValues、enable、returnClassName
通过 Gson 将 json 转为 returnClassName 的对象
resultValues: json 字符串