android UnCrackable练习 OWASP的crackme练习里面有一些app安全的保护,破解者需要掌握一些逆向的知识才能获取正确的值。下面是android的两个题目,能帮助掌握基本的jadx逆向java代码、frida和ida逆向so的使用。
样本地址: Github:https://github.com/OWASP/owasp-mstg/tree/master/Crackmes 百度网盘地址: 链接: https://pan.baidu.com/s/1YCiUU2Xy2xBSUQNxric8mQ 密码: 81kn
我用到的环境和工具
pixel xl arm64-v8a
python 3.8.0
frida 12.8.0
java 11.0.8
jadx 1.1.0
IDA 7.0
Ghidra 9.1.2
Android Level 1 UnCrackable1下载
考察的知识点: java逆向、root检测绕过 工具:jadx 、frida
安装应用
1 2 3 owasp-mstg/Crackmes/Android/Level_01(master*) » adb install UnCrackable-Level1.apk Performing Streamed Install Success
打开应用会提示root 要绕root 用jadx打开apk 搜索root文本 发现c.a\c.b\c.c方法是判断root然后进入到方法里查看(选中方法右键跳到声明)
1 2 3 4 5 6 7 8 9 10 11 12 ··· public void onCreate(Bundle bundle) { if (c.a() || c.b() || c.c()) { a("Root detected!"); } if (b.a(getApplicationContext())) { a("App is debuggable!"); } super.onCreate(bundle); setContentView(R.layout.activity_main); } ···
跳到方法发现这个类是检测root的类,使用frida进行hook掉检测类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package sg.vantagepoint.a; import android.os.Build; import java.io.File; public class c { public static boolean a() { for (String file : System.getenv("PATH").split(":")) { if (new File(file, "su").exists()) { return true; } } return false; } public static boolean b() { String str = Build.TAGS; return str != null && str.contains("test-keys"); } public static boolean c() { for (String file : new String[]{"/system/app/Superuser.apk", "/system/xbin/daemonsu", "/system/etc/init.d/99SuperSUDaemon", "/system/bin/.ext/.su", "/system/etc/.has_su_daemon", "/system/etc/.installed_su_daemon", "/dev/com.koushikdutta.superuser.daemon/"}) { if (new File(file).exists()) { return true; } } return false; } }
首先通过逆向分析发现sg.vantagepoint.a.c的类是检测root的类 c类下的a、b、c方法是检测的方法hook方法让他返回值为false frida代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Java.perform(function () { send("hook start"); var c=Java.use("sg.vantagepoint.a.c"); //返回值改成false c.a.overload().implementation = function(){ return false; } c.b.overload().implementation = function(){ return false; } c.c.overload().implementation = function(){ return false; } send("hook end"); });
执行frida代码frida -U -f owasp.mstg.uncrackable1 --no-pause -l uncrackable1.js
启动后已经hook成功了,没有弹框了,然后是随便输入个值在点击VERIFY,提示That’s not it.Try again. 然后我们在jadx反编译后的代码里搜索下Try again 发现跳转verify方法,用于验证的是a.a(obj)跳转到a方法 1可以继续用frida hook该函数进行返回值输出
1 2 3 4 5 6 7 8 9 10 11 public static boolean a(String str) { byte[] bArr; byte[] bArr2 = new byte[0]; try { bArr = sg.vantagepoint.a.a.a(b("8d127684cbc37c17616d806cf50473cc"), Base64.decode("5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc=", 0)); } catch (Exception e) { Log.d("CodeCheck", "AES error:" + e.getMessage()); bArr = bArr2; } return str.equals(new String(bArr)); }
frida代码:
1 2 3 4 5 6 7 8 var a =Java.use("sg.vantagepoint.a.a"); a.a.overload('[B', '[B').implementation=function(arg1,arg2){ //执行函数 var ret = this.a(arg1,arg2); //输出返回值 console.log(jhexdump(ret)); return ret; }
uncrackable1.js frida完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 // owasp.mstg.uncrackable1 // hookroot检测 function hookrootuncrackable1(){ Java.perform(function () { send("hook start"); var c=Java.use("sg.vantagepoint.a.c"); //返回值改成false c.a.overload().implementation = function(){ return false; } var a =Java.use("sg.vantagepoint.a.a"); /** *重载报错 根据报错把overload添加上就可以了 * Error: a(): argument count of 0 does not match any of: .overload('[B', '[B') at throwOverloadError (frida/node_modules/frida-java-bridge/lib/class-factory.js:1020) at frida/node_modules/frida-java-bridge/lib/class-factory.js:686 at /uncrackable1.js:13 at frida/node_modules/frida-java-bridge/lib/vm.js:11 at E (frida/node_modules/frida-java-bridge/index.js:346) at frida/node_modules/frida-java-bridge/index.js:332 at input:1 */ a.a.overload('[B', '[B').implementation=function(arg1,arg2){ //执行函数 var ret = this.a(arg1,arg2); console.log(jhexdump(ret)); // console.log(byte2string(ret)); /*** * retval = this.a(arg1, arg2); password = '' for(i = 0; i < retval.length; i++) { password += String.fromCharCode(retval[i]); } console.log("[*] Decrypted: " + password); */ return ret; } send("hook end"); }); } function jhexdump(array,off,len) { var ptr = Memory.alloc(array.length); for(var i = 0; i < array.length; ++i) Memory.writeS8(ptr.add(i), array[i]); //console.log(hexdump(ptr, { offset: off, length: len, header: false, ansi: false })); console.log(hexdump(ptr, { offset: 0, length: array.length, header: false, ansi: false })); } function main(){ hookrootuncrackable1(); } setImmediate(main) // owasp.mstg.uncrackable1 //frida -U -f owasp.mstg.uncrackable1 --no-pause -l uncrackable1.js
执行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ~ » frida -U -f owasp.mstg.uncrackable1 --no-pause -l uncrackable1.js ____ / _ | Frida 12.8.0 - A world-class dynamic instrumentation toolkit | (_| | > _ | Commands: /_/ |_| help -> Displays the help system . . . . object? -> Display information about 'object' . . . . exit/quit -> Exit . . . . . . . . More info at https://www.frida.re/docs/home/ Spawned `owasp.mstg.uncrackable1`. Resuming main thread! [Google Pixel XL::owasp.mstg.uncrackable1]-> message: {'type': 'send', 'payload': 'hook start'} data: None message: {'type': 'send', 'payload': 'hook end'} data: None 7062ac63b0 49 20 77 61 6e 74 20 74 6f 20 62 65 6c 69 65 76 I want to believ 7062ac63c0 65 e
I want to believe 是最后的值
2.分析代码使用aes算法进行输出
1 2 » echo 5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc= | openssl enc -aes-128-ecb -base64 -d -nopad -K 8d127684cbc37c17616d806cf50473cc I want to believe%
解题参考链接:https://www.codemetrix.io/hacking-android-apps-with-frida-2/ 翻译【技术分享】利用FRIDA攻击Android应用程序(二)
Android Level 2 UnCrackable2下载 考察的知识点: java逆向、root检测绕过、so逆向 工具:jadx 、frida 、IDA、Ghidra
安装应用:adb install UnCrackable-Level2.apk
发现仍然有root检测 用jadx打开UnCrackable-Level2.apk分析下代码吧~ jadx-gui UnCrackable-Level2.apk
依旧搜索Root detected!
发现跟第一道题是一样的,就是类名换掉了,用frida在hook下,就可以解决了 frida代码:
1 2 3 4 5 6 7 8 9 10 11 12 Java.perform(function(){ var b=Java.use("sg.vantagepoint.a.b"); b.a.overload().implementation = function(){ return false; } b.b.overload().implementation = function(){ return false; } b.c.overload().implementation = function(){ return false; } });
正常启动后再搜索Try again
1 2 3 4 5 6 7 8 9 10 verify() ··· if (this.m.a(obj)) { create.setTitle("Success!"); str = "This is the correct secret."; } else { create.setTitle("Nope..."); str = "That's not it. Try again."; } ···
1 2 3 4 5 private native boolean bar(byte[] bArr); public boolean a(String str) { return bar(str.getBytes()); }
最后分析到a方法最后到了bar方法是native函数里,是写在so里的,需要用IDA进行分析 解压UnCrackable-Level2.apk 到Level_02/UnCrackable-Level2/lib/armeabi-v7a文件夹中有个libfoo.so文件用IDA打开进行分析 搜索bar函数 按F5查看伪c代码 发现有个Thanks for all the fish
字符串尝试输入,发现已经Success了
除了IDA还可以用Ghidra打开尝试 搜索bar函数 打开 分析代码发现有几个值进行对比 然后拼接后转字符串查看 小端序所以是倒着的6873696620656874206c6c6120726f6620736b6e616854
使用十六进制转换工具进行查看 十六进制转换工具:https://zixuephp.net/tool-str-hex.html 选择16进制转字符串就可以了 工具:https://gchq.github.io/CyberChef 得到的结果hsif eht lla rof sknahT
最后的结果Thanks for all the fish
解题参考链接:https://tereresecurity.wordpress.com/2021/03/23/write-up-uncrackable-level-2/
https://enovella.github.io/android/reverse/2017/05/20/android-owasp-crackmes-level-2.html
https://www.codemetrix.io/hacking-android-apps-with-frida-3/ 翻译【技术分享】利用FRIDA攻击Android应用程序(三)
Android Level 3 解题参考链接:https://enovella.github.io/android/reverse/2017/05/20/android-owasp-crackmes-level-3.html
http://sh3llc0d3r.com/owasp-uncrackable-android-level3/ 翻译【技术分享】利用FRIDA攻击Android应用程序(四)
Android Level 4 https://www.romainthomas.fr/post/20-09-r2con-obfuscated-whitebox-part1/ https://www.romainthomas.fr/post/20-09-r2con-obfuscated-whitebox-part2/
LINKS [原创]UnCrackable App 三部曲学习记录分享 OWASP Android Uncrackable1~3练习
Author:
tea9
Permalink:
http://tea9.github.io/post/2623200361.html
License:
Copyright (c) 2017-2025 CC-BY-NC-4.0 LICENSE
Slogan:
Do you believe in DESTINY ?