「这是我参与2022首次更文挑战的第23天,活动详情查看:2022首次更文挑战」
关于逆向
构建Proguard时都会输出一个mapping.txt文件,在app\build\outputs\mapping文件夹下,主要提供原始与混淆过的类、方法和字段名称之间的转换。这个文件非常重要,里面记述了解码混淆过的堆叠追踪。
比如我现在要传输一份重要名单文件,为防止传输过程中被恶意者拿到名单,我们对名单文件进行AES加密。在apk运行的时候,才通过解密来获取真实文件流。那么对于我的AESUtil解密类,我肯定希望混淆后,不会有人知道我的算法秘钥(password)和偏移量(iv)。
但是根据mapping.txt文件实际上是能跟踪到的。
追踪过程
首先我们查看一下源码(源代码为AESUtil.java类),主要代码就是这段,password和iv被调用的地方,实际上是AESUtil类的decrypt方法。
//--解密
public static byte[] decrypt(byte[] content) {
byte[] result = decryptByte2Byte(content, password, iv);
return result;
}
//-- 解密字节数组到字节数组
private static byte[] decryptByte2Byte(byte[] content, String password, String iv) {
try {
SecretKeySpec key = createKey(password);
Cipher cipher = Cipher.getInstance(CipherMode);
cipher.init(Cipher.DECRYPT_MODE, key, createIV(iv));
byte[] result = cipher.doFinal(content);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
接下来我们打开mapping.txt,搜索decrypt方法,并没有搜索到,但是有decryptByte2Byte方法,说明这两个方法被压缩为一个方法了,所以我们只需要找到decryptByte2Byte方法就可以了。
如图,它告诉我们,原来的AESUtil被编译为com.snap.update.g.a,decryptByte2Byte方法编译为了 a方法。我们打开编译后的代码:
找到该方法。该方法显示,参数是被传过的,所以我们转而找a方法被调用的地方。也就是源代码中的decrypt方法。查看源码,实际调用的地方,其实是UpdateManage类的updateMinimumRequired方法。在mapping.txt中搜索:
然后再去编译后的源码中寻找,如下,成功找到了偏移值和秘钥。
over
总结
当然,想要逆向我们项目的人一般是拿不到mapping.txt文档的,也不会知道我们方法的调用关系。举这个例子只是想说,逆向后的代码其实是存储了我们所有的代码内容的,只是不容易阅读而已。即混淆不能阻止反编译,只能增加反编译以后阅读理解的难度。
用官方的话来说就是,“Proguard通过移除没有用到的代码以及通过特定规则重命名类、变量、方法来压缩、优化、混淆你的代码。这样做可以让你的apk更小,更难被逆向分析。由于可以提高被逆向分析的难度,对相关功能安全敏感的应用使用它是十分必要的。”仅此而已。
就像是如果一个对AES加密相当了解的程序员,拿到了我们的apk,去破译我们的解密过程,是可以成功的。
最后,在安全技术这块,没有绝对安全的。我们能做的只是尽量运用各种加密算法、各种混淆加固等手段,尽量提高安全性而已。