此文总结于看雪安卓安全白皮书第9章
破解重点于核心功能存在于那端,若在服务端只能尽可能分析交互数据手动仿造
1.试用版软件
常见类型
免费试用:过一定期限后无法使用,理论上存在完整数据,可破解
演示版:只有部分功能演示用,本地无数据,不可破解
限制版:部分功能付费开启,视情况定,看是否有功能数据。
关于示例1:
- createPackageContext用于获取其它程序的context,甚至可执行其它软件的代码,要求有相同的用户id(manifest标签中的android:sharedUserID)与签名。当俩个程序用户id相同时,这俩个程序运行在同一个进程空间。
- java的加密解密类:123456789101112131415161718192021222324252627取key 参数为种子public static byte[] getRawKey(byte[] seed) throws Exception {KeyGenerator kgen = KeyGenerator.getInstance("AES"); //key生产者,生成指定算法的keySecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); //安全随机sr.setSeed(seed); //设置seedkgen.init(128, sr); // 192 and 256 bits may not be available //指定密匙大小和随机源SecretKey skey = kgen.generateKey(); //生成一个密钥 同一个key同一次使用生成的是一个,但一次运行多次生成的不同byte[] raw = skey.getEncoded(); //返回基本编码格式的密钥return raw;}加密 参数1:key 参数2:明文 返回密文private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); //key的规格与值Cipher cipher = Cipher.getInstance("AES"); //密码初始cipher.init(Cipher.ENCRYPT_MODE, skeySpec); //密码设置keybyte[] encrypted = cipher.doFinal(clear);return encrypted;}解密 参数1:key 参数2密文 返回明文private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); //key的规格与值Cipher cipher = Cipher.getInstance("AES"); //密码实例cipher.init(Cipher.DECRYPT_MODE, skeySpec); //用key设置密码byte[] decrypted = cipher.doFinal(encrypted); //解密return decrypted;}
2.序列号保护
用户提供机器码,厂商用注册机生成注册码,用户用注册码使用软件,一般软件注册码保证机器/用户对应
3.网络验证
未成功
网络分析可以使用android移植版的tcpdump工具。位于模拟器下的/system/xbin/下。
adb shell tcpdump -p -vv -s 0 -w /sdcard/xxx.pcap
之后用 adb pull /scard/xxx.pcap取出用wireshark分析即可
网上还有种思路是pc开热点用wireshark分析虚拟网卡即可。但我的ws识别不出虚拟网卡……?
4.应用内付费
这个建议写一个应用试试。
应用实现一个服务与广播接收器,该服务与付费服务(由支付宝等提供)沟通,用户操作结果通过广播/服务返回,应用再随意处理。
5.向商店查询
通过应用商点app接口向商店查询用户已买app
6.重启验证
将得到的信息保存本地。之后应用在执行各种功能,步骤时检验文件核心的检验步骤可放在native层。
示例中:
- JNI_OnLoad加载时调用。JNIEnv表示java环境,不可跨线程,因此设置java native函数对应地址表没问题,JavaVM代表虚拟机,主要就是线程相关
- 由native层验证判断后调用java层代码实现功能。
- JNI中对应的java native函数的名字不一定是javah生成的那样。12345(*env)->RegisterNatives(env,native_class, methods, num){//把java类的native函数对应到原生函数中,手动。自动的话是按javah生成的对应,这里没有包含javah生成的头文件//参1:jclass:要对应的java类//参2:JNINativeMethod数组,表明了java类中方法的名字,元数据,原生函数地址//参3:参数2数组length
7.Mono初探
Mono使linux上可运行.NET c#程序。untiy使用该方法跨平台,游戏安全中重点了解。
目前只找到官网资料:http://www.mono-project.com/
基本原理与java同,就是c#脚本编译为il语言的dll之后用mono实现的clr运行时jit(时时编译为原生)或者aot(提前编译为原生)运行。
此时就可以动态修改代码实现热更新。crl虚拟机也是基于栈的。
现在unity又实现了IL2CPP功能,可以讲IL再编译为c++代码,由于c++有许多跨平台编译器,所以可以编译成多平台运行。但是由于内存管理等语言特性需要小虚拟机管理,同时由于可执行代码的复杂度增加失去热更新。
总结:学好c++与c++逆向,什么都好说