观前提示:
本文章仅供学习交流,切勿用于非法通途,如有侵犯贵司请及时联系删除
样本:aHR0cHM6Ly9wYW4uYmFpZHUuY29tL3MvMTJEaHRKTFZnbUc1YWxmbTdBLUhQdGc/cHdkPWxpbm4=
0x1 加密点定位
这次的受害参数是x-zse-96
jadx-gui直接搜索无结果
搜索拦截器Interceptor 转到实现 发现有不明解密
hookH.d
方法 并发现方法被多次调用 直接搜索X-Zse-96
能看到x-zse-96
对应的密文就是G51CEEF09BA7DF27F
几次跳转后最终定位到加密位置
顺便hook传入参数以及返回结果留着备用
(agent) [548705] Arguments com.bangcle.CryptoTool.laesEncryptByteArr(34,-128,-127,-115,-118,41,-117,-119,42,-128,42,41,-119,-127,34,-117,33,-115,35,-120,41,-127,-120,40,-113,-127,33,-115,-120,35,-118,-115, 541a3a5896fbefd351917c8251328a236a7efbf27d0fad8283ef59ef07aa386dbb2b1fcbba167135d575877ba0205a02f0aac2d31957bc7f028ed5888d4bbe69ed6768efc15ab703dc0f406b301845a0a64cf3c427c82870053bd7ba6721649c3a9aca8c3c31710a6be5ce71e4686842732d9314d6898cc3fdca075db46d1ccf3a7f9b20615f4a303c5235bd02c5cdc791eb123b9d9f7e72e954de3bcbf7d314064a1eced78d13679d040dd4080640d18c37bbde, -103,48,58,58,50,52,58,57,-110,-110,58,59,58,-103,-110,-110) (agent) [548705] Return Value: -84,-33,-63,-1,-23,71,98,100,-3,58,38,9,29,-71,123,61,-52,-118,60,81,-51,-44,92,-93,5,122,117,5,118,-58,-91,-95,48,-2,-107,-34,-25,-114,-28,59,75,-72,-14,-67,-77,5,124,-113
0x2 so修复
打开libbangcle_crypto_tool.so
在导出表搜素可以直接搜到
双击进入 可以看到so加壳了
使用lasting-yang大佬的dumpso脚本即可
修复好的so也能正常看伪代码了
0x3 Unidbg调用
先造个轮子直接复制粘贴运行
public void laesEncryptByteArr(){ List<Object> args = new ArrayList<>(10); args.add(vm.getJNIEnv()); args.add(0); args.add(vm.addLocalObject(new ByteArray(vm,new byte[]{34,-128,-127,-115,-118,41,-117,-119,42,-128,42,41,-119,-127,34,-117,33,-115,35,-120,41,-127,-120,40,-113,-127,33,-115,-120,35,-118,-115}))); args.add(vm.addLocalObject(new StringObject(vm,"541a3a5896fbefd351917c8251328a236a7efbf27d0fad8283ef59ef07aa386dbb2b1fcbba167135d575877ba0205a02f0aac2d31957bc7f028ed5888d4bbe69ed6768efc15ab703dc0f406b301845a0a64cf3c427c82870053bd7ba6721649c3a9aca8c3c31710a6be5ce71e4686842732d9314d6898cc3fdca075db46d1ccf3a7f9b20615f4a303c5235bd02c5cdc791eb123b9d9f7e72e954de3bcbf7d314064a1eced78d13679d040dd4080640d18c37bbde"))); args.add(vm.addLocalObject(new ByteArray(vm,new byte[]{-103,48,58,58,50,52,58,57,-110,-110,58,59,58,-103,-110,-110}))); Number number=module.callFunction(emulator,0xa708,args.toArray()); Inspector.inspect((byte[]) vm.getObject(number.intValue()).getValue(),"laesEncryptByteArr"); }
接着就是补环境补上currentPackageName
@Override public DvmObject<?> callStaticObjectMethod(BaseVM vm, DvmClass dvmClass, String signature, VarArg varArg) { switch (signature){ case "android/app/ActivityThread->currentPackageName()Ljava/lang/String;":{ return new StringObject(vm,"com.xxx.android"); } } return super.callStaticObjectMethod(vm,dvmClass,signature,varArg); }
补完之后再运行出现不知名错误
找到rescources\log4j.properties
将INFO
替换为DEBUG
后运行
可以看到这里抛出了一个Write memory failed
不知道抛出什么 跳转过去看看
0xb17c
跳转过来 看着都很正常的样子
那就在get_pkgname
下个console debugger
断下后输入blr
然后输入c
放行
并没有出现报错 那就找交叉引用位置
来到引用位置
主要看sub方法 而这几个方法进入都是显示off_xxxx 看不出个所以然
先hooksub_24A0
通过上面的步骤看这个方法能不能完整运行
然后hooksub_2488
同样的操作
所以问题就是在sub_2488
里面了
但是sub_2488
里面看不出是什么逻辑
回到上层 通过逻辑可知sub_2488
传入包名 返回的结果给到result
而result作为check_package_name
的结果返回到上层
在check_md5
也没进行其余的操作 那是不是可以nop掉sub_2488
也能保证代码正常运行呢?
答案是可以的
public void patch_2488() { try (Keystone keystone = new Keystone(KeystoneArchitecture.Arm, KeystoneMode.ArmThumb)){ KeystoneEncoded assemble = keystone.assemble("nop;nop;"); byte[] machineCode = assemble.getMachineCode(); emulator.getMemory().pointer(module.base+0x4D24).write(0,machineCode,0,machineCode.length); }catch (Exception e){ e.printStackTrace(); } }
成功出结果
有了这个就可以为所欲为了
0x4 so分析
进到laesEncryptByteArr
看到主要流程在sub_8E74
里面
进入sub_8E74
里面后 看到好多个加密方法
hook一下off_12020
看是走了哪个分支
所以是走到了Bangcle_LAES_cbc_encrypt
这个方法
从字面上了解很明显告诉你这是一个AES CBC
最终走到了Bangcle_WB_LAES_encrypt
加密算法位置就在这
进入Bangcle_WB_LAES_encrypt
映入眼帘的是一堆表 和平常见到的AES又不大一样
根据方法名中的WB(White Box)
和方法里面的一堆查表操作 可以断定这是一个白盒AES 他的目的就是不让你轻易的拿到KEY 从而提高安全性
面对白盒 不要慌 有一部分白盒可以通过DFA攻击获取KEY 但是这个白盒盲猜可能存在魔改 所以并没有尝试DFA 留个坑下次再尝试吧
所以我就直接翻译调用 整体翻译下来也没有太难的点 熟悉AES流程的朋友估计都能观察出大概
感谢各位大佬观看
感谢大佬们的文章分享
如有错误 还请海涵
共同进步 带带弟弟
[完]