xposed是一个模块框架,可以在不接触任何apk的情况下更改系统和应用程序的行为。这意味着模块可以在不同版本甚至rom上工作而无需任何更改。
jshook是对app注入rhino/frida,xposed模块开发需要一定的java语法基础,技术门槛高,而jshook注入的rhino/frida只需要会简短的js,即可用手机快速实现hook,并且hook支持java层和native层。
- Xposed api 82
- Android 5 - 13
启用脚本前请确认选择的应用已开启hook服务选项,如果是lsposed非全局作用域在激活时除了勾选系统还需勾选对应脚本生效的应用,每次更改脚本内容都需要重启一下被hook的app。
如果你对xposed的hook方法比较熟,推荐rhino,使用js调用xposed框架的api,且兼容性高;而frida属于另一个hook框架,需要对frida有一定的了解,上手较难,且不支持部分机型和app。
日志打印:
common.log('...');
console.log('...');
消息提示:
common.toast('...');
弹窗提示:
common.dialog('...');
获取Context:
common.getcontext();
mod菜单:
modmenu | |||
参数 | 参数类型 | 参数说明 | 是否必填 |
title | String | 标题 | N |
item | Array | 菜单项 | Y |
title | String | 标题 | N |
change | Function | 回调 | N |
示例:
common.modmenu('test mod', [
{
'id': '1',
'type': 'category',
'title': 'category title'
},
{
'id': '2',
'type': 'switch',
'title': 'switch1 title',
'enable': true
},
{
'id': '3',
'type': 'switch',
'title': 'switch2 title'
},
{
'id': '4',
'type': 'webview',
'data': '<font color="red"><b>text</b></font>',
//or
//'url': 'http://xxxxx.com'
},
{
'id': '5',
'type': 'button',
'title': 'button title'
},
{
'id': '6',
'type': 'input',
'title': 'input title',
'val': 'default value'
},
{
'type': 'collapse',
'title': 'collapse title',
'item': [
{
'id': '7',
'type': 'switch',
'title': 'switch title'
}
],
'enable': true
},
{
'id': '8',
'type': 'slider',
'title': 'slider title',
'val': 88,
'min': 1,
'max': 100
},
{
'id': '9',
'type': 'checkbox',
'title': 'checkbox title',
'enable': true
},
{
'type': 'checkboxs',
'item': [
{
'id': '10',
'type': 'checkbox',
'title': '1 title'
},
{
'id': '11',
'type': 'checkbox',
'title': '2 title'
},
{
'id': '12',
'type': 'checkbox',
'title': '33333333 title'
}
]
},
{
'id': '13',
'type': 'radio',
'title': 'radio title',
'item': ['test', 'test2', 'test3']
}
], function (data) {
common.toast(JSON.stringify(data));
});
带tab选项卡的示例:
common.modmenu('test mod', [
{
'type': 'tab',
'title': 'tab1 title',
'item': [
{
'id': '1',
'type': 'switch',
'title': 'switch1 title'
}
],
'enable': true
},
{
'type': 'tab',
'title': 'tab2 title',
'item': [
{
'id': '2',
'type': 'switch',
'title': 'switch2 title'
}
]
}
], function (data) {
common.toast(JSON.stringify(data));
});
注意:使用mod菜单需要让jshook保持运行状态且授权悬浮窗权限,关闭jshook会导致菜单关闭,不影响hook服务
获取LoadPackageParam
getlpparam | |||
参数 | 参数类型 | 参数说明 | 是否必填 |
无 |
示例:
common.getlpparam();
获取类实例
findClass | |||
参数 | 参数类型 | 参数说明 | 是否必填 |
className | String | 类名 | Y |
classLoader | ClassLoader | 类加载器 | Y |
示例:
common.findClass('com.test.test', classLoader);
hook构造函数
hookAllConstructors | |||
参数 | 参数类型 | 参数说明 | 是否必填 |
className | Object | 类实例或类名 | Y |
beforeHookedMethod | Function | 构造函数执行前 | N |
afterHookedMethod | Function | 构造函数执行后 | N |
replaceHookedMethod | Function | 替换构造函数执行过程 | N |
示例:
common.hookAllConstructors('com.test.test', function (param) {
//构造函数执行前
//打印构造函数接收到的第一个参数
common.log(param.args[0]);
//修改这个参数的值
param.args[0] = 'fuck';
}, function (param) {
//构造函数执行后
//...
});
hook指定参数的构造函数
hookConstructor | |||
参数 | 参数类型 | 参数说明 | 是否必填 |
className | Object | 类实例或类名 | Y |
paramTypes | Object[] | 参数类型 | Y |
beforeHookedMethod | Function | 构造函数执行前 | N |
afterHookedMethod | Function | 构造函数执行后 | N |
replaceHookedMethod | Function | 替换构造函数执行过程 | N |
示例:
common.hookConstructor('com.test.test', ['java.lang.String', 'int'], function (param) {
//...
}, function (param) {
//...
});
hook类方法
hookAllMethods | |||
参数 | 参数类型 | 参数说明 | 是否必填 |
className | Object | 类实例或类名 | Y |
beforeHookedMethod | Function | 函数执行前 | N |
afterHookedMethod | Function | 函数执行后 | N |
replaceHookedMethod | Function | 替换函数执行过程 | N |
示例:
common.hookAllMethods('com.test.test', 'methodname', function (param) {
//...
}, function (param) {
//...
}, function (param) {
//调用原方法返回
return common.thisMethod(param);
});
hook指定的类方法
hookByMethod | |||
参数 | 参数类型 | 参数说明 | 是否必填 |
method | Method | 方法对象 | Y |
beforeHookedMethod | Function | 函数执行前 | N |
afterHookedMethod | Function | 函数执行后 | N |
replaceHookedMethod | Function | 替换函数执行过程 | N |
示例:
common.hookByMethod(method, function (param) {
//...
//修改返回值
param.setResult('fuck');
}, function (param) {
//...
//获取类方法的返回值并打印
common.log(param.getResult());
});
hook指定参数的类方法
hookMethod | |||
参数 | 参数类型 | 参数说明 | 是否必填 |
className | String | 类名 | Y |
paramTypes | Object[] | 参数类型 | Y |
beforeHookedMethod | Function | 函数执行前 | N |
afterHookedMethod | Function | 函数执行后 | N |
replaceHookedMethod | Function | 替换函数执行过程 | N |
示例:
common.hookMethod('com.test.test', 'methodname', ['java.lang.String', 'int'], function (param) {
//...
//修改返回值
param.setResult('fuck');
}, function (param) {
//...
//获取类方法的返回值并打印
common.log(param.getResult());
});
修改静态变量值
setStaticObjectField | |||
参数 | 参数类型 | 参数说明 | 是否必填 |
className | Object | 类实例或类名 | Y |
fieldName | String | 变量名 | Y |
fieldValue | Object | 变量值 | Y |
示例:
common.setStaticObjectField('com.test.test', '变量名', '变量值');
修改动态变量值
setObjectField | |||
参数 | 参数类型 | 参数说明 | 是否必填 |
className | Object | 类名或者当前实例 | Y |
fieldName | String | 变量名 | Y |
fieldValue | Object | 变量值 | Y |
示例:
common.setObjectField('com.test.test', '变量名', '变量值');
//或者
//param.thisObject 在hook回调方法中获取
common.setObjectField(param.thisObject, '变量名', '变量值');
获取静态变量值
getStaticObjectField | |||
参数 | 参数类型 | 参数说明 | 是否必填 |
className | Object | 类实例或类名 | Y |
fieldName | String | 变量名 | Y |
示例:
common.getStaticObjectField('com.test.test', '变量名');
获取动态变量值
getObjectField | |||
参数 | 参数类型 | 参数说明 | 是否必填 |
className | Object | 类名或者当前实例 | Y |
fieldName | String | 变量名 | Y |
示例:
common.getObjectField('com.test.test', '变量名');
主动调用动态方法
callMethod | |||
参数 | 参数类型 | 参数说明 | 是否必填 |
className | Object | 类名或者当前实例 | Y |
methodMame | String | 方法名 | Y |
paramTypes | Object[] | 参数值 | N |
示例:
common.callMethod('com.test.test', 'methodname', ['a', 1]);
主动调用静态方法
callStaticMethod | |||
参数 | 参数类型 | 参数说明 | 是否必填 |
className | Object | 类实例或类名 | Y |
methodMame | String | 方法名 | Y |
paramTypes | Object[] | 参数值 | N |
示例:
common.callStaticMethod('com.test.test', 'methodname', ['a', 1]);
replaceHookedMethod
中调用原方法
thisMethod | |||
参数 | 参数类型 | 参数说明 | 是否必填 |
param | Object | 参数 | Y |
示例:
//param在replaceHookedMethod中获取
common.thisMethod(param);
curl
curl | |||
参数 | 参数类型 | 参数说明 | 是否必填 |
url | String | 地址 | Y |
method | String | 请求类型 | N |
header | Array | 头部信息 | N |
data | Object | 提交数据 | N |
callback | Function | 回调 | N |
示例:
common.curl('https://xxxxx.com', 'post', ['token: sssss'], {data: '111'}, function (data) {
common.log(data);
});
shell
shell | |||
参数 | 参数类型 | 参数说明 | 是否必填 |
content | String | 内容 | Y |
示例:
common.shell('curl https://xxxxx.com', function (data) {
common.log(data);
});