利用frida來解一些安卓題目


之前在github看了r0ysue大佬的frida系列教程,於是想來實踐一下。

DDCTF2018-HelloBabyDex

這道題涉及到了APK的熱修復,目前還沒有怎么接觸,之后得深入一下。

 

 這道題在Mainactivity的onCreate函數中調用了Joseph函數,並把它的返回值拼接作為flag

            String v9 = this.Joseph(1, 2);
            super.onCreate(arg13);
            this.setContentView(0x7F09001B);  // layout:activity_main
            this.runRobust();
            SignCheck v10 = new SignCheck(this, this, "1B:D0:4A:9D:B5:A9:84:93:7E:79:27:9C:6C:C4:14:AB:DD:B0:75:7F");
            v10.check();
            Debug.isDebuggerConnected();
            View v8 = this.findViewById(0x7F07003D);  // id:input_text
            EditText v8_1 = (EditText)v8;
            View v7 = this.findViewById(0x7F070026);  // id:check_btn
            Button v7_1 = (Button)v7;
            cn.chaitin.geektan.crackme.MainActivity.1 v0_3 = new View.OnClickListener() {
                public static ChangeQuickRedirect changeQuickRedirect;

                @Override  // android.view.View$OnClickListener
                public void onClick(View arg9) {
                    Object[] v0 = new Object[1];
                    v0[0] = arg9;
                    ChangeQuickRedirect v2 = cn.chaitin.geektan.crackme.MainActivity.1.changeQuickRedirect;
                    Class[] v5 = new Class[1];
                    Class v1 = View.class;
                    v5[0] = v1;
                    Class v6 = Void.TYPE;
                    boolean v0_1 = PatchProxy.isSupport(v0, this, v2, false, 18, v5, v6);
                    if(v0_1) {
                        Object[] v0_2 = new Object[1];
                        v0_2[0] = arg9;
                        ChangeQuickRedirect v2_1 = cn.chaitin.geektan.crackme.MainActivity.1.changeQuickRedirect;
                        Class[] v5_1 = new Class[1];
                        Class v1_1 = View.class;
                        v5_1[0] = v1_1;
                        Class v6_1 = Void.TYPE;
                        PatchProxy.accessDispatch(v0_2, this, v2_1, false, 18, v5_1, v6_1);
                    }
                    else {
                        EditText v0_3 = v8_1;
                        Editable v0_4 = v0_3.getText();
                        boolean v0_5 = TextUtils.isEmpty(v0_4);
                        if(v0_5) {
                        label_31:
                            MainActivity v0_12 = MainActivity.this;
                            Toast v0_13 = Toast.makeText(v0_12, "大佬莫急!再試試!", 0);
                            v0_13.show();
                        }
                        else {
                            EditText v0_6 = v8_1;
                            Editable v0_7 = v0_6.getText();
                            String v0_8 = v0_7.toString();
                            StringBuilder v1_2 = new StringBuilder();
                            StringBuilder v1_3 = v1_2.append("DDCTF{");
                            String v2_2 = v9;
                            StringBuilder v1_4 = v1_3.append(v2_2);
                            StringBuilder v1_5 = v1_4.append("}");
                            String v1_6 = v1_5.toString();
                            boolean v0_9 = v0_8.equals(v1_6);
                            if(!v0_9) {
                                goto label_31;
                            }

                            MainActivity v0_10 = MainActivity.this;
                            Toast v0_11 = Toast.makeText(v0_10, "恭喜大佬!密碼正確!", 0);
                            v0_11.show();
                        }
                    }
                }
            };
            v7_1.setOnClickListener(v0_3);    

可以看到v9參與了之后的拼接以及equals操作,於是我們這里可以使用frida直接來進行hook

hook equals函數的話,可以直接出flag,hook Joseph函數的話,可以出flag中的字符串,拼接起來。

上腳本:

import frida, sys

