Android逆向 (二) 找flag实例1-java层

一、系统环境

OS: Windows_NT x64 10.0.19045

python:3.8.10

Node.js: 18.17.1

frida :14.2.14

objection:1.11.0

vscode: 1.87.2

device:nexus 5x-7.1.2

二、详细分析

1.首先用jadx查看程序逻辑

这个实例没有加壳,可以很清晰的看到程序代码,直接打开MainActivity就可以看到验证的代码位置

通过上面的代码可以看到用户名和密码相加后的内容传入到VVVVV.VVVV进行校验,根据返回的结果弹出不同的提示内容,下面是VVVVV这个类的完整代码

public class VVVVV {
    private VVVVV() {
    }

    public static boolean VVVV(View.OnClickListener context, String input) {
        if (input.length() != 5) {
            return false;
        }
        byte[] v = eeeee(input);
        byte[] p = "6f452303f18605510aac694b0f5736beebf110bf".getBytes();
        if (v.length != p.length) {
            return false;
        }
        for (int i = 0; i < v.length; i++) {
            if (v[i] != p[i]) {
                return false;
            }
        }
        return true;
    }

    private static byte[] eeeee(String input) {
        byte[] SALT = {95, 35, 83, 73, 75, 35, 95};
        try {
            StringBuilder sb = new StringBuilder();
            sb.append((char) SALT[0]);
            sb.append((char) SALT[1]);
            for (int i = 0; i < input.length(); i++) {
                sb.append((char) input.getBytes("iso-8859-1")[i]);
                sb.append((char) SALT[i + 2]);
            }
            sb.append((char) SALT[6]);
            byte[] bArr = new byte[0];
            return sssss(sb.toString()).getBytes("iso-8859-1");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
    }

    private static String ccccc(byte[] data) {
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < data.length; i++) {
            int halfbyte = (data[i] >>> 4) & 15;
            int two_halfs = 0;
            while (true) {
                if (halfbyte < 0 || halfbyte > 9) {
                    buf.append((char) ((halfbyte - 10) + 97));
                } else {
                    buf.append((char) (halfbyte + 48));
                }
                halfbyte = data[i] & 15;
                int two_halfs2 = two_halfs + 1;
                if (two_halfs >= 1) {
                    break;
                }
                two_halfs = two_halfs2;
            }
        }
        return buf.toString();
    }

    private static String sssss(String text) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            byte[] bArr = new byte[40];
            md.update(text.getBytes("iso-8859-1"), 0, text.length());
            return ccccc(md.digest());
        } catch (UnsupportedEncodingException e2) {
            e2.printStackTrace();
            return null;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }
}

从这个代码可以知道账户名加密码也就是flag的长度是5个数字


        if (input.length() != 5) {
            return false;
        }

从上面的代码可以看出调用逻辑是

VVVV -> eeeee -> sssss -> ccccc

只有VVVV是进行校验的地方,后面3个函数都是对输入的内容进行加密的代码

通过上面的分析发现有两种方式可以获得flag:

1.暴力破解,通过循环的方式调用VVVV获得正确的flag

2.把加密代码抠出来,用android studio创建工程调用加密代码获得正确的flag加密后的内容

目标明确后就用objection来验证函数的调用逻辑是否正确

2.用objection调试看函数内容

打开终端运行附加进程命令

objection -g com.kanxue.pediy1 explore

验证内存中类是否存在

android hooking search classes com.kanxue.pediy1.VVVVV

hook指定方法并打印调用信息

com.kanxue.pediy1 on (google: 7.1.2) [usb] # android hooking watch  class_method com.kanxue.pediy1.VVVVV.VVVV  --dump-args --dump-backtrace --dump-return
(agent) Attempting to watch class com.kanxue.pediy1.VVVVV and method VVVV.
(agent) Hooking com.kanxue.pediy1.VVVVV.VVVV(android.view.View$OnClickListener, java.lang.String)
(agent) Registering job 483231. Type: watch-method for: com.kanxue.pediy1.VVVVV.VVVV
com.kanxue.pediy1 on (google: 7.1.2) [usb] # (agent) [483231] Called com.kanxue.pediy1.VVVVV.VVVV(android.view.View$OnClickListener, java.lang.String)
(agent) [483231] Backtrace:
        com.kanxue.pediy1.VVVVV.VVVV(Native Method)
        com.kanxue.pediy1.MainActivity$1.onClick(MainActivity.java:36)
        android.view.View.performClick(View.java:5637)
        android.view.View$PerformClick.run(View.java:22429)
        android.os.Handler.handleCallback(Handler.java:751)
        android.os.Handler.dispatchMessage(Handler.java:95)
        android.os.Looper.loop(Looper.java:154)
        android.app.ActivityThread.main(ActivityThread.java:6121)
        java.lang.reflect.Method.invoke(Native Method)
        com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
        com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
        de.robv.android.xposed.XposedBridge.main(XposedBridge.java:107)

(agent) [483231] Arguments com.kanxue.pediy1.VVVVV.VVVV([object Object], ass1112)
(agent) [483231] Return Value: (none)


3.用frida进行hook修改函数执行结果

function main(){
    Java.perform(function(){
        //先故意写错,通过异常提示来得出函数的参数签名
        Java.use("com.kanxue.pediy1.VVVVV").VVVV.implementation = function(x){
            var result = this.VVVV(x);
            console.log("x,y,result:",x,result);
            return result;
        }
    })
}

setImmediate(main);

通过异常信息得到参数签名

[Nexus 5X::com.kanxue.pediy1]-> Error: expected an unsigned integer
Error: VVVV(): argument types do not match any of:
        .overload('android.view.View$OnClickListener', 'java.lang.String')  

把正确的参数签名填入代码后,就可以获得正常hook函数

function main(){
    Java.perform(function(){
        //先故意写错,通过异常提示来得出函数的参数签名
        // Java.use("com.kanxue.pediy1.VVVVV").VVVV.implementation = function(x){
        //     var result = this.VVVV(x);
        //     console.log("x,y,result:",x,result);
        //     return result;
        // }

        Java.use("com.kanxue.pediy1.VVVVV").VVVV.overload('android.view.View$OnClickListener', 'java.lang.String').implementation = function(x,y){
            var result = this.VVVV(x,y);
            console.log("x,y,result:",x,y,result);
            return result;
        }
    })
}

setImmediate(main);
x,y,result: [object Object] 33311 false

修改代码循环调用VVVV轮询出正确的flag,flag确定是5位数,所以flag的范围一定是在10000-99999之间

        Java.use("com.kanxue.pediy1.VVVVV").VVVV.overload('android.view.View$OnClickListener', 'java.lang.String').implementation = function(x,y){

            var intv = 10000;
            for(var i = 0;i < 90000; i++){
                var strv = intv + i;
                var result = this.VVVV(x,strv.toString());
                if(result == true){
                    console.log("x,y,result:",x,strv.toString(),result);
                }
                
            }
            return result;
        }

注入js文件注入程序

$frida -U com.kanxue.pediy1 -l test1.js

获取正确flag

[Nexus 5X::com.kanxue.pediy1]-> x,y,result: [object Object] 66888 true

第2种扣代码用android studio写的方式大同小异就不写了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值