Android
作为一名弱鸡Android选手,刚了几个月的密码学,插播一条Android题。
使用JEB打开,可以看到给了AES-CBC加密后的密文,而且密文格式需要做一定处理,要求还原出明文。明文就是apk上要输入的密码。
代码里调用了so库,可以使用frida进行hook,将生成的IV和key打印出来再进行解密。也可以使用Android Studio加载so文件进行分析。
Hook方式
这里需要注意,对于byte[],直接再frida的js脚本里通过console.log打印将会返回Object对象,需要使用下面的方式打印IV。
js文件内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 setImmediate(function ( ) { Java.perform(function ( ) { var mc = Java.use("com.zhuotong.zzsence" ); var mc2 = mc.$new (); console .log("---------" ) var ret = mc2.generateIv(); var buffer = Java.array('byte' ,ret); console .log(ret); console .log(buffer.length); var result = []; for (var i=0 ;i<buffer.length;++i){ result += buffer[i]; } console .log(result); console .log("+++++++++" ); console .log(mc2.generatekey()); console .log("+++++++++" ); }); });
Hook对应的apk后得到加密使用的IV和key值
处理反编译读到的密文,得到byte[] n:
Android Studio的代码片段如下:
1 2 3 4 5 6 7 8 9 10 int [] t = new int []{0x7F , 41 , 0x20 , -23 , 53 , 0xFFFFFF8F , -59 , 0x9A , 5 , 16 , 52 , 0xBC , 91 , 150 , 43 , 0xA3 , 140 , 170 , 0x9E , 36 , 0x91 , 140 , 0xD3 , 17 , 18 , 0x4F , 200 , 0xB1 , 0x7A , 78 , 0xDB , 0xF7 };byte [] n = new byte [32 ];Log.i("Leon" ,Integer.toString(t.length)); for (int j = 0 ; j < 32 ; j++) { n[j] = ((byte ) t[j]); }
解密代码如下,注意这里的iv处理形式和解密使用的参数Cipher.DECRYPT_MODE:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public String decrypt (byte [] arg6) throws Exception { SecretKey key = handleKey("ipapmpnpoptppppppppppppppppppp" ).a(); byte [] iv = new byte [16 ]; int [] ivraw = new int []{0 ,2 ,4 ,6 ,8 ,10 ,12 ,14 ,16 ,18 ,20 ,22 ,24 ,26 ,28 ,30 }; for (int i = 0 ; i < 16 ; ++i) { iv[i] = ((byte ) ivraw[i]); } Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding" ); cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv)); return new String(cipher.doFinal(arg6)); } public static zzsence.a handleKey (String arg4) throws NoSuchAlgorithmException, UnsupportedEncodingException { return new zzsence().new a(new SecretKeySpec(Arrays.copyOf(MessageDigest.getInstance("SHA-1" ).digest(arg4.getBytes("UTF-8" )), 16 ), "AES" )); }
在Android Studio里调用decrypt(n)即可解出flag:flag{jsdg632t12}
加载SO方式
首先创建一个com.zhuotong.easyctf2的工程,zzsence的代码基本参考反编译后的内容。
并将libone.so放到app/main/jniLibs/armeabi-v7a下,如下图
注意zzsence.java里和so库相关的部分代码片段。
1 2 3 4 5 6 7 static { System.loadLibrary("one" ); } public static native byte [] generateIv();public static native String generatekey () ;
根据代码特点,写出如下解密代码:
1 2 3 4 5 6 7 8 9 10 public String decrypt (byte [] arg6,zzsence.a arg4) throws Exception { byte [] iv = zzsence.generateIv(); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding" ); cipher.init(Cipher.DECRYPT_MODE, arg4.a(), new IvParameterSpec(iv)); return new String(cipher.doFinal(arg6)); }
解密即可得到flag
1 decrypt(n, handleKey(zzsence.generatekey()))
在Android Studio里运行即可得到flag
在apk里输入后提示正确。