source = """
Java.perform(function() {
    var clazz = Java.use('cn.chaitin.geektan.crackme.MainActivity');
    clazz.Joseph.implementation = function() {

        var msg = clazz.Joseph.apply(this, arguments);
        send(msg);
        return msg;
    }
    var clazzz = Java.use('java.lang.String');
    clazzz.equals.implementation = function() {

        var msg = clazzz.equals.apply(this, arguments);
        var ret = clazzz.valueOf.apply(this,arguments);
        if(ret.indexOf("DDCTF")!=-1)
            send(ret);
        return msg;
    }
});
"""
def on_message(message, data):
    if message['type'] == 'send':
        print("[*] {0}".format(message['payload']))
    else:
        print(message)

 
process = frida.get_usb_device().attach('cn.chaitin.geektan.crackme')
script = process.create_script(source)
script.on('message', on_message)
script.load()
sys.stdin.read()

 

 可以看到,Joseph函數只調用了一次,但輸出了兩次,這就是熱補丁的結果。

hook equals函數后,再加以篩選,直接出flag!

 

RCTF2015(FlagSystem)

這道題看了奈沙夜影的wp,他是用xposed實現的,這里我使用了frida

引用大佬的分析過程,這里只給出frida實現。

https://blog.csdn.net/whklhhhh/article/details/89118707

 

上腳本:

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
import frida , sys#select book_author,book_name from books_table
 
jscode = """
Java.perform(function () {
    send("Hook start..");
    
    var test = Java.use('com.example.mybackup.Test');
    var k;
    test.getSign.implementation = function () {
        send("getSign Function implemented");
        k = test.getSign.apply(this,arguments);
        send("Password is : " + k);

        return k;
    }

    var demo = Java.use('com.example.mybackup.BooksDB');
    var db;
    demo.getReadableDatabase.implementation = function (k) {
        send("getReadableDatabase Function implemented");
        db = this.getReadableDatabase(k);
        if(db != null)
            send('DB got');
        var S = Java.use("java.lang.String");
        var sql = S.$new("select book_author,book_name from books_table");
        var cursor = db.rawQuery(sql,null);
        if(cursor!=null)
            send('cursor got');
        /*cursor.getString(0);
        while(cursor.moveToNext()) {
            send("Result : " + cursor.getString(0));
        }
        Java.choose("net.sqlcipher.Cursor" , {
            onMatch : function(instance){
                console.log("Found instance: "+instance);
            },
            onComplete:function(){}
        });*/
        var class_cursor = Java.use("android.database.Cursor");
        cursor = Java.cast(cursor,class_cursor);
        while(cursor.moveToNext()) {
            send("Result : " + cursor.getString(0));
        }

        return db;
    }

    demo.$init.implementation = function (a) {
        send("$init Function implemented");
        return this.$init(a);
    }



});
"""
def on_message(message, data):
    if message['type']=='send':
        print("[*] {0}".format(message['payload']))
    else:
        print(message)

device = frida.get_usb_device()
pid = device.spawn(['com.example.mybackup'])
process = device.attach(pid)
 
script = process.create_script(jscode)
 
script.on("message", on_message)
script.load()
device.resume(pid)
sys.stdin.read()

這里說明一下與上一個frida腳本的區別,這道題需要拿到sqlite的db,所以需要hook getReadableDatabase這個函數,這個函數在構造函數中所以需要在APK剛運行時插樁,使用了spawn。

拿到db之后就容易了,再獲取到cursor,讀取數據庫就好了。

這里還有一個坑點,由於這個apk使用了sqlcipher庫,這個庫中的cursor是經過包裝的接口,真正的Cursor.moveToNext等函數在AbstractCursor中實現,這里直接拿到cursor的話,調用

cursor.moveToNext會報錯,所以需要強制cast成android.database.Cursor這個類型才行。當時嘗試了直接獲取AbstractCursor的instance和獲取cursor的instance都不可以。。

最終效果:

 不得不說,frida真的是神器。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM