又一道简单的安卓逆向

Author Avatar
ciaoly 2021年09月06日
  • 在其它设备中阅读本文章

这是第七届职业技能竞赛山东省赛的一道赛题, 价值3分.

题目附件


逆向分析

下载题目附件, 直接拖到Jadx里反编译, 代码比较简单, 同样没有加壳和混淆. 其主要逻辑部分的代码如下:

//...
while (true) {
    if (this.target_data < 0) {
        this.target_data *= -1;
    }
    if (5 < this.target_data) {
        this.target_data %= 32;
        this.target_data *= 16384;
        ((TextView) findViewById(R.id.tv_data)).setText("0");
        ((TextView) findViewById(R.id.tv_target)).setText("" + this.target_data);
        Button btn2 = (Button) findViewById(R.id.btn2);
        ((Button) findViewById(R.id.btn1)).setOnClickListener(new View.OnClickListener() {
        /* class com.wdkj.ctf6.ctf6.MainActivity.AnonymousClass1 */

            public void onClick(View v) {
                MainActivity.this.cur_data++;
                ((TextView) MainActivity.this.findViewById(R.id.tv_data)).setText("" + MainActivity.this.cur_data);
                if (MainActivity.this.cur_data >= MainActivity.this.target_data) {
                    ((Button) MainActivity.this.findViewById(R.id.btn2)).setClickable(true);
                }
            }
        });
        btn2.setOnClickListener(new View.OnClickListener() {
        /* class com.wdkj.ctf6.ctf6.MainActivity.AnonymousClass2 */

            public void onClick(View v) {
                Toast.makeText(MainActivity.this.getApplicationContext(), "Flag:" + MainActivity.this.get_flag(MainActivity.this.target_data), 1).show();
            }
        });
        btn2.setClickable(false);
        return;
    }
    this.target_data = random.nextInt();
}
// ...

有一个native的方法, so是arm的. 为了避免C逆向, 尝试直接crack该apk.

由于比赛时为线下赛, 且不允许使用手机和自己的电脑, 我用IDA大致看了看so文件后直接放弃了这题.

Crack

在程序中有设置证书校验和调试检测的代码, 为了能正常Crack, 需要把证书校验的方法给绕过. 之后, 将属性cur_data的值直接修改为32 * 16384. 运行程序即可获得flag.

使用Jadx可以直接导出Gradle工程. 再使用Android Studio导入工程即可进行Crack. 但是, 用新版本的Android Studio构建项目时需要处理各种各样的Gradle和依赖库的兼容性问题, 非常烦人, 索性直接在手机上用MT管理器修改Smali了.

首先, 找到函数validateAppSignature, 在函数返回语句return v5前添加赋值语句const/4 v5, 0x1:

IMG_20210906_165210

之后, 在MainActivity的构造器处, 删除条件判断语句, 绕过调试状态检测

IMG_20210906_170246

最后, 在OnCreate方法中找到为按钮R.id.btn1设置点击监听器的代码, 发现其实例化了子类MainActivity$1.

IMG_20210906_170454

打开MainActivity$1, 在OnClick回调函数处将语句add-int/lit8 v3,v3,0x1修改为const v3, 0x80000.

IMG_20210906_170817

重新打包并签名, 安装程序并运行. 点击按钮"攒一分", 一刀满级, 之后再点击"看答案", 将得到flag: 1E238A5611D4BD4A

IMG_20210906_161758