xposed hook框架的使用(二)
上次埋了个坑,这次我们用一个实际例子来实战练习一下 xposed 的用法
首先创建一个 app 作为我们 hook 的目标,大致就是下面这个样子
下面是处理逻辑,初学着,以前没接触过 android 开发有哪不对的多多包含
package com.example.login;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
private String name;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final EditText etUserName = (EditText)findViewById(R.id.userName);
final EditText etPassword = (EditText)findViewById(R.id.password);
Button btnLogin = (Button)findViewById(R.id.login);
btnLogin.setOnClickListener(new OnClickListener() {
@Override
//点击登录事件
public void onClick(View arg0) {
// TODO Auto-generated method stub
//login 方法判断是否正确
if(login(etUserName.getText().toString(), etPassword.getText().toString()))
{
Toast.makeText(getApplicationContext(), "正确", Toast.LENGTH_LONG).show();
//正确把用户名保存
name = etUserName.getText().toString();
}else{
Toast.makeText(getApplicationContext(), "错误", Toast.LENGTH_LONG).show();
}
}
});
}
//判断是否正确
private boolean login(String userName,String password)
{
if(userName.equals("tanzui") && password.equals("123"))
{
return true;
}
return false;
}
}
接下来,把生成的 bin 目录的 apk 文件找出来模拟分析下吧(这里不导出了,偷个懒)
然后用 jeb2 打开(另一神器,既能静态分析,又能动态调试,版权问题自己百度搜索吧)
打开之后是下面这个样子
不多做介绍了,自己摸索下应该也就清楚了,双击 Bytecode 变成如下,切换到 Bytecode/Hierarchy,右键 MainActivity 点击 Decompile
然后神奇的一幕就出现了,如图
你会发现源码出来了,虽然有点不太一样,这应该是我们编译的时候程序优化我们的代码了(笑哭),但是整体流程是对的,当然正式的 app 一般来说都会混淆代码,对代码阅读造成一定影响,咱们现在是实验就不混淆了
梳理下思路,上面代码如果想得到账号和密码只需要 hook “login”方法的两个参数就可以了
接下来咱们接着上一篇留的坑继续补全
打开 com.example.hookproject.demo.HookDemo 类填入一下代码
package com.example.hookproject.demo;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
public class HookDemo implements IXposedHookLoadPackage{
@Override
public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable {
// TODO Auto-generated method stub
//判断程序是否是我们要 hook 的,不是就跳过
if(!lpparam.packageName.equals("com.example.login"))
{
return;
}
//hook 指定的 class 中的方法
XposedHelpers.findAndHookMethod(
//要 hook 的类,很明显是 MainActivity
"com.example.login.MainActivity",
//类加载器
lpparam.classLoader,
//要 hook 方法的名称
"login",
//参数类型
String.class,
//参数类型
String.class,
new XC_MethodHook(){
//在方法运行之前 hook 可在运行之前改变参数的值从而影响运行结果,得不到返回值
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
}
//在方法运行之后 hook 可以得到返回值 这里我们在运行之后就可以了 因为我们需要拿到返回值
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
//参数 1 的值
XposedBridge.log("tanzui userName:" + param.args[0]);
//参数 2 的值
XposedBridge.log("tanzui password:" + param.args[1]);
//返回值
XposedBridge.log("tanzui Login:" + param.getResult());
//获取私有属性 name 的值
XposedBridge.log("tanzui name:" + XposedHelpers.getObjectField(param.thisObject, "name"));
}
}
);
}
}
重启完成之后,打开命令行-使用 adb shell 连接 手机 执行代码 (不知道adb shell 百度搜索一下吧,资料很多)
logcat |grep "tanzui"
等待 log 输出
打开 login app 输入账号 - 密码
cmd 会有以下输出
可以很直观的看到 账号 密码以及返回是否正确都被打印了出来 ,细心的朋友可能会发现为什么属性 name 是 null ,这是因为写 login app 的登录验证时把赋值 name 写在了 login 后面 所以hook 到 login方法的时候赋值还没有被执行,再次点 login按钮 会发现 name 有内容了,这是上一次赋的值(笑哭)
至此 第一个真正意义上的 hook 就算完成了,有兴趣的朋友还可以在去多多实验一下,下篇准备写一写,dex 分包应用的 hook
下面是工程附件:
(新账号太穷,设了一个积分的下载分,缺分的同学可以按照上一篇一点点来不影响的,分多的同学希望能支持下(害羞))
http://download.csdn.net/download/tanzui/9938680
上一篇: 自制Java虚拟机(二)指令、帧/栈帧
下一篇: Xposed hook(android)