ToB企服应用市场:ToB评测及商务社交产业平台

标题: Frida主动调用java函数来爆破解题思路 [打印本页]

作者: 盛世宏图    时间: 2023-7-12 02:45
标题: Frida主动调用java函数来爆破解题思路
利用Frida去调用java代码中的类,然后爆破。算是一种主动调用的方法。主动调用可以用于爆破,模拟程序部分执行,需要注意的知识点是在java代码中的static类型数据在爆破过程中需要每次都对这种类型值重新设置。因为static类型在所有实例中都是统一,修改一个实例就会修改所有实例,需要用变量.属性.value = ...的写法重新设置值。
  1. var bvar = b.$new(IntClass.$new(2));
  2. for (...) {
  3.    bvar._static_val.value = ...;
  4. }
复制代码
背景知识

java类中静态值在爆破中需要修改

在java类中,一个属性如果是static的,不是说这个值不能改,而是说这个属性在程序中是唯一的,无论几个实例,只要改了其中一个实例中static的值,其他实例对应的值也会被改变。
在爆破过程中,如果需要爆破过程中不停new一个新的类实例,记得看看其中有没有static类型的变量。比如下面的这个例子
  1. public class b {
  2.    public static ArrayList<Integer> a = new ArrayList<>();
  3.    static String b = "abcdefghijklmnopqrstuvwxyz";
  4.    static Integer d = 0;
  5.    Integer[] c = {8, 25, 17, 23, 7, 22, 1, 16, 6, 9, 21, 0, 15, 5, 10, 18, 2, 24, 4, 11, 3, 14, 19, 12, 20, 13};
  6.    public b(Integer num) {
  7.        for (int intValue = num.intValue(); intValue < this.c.length; intValue++) {
  8.            a.add(this.c[intValue]);
  9.        }
  10.        for (int i = 0; i < num.intValue(); i++) {
  11.            a.add(this.c[i]);
  12.        }
  13.    }
  14. ...
复制代码
每次new一个b类,比如b bVar = new b(2).如果要不停调用这个类,并且使用其中的方法,要注意其中的static变量会不会变。如果会变,那么在爆破过程中,需要new完实例后,修改static变量的值。
frida调用java中静态方法与动态方法

如果调用静态方法,可以直接调用,比如java代码如下
  1. public class Verifier {
  2.    private Verifier() {
  3.    }
  4.    public static boolean verifyPassword(Context context, String input) {
  5.        ...
  6.    }
复制代码
那么如果调用verifyPassword可以直接在frida中调用
  1. var verify = Java.use("org.teamsik.ahe17.qualification.Verifier");
  2. verify.verifyPassword(a, b);
复制代码
如果是动态方法,有两种方法可以调用动态方法
【----帮助网安学习,以下所有学习资料免费领!加vx:yj009991,备注 “博客园” 获取!】
 ① 网安学习成长路径思维导图
 ② 60+网安经典常用工具包
 ③ 100+SRC漏洞分析报告
 ④ 150+网安攻防实战技术电子书
 ⑤ 最权威CISSP 认证考试指南+题库
 ⑥ 超1800页CTF实战技巧手册
 ⑦ 最新网安大厂面试题合集(含答案)
 ⑧ APP客户端安全检测指南(安卓+IOS)
第一种是,使用内存中已存在实例的方法,需要用到java.choose(...),这个是在内存中寻找对象
  1. //从内存中(堆)直接搜索已存在的对象
  2. Java.choose('xxx.xxx.xxx', //这里写类名
  3. {   //onMatch 匹配到对象执行的回调函数
  4.     onMatch: function (instance) {
  5.    },
  6.    //堆中搜索完成后执行的回调函数
  7.    onComplete: function () {
  8.    }
  9. });
复制代码
第二种是,我们new一个新的实例,然后调用实例中的方法
  1. //获取类的引用
  2. var cls = Java.use('这里写类名');
  3. //调用构造函数 创建新对象  这里注意参数
  4. var obj = cls.$new();
复制代码
Easy-QAHE17

首先是看吾爱破解的一道题目,核心代码如下。
  1. public void verifyPasswordClick(View view) {
  2.        String password = this.txPassword.getText().toString();
  3.        if (!Verifier.verifyPassword(this, password)) {
  4.            Toast.makeText(this, (int) org.teamsik.ahe17.qualification.easy.R.string.dialog_failure, 1).show();
  5.        } else {
  6.            showSuccessDialog();
  7.        }
  8.    }
  9. public class Verifier {
  10.    private Verifier() {
  11.    }
  12.    public static boolean verifyPassword(Context context, String input) {
  13.        if (input.length() != 4) {
  14.            return false;
  15.        }
  16.        byte[] v = encodePassword(input);
  17.        byte[] p = "09042ec2c2c08c4cbece042681caf1d13984f24a".getBytes();
  18.        if (v.length == p.length) {
  19.            for (int i = 0; i < v.length; i++) {
  20.                if (v[i] != p[i]) {
  21.                    return false;
  22.                }
  23.            }
  24.            return true;
  25.        }
  26.        return false;
  27.    }
  28. ...
  29. ...
  30. ...
复制代码
输入长度为4,通过分析后面知道输入是数字。所以范围是1000-9999.所以是可以爆破的,但是爆破是要用到encodePassword方法,自己写一个当然也可以,但是很麻烦。这里就可以直接frida调用encodePassword函数.
注意这里encodePassword是静态方法,所以可以直接调用
  1. function main() {
  2.    Java.perform(function x() {
  3.        console.log("In Java perform")
  4.        var verify = Java.use("org.teamsik.ahe17.qualification.Verifier")
  5.        var stringClass = Java.use("java.lang.String")
  6.        var p = stringClass.$new("09042ec2c2c08c4cbece042681caf1d13984f24a")
  7.        
  8.        for (var i = 999; i < 10000; i++){
  9.            var v = stringClass.$new(String(i))
  10.            var vSign = verify.encodePassword(v)
  11.            if (parseInt(p) == parseInt(stringClass.$new(vSign))) {
  12.                console.log("yes: " + v)
  13.                break
  14.            }
  15.            console.log("not :" + v)
  16.        }
  17.    })
  18. }
  19. setImmediate(main)
复制代码
结果
  1. not :9078
  2. not :9079
  3. not :9080
  4. not :9081
  5. not :9082
  6. yes: 9083
复制代码
需要注意的是,要调用parseInt解析内存中的内存再对比,因为string类型是java的string类型,对js代码来说是一段内存。
EasyJava

这题是纯java题,逻辑很清晰,对输入的每一个字符单个检查,加密并对比。所以可以很简单的想到爆破的思路
  1. public static Boolean b(String str) {
  2.    if (str.startsWith("flag{") && str.endsWith("}")) {
  3.        String substring = str.substring(5, str.length() - 1);
  4.        b bVar = new b(2);
  5.        a aVar = new a(3);
  6.        StringBuilder sb = new StringBuilder();
  7.        int i = 0;
  8.        for (int i2 = 0; i2 < substring.length(); i2++) {
  9.            sb.append(a(substring.charAt(i2) + "", bVar, aVar));
  10.            Integer valueOf = Integer.valueOf(bVar.b().intValue() / 25);
  11.            if (valueOf.intValue() > i && valueOf.intValue() >= 1) {
  12.                i++;
  13.            }
  14.        }
  15.        return Boolean.valueOf(sb.toString().equals("wigwrkaugala"));
  16.    }
  17.    return false;
  18. }
复制代码
所以可以单个字符爆破,但是要注意到,com.a.easyjava.b和com.a.easyjava.a两个类中都存在static属性的变量,下面是b类的
  1. public class b {
  2.    public static ArrayList<Integer> a = new ArrayList<>();
  3.    static String b = "abcdefghijklmnopqrstuvwxyz";
  4.    static Integer d = 0;
  5.    Integer[] c = {8, 25, 17, 23, 7, 22, 1, 16, 6, 9, 21, 0, 15, 5, 10, 18, 2, 24, 4, 11, 3, 14, 19, 12, 20, 13};
  6.    public b(Integer num) {
  7.        for (int intValue = num.intValue(); intValue < this.c.length; intValue++) {
  8.            a.add(this.c[intValue]);
  9.        }
  10.        for (int i = 0; i < num.intValue(); i++) {
  11.            a.add(this.c[i]);
  12.        }
  13.    }
  14.    public static void a() {
  15.        int intValue = a.get(0).intValue();
  16.        a.remove(0);
  17.        a.add(Integer.valueOf(intValue));
  18.        b += "" + b.charAt(0);
  19.        b = b.substring(1, 27);
  20.        Integer num = d;
  21.        d = Integer.valueOf(d.intValue() + 1);
  22.    }
  23.    public Integer a(String str) {
  24.        int i = 0;
  25.        if (b.contains(str.toLowerCase())) {
  26.            Integer valueOf = Integer.valueOf(b.indexOf(str));
  27.            for (int i2 = 0; i2 < a.size() - 1; i2++) {
  28.                if (a.get(i2) == valueOf) {
  29.                    i = Integer.valueOf(i2);
  30.                }
  31.            }
  32.        } else {
  33.            i = str.contains(" ") ? -10 : -1;
  34.        }
  35.        a();
  36.        return i;
  37.    }
  38.    public Integer b() {
  39.        return d;
  40.    }
  41. }
复制代码
b类中的a,b,d变量都是static类型的同时,这三个变量都会被下面的方法所改变。所以如果要爆破,需要重新修改实例中的属性值。如果不重新修改属性的值,我们通过观察b类中的b变量可以看到会有什么问题。
这个脚本是爆破第一个字符在加密后所有的可能性。爆破范围通过分析b类可以缩小到a-z,然后模仿加密过程,加密一个字符看看结果。中间每循环一次会重新申请一个b和a类的实例,想通过申请新的实例来避免类中变量的修改.
  1. function main() {
  2.    Java.perform(function x() {
  3.        console.log('[+] script load');
  4.        
  5.        var b = Java.use("com.a.easyjava.b");
  6.        var a = Java.use("com.a.easyjava.a");
  7.        var StringClass = Java.use("java.lang.String");
  8.        var IntClass = Java.use("java.lang.Integer");
  9.        var MainActivity = Java.use("com.a.easyjava.MainActivity");
  10.        try { // try catch 用来查看报错的,可以去掉
  11.            for (var i = 97; i < 123; i++) {
  12.                var bvar = b.$new(IntClass.$new(2));
  13.                var avar = a.$new(IntClass.$new(3));
  14.                var s = String.fromCharCode(i);
  15.                var c = MainActivity.a(s, bvar, avar);
  16.                console.log(`enc(${s}) => ${c}, b.a => ${b._b.value}`);
  17.            }
  18.        } catch (e) {
  19.            console.log(e);
  20.        }
  21.        console.log('[+] script end');
  22.    })
  23. }
  24. setImmediate(main)
复制代码
结果如下
  1. # python3 loader.py
  2. [+] script load
  3. enc(a) => a, b.b => bcdefghijklmnopqrstuvwxyza
  4. enc(b) => a, b.b => cdefghijklmnopqrstuvwxyzab
  5. enc(c) => a, b.b => defghijklmnopqrstuvwxyzabc
  6. enc(d) => a, b.b => efghijklmnopqrstuvwxyzabcd
  7. enc(e) => a, b.b => fghijklmnopqrstuvwxyzabcde
  8. enc(f) => a, b.b => ghijklmnopqrstuvwxyzabcdef
  9. enc(g) => a, b.b => hijklmnopqrstuvwxyzabcdefg
  10. enc(h) => a, b.b => ijklmnopqrstuvwxyzabcdefgh
  11. enc(i) => a, b.b => jklmnopqrstuvwxyzabcdefghi
  12. enc(j) => a, b.b => klmnopqrstuvwxyzabcdefghij
  13. enc(k) => a, b.b => lmnopqrstuvwxyzabcdefghijk
  14. enc(l) => a, b.b => mnopqrstuvwxyzabcdefghijkl
  15. enc(m) => a, b.b => nopqrstuvwxyzabcdefghijklm
  16. enc(n) => a, b.b => opqrstuvwxyzabcdefghijklmn
  17. enc(o) => a, b.b => pqrstuvwxyzabcdefghijklmno
  18. enc(p) => a, b.b => qrstuvwxyzabcdefghijklmnop
  19. enc(q) => a, b.b => rstuvwxyzabcdefghijklmnopq
  20. enc(r) => a, b.b => stuvwxyzabcdefghijklmnopqr
  21. enc(s) => a, b.b => tuvwxyzabcdefghijklmnopqrs
  22. enc(t) => a, b.b => uvwxyzabcdefghijklmnopqrst
  23. enc(u) => a, b.b => vwxyzabcdefghijklmnopqrstu
  24. enc(v) => a, b.b => wxyzabcdefghijklmnopqrstuv
  25. enc(w) => a, b.b => xyzabcdefghijklmnopqrstuvw
  26. enc(x) => a, b.b => yzabcdefghijklmnopqrstuvwx
  27. enc(y) => a, b.b => zabcdefghijklmnopqrstuvwxy
  28. enc(z) => a, b.b => abcdefghijklmnopqrstuvwxyz
  29. [+] script end
复制代码
可以看到实际上,虽然每次new了一个新的实例,但是实例中的static变量是变了的,这导致了之前的爆破会影响到下一次爆破,同时也可以看到加密结果全部都是a。所以如果要爆破,就得想办法让每次爆破,新的实例中的值不变。
需要使用bvar._b.value = StringClass.$new("abcdefghijklmnopqrstuvwxyz");这样的语法对static类型的变量重新设值。
需要注意的是有些变量在jadx/jeb中看到的名字可能会被重载,需要加一个下划线比如b -> _b。可以通过console打印看看是不是unknow,也可以直接用jadx右键复制frida片段,查看此变量frida需不需要加一个下划线
解题脚本的思路就很简单,单个字符来爆破,每次重新生成类的实例,并将类中的值置为初始状态(通过调用类$init方法)。
exp
  1. function main() {
  2.    Java.perform(function x() {
  3.        console.log('[+] script load');
  4.        var b = Java.use("com.a.easyjava.b");
  5.        var a = Java.use("com.a.easyjava.a");
  6.        var IntClass = Java.use("java.lang.Integer");
  7.        var StringClass = Java.use("java.lang.String");
  8.        var ArrayList = Java.use("java.util.ArrayList");
  9.        var MainActivity = Java.use("com.a.easyjava.MainActivity");
  10.        var flag = new Array();
  11.        var cipher = "wigwrkaugala";
  12.        var bvar = b.$new(IntClass.$new(2));
  13.        var avar = a.$new(IntClass.$new(3));
  14.        for (var _ = 0; _ < cipher.length; _++) {
  15.            for (var i = 97; i < 123; i++) { // 97 - 123是字母a-z
  16.                // reset static value
  17.                bvar._b.value = StringClass.$new("abcdefghijklmnopqrstuvwxyz");
  18.                bvar.d.value = IntClass.$new(0);
  19.                bvar._a.value = ArrayList.$new();
  20.                bvar["$init"](IntClass.$new(2));
  21.                avar.b.value = StringClass.$new("abcdefghijklmnopqrstuvwxyz");
  22.                avar.d.value = IntClass.$new(0);
  23.                avar._a.value = ArrayList.$new();
  24.                avar["$init"](IntClass.$new(3));
  25.                var s = String.fromCharCode(i);
  26.                flag.push(s);
  27.                for (var e = 0; e < flag.length; e++) {
  28.                    var c = MainActivity.a(flag[e].toString(), bvar, avar);
  29.                    if (c != cipher[e]) {
  30.                        break;
  31.                    }
  32.                }
  33.                if (c == cipher[flag.length - 1]) {
  34.                    console.log(flag);
  35.                    break
  36.                }
  37.                flag.length -= 1;
  38.            }
  39.        }
  40.        console.log('flag{' + flag.join('') + '}');
  41.        console.log('[+] script end');
  42.    })
  43. }
  44. setImmediate(main);
复制代码
结果
  1. root@kali ~/frida-script-dev# python3 loader.py
  2. [+] script load
  3. v
  4. v,e
  5. v,e,n
  6. v,e,n,i
  7. v,e,n,i,v
  8. v,e,n,i,v,i
  9. v,e,n,i,v,i,a
  10. v,e,n,i,v,i,a,i
  11. v,e,n,i,v,i,a,i,v
  12. v,e,n,i,v,i,a,i,v,i
  13. v,e,n,i,v,i,a,i,v,i,c
  14. v,e,n,i,v,i,a,i,v,i,c,i
  15. flag{veniviaivici}
  16. [+] script end
复制代码
更多网安技能的在线实操练习,请点击这里>>

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4