我终于把这块硬骨头啃下来了!
说实话,写这篇文章之前我犹豫了很久,为啥?因为百度加固这玩意儿,真的是个冷门到不能再冷门的领域了,你去搜一圈,翻来覆去就那么几篇老掉牙的帖子,还都是浅尝辄止的那种,看得人心里直冒火,但没办法啊,项目上遇到了,硬着头皮也得上,折腾了差不多两个礼拜,踩了无数坑,今天终于算是摸出点门道了,赶紧趁热乎劲儿把这篇文章写出来,算是给后来人省点时间吧。

先说说我为啥要搞这个吧,前段时间接了个逆向的单子,拿到APK一分析,好家伙,百度加固,当时心里就“咯噔”一下——这玩意儿资料太少了,跟360加固、腾讯乐固比起来,网上的教程简直是凤毛麟角,论坛里问了一圈,要么没人回,要么就是“脱壳机一把梭”这种废话,拜托,我要能一把梭我还用问你?
行吧,自己动手丰衣足食。
第一步:认清百度加固的“脾气”
百度加固跟其他几家不太一样,它有个特点——壳的入口非常隐蔽,你反编译之后看AndroidManifest.xml,application节点被替换成了一个奇怪的类名,而且这个类名还做了混淆,我第一次看的时候直接懵了,这啥玩意儿?
后来慢慢摸索出来,百度加固的核心逻辑其实就两块:一个是DEX文件的整体加密,另一个是运行时动态解密加载,说白了,你静态分析根本看不到真正的代码,必须得让它跑起来,在内存里把DEX dump出来。
这里插一句啊,网上有些教程说直接搜attachBaseContext就能找到入口,我只能说——太天真了,百度加固早就把这块儿改得面目全非了,你得结合ClassLoader的加载流程去追,才能找到那个真正的解密点。
第二步:动态调试的“骚操作”
说到动态调试,这才是百度加固高级教程里最核心的部分,我试过用Xposed,试过用Frida,最后发现还是Frida配合自定义脚本最靠谱。
具体咋搞呢?简单说就是在DexClassLoader的构造函数上下断点,然后等它把解密后的DEX文件加载进去之后,直接hook open或者read系统调用,把内存里的DEX数据抠出来,听起来简单对吧?但实际操作的时候你会发现——百度加固加了反调试,而且还不止一层。
我印象特别深,有一次刚attach上去,进程直接就崩了,后来查了半天才发现,它在/proc/self/status里检测TracerPid,解决办法也有,用Frida的Interceptor把那个检测函数替换掉就行,但问题是,你得先找到那个函数在哪儿……这就又回到了静态分析的老路上。
第三步:脱壳之后的“善后工作”
好不容易把DEX dump出来了,你以为就完事儿了?太年轻了,百度加固还会对DEX文件头做手脚,你直接扔进jadx里面,大概率会报错说“无法解析”,这时候你得手动修复DEX的magic number和checksum,具体操作我就不展开说了,网上有工具,但工具不一定好用,有时候还得自己写脚本。
另外还有一点,百度加固会抽离部分方法的代码,也就是所谓的“抽代码”,你dump出来的DEX里,有些方法体是空的,真正的指令在运行时才填充进去,这种情况就比较麻烦了,得结合动态执行时的寄存器状态去还原,说实话,这块我到现在也没完全搞定,只能针对具体的方法一个个手动修复。
最后唠几句心里话
写这篇百度加固高级教程,不是说我有多厉害,恰恰相反,是因为我太菜了,踩的坑太多了,才想着把经验记录下来,这玩意儿真的太冷门了,冷门到你遇到问题的时候,连个问的人都找不到,论坛上那些大佬要么忙着赚钱,要么早就转行了,剩下的都是一群跟我一样的苦逼逆向狗,大眼瞪小眼。
所以啊,如果你也在搞百度加固,别灰心,慢慢来,记住几个关键点:动态调试是核心,反调试要绕过,DEX修复要耐心,实在搞不定的时候,就去翻翻老外的帖子,虽然他们搞百度加固的也不多,但思路是相通的。
好了,今天就先唠到这儿吧,我得去继续修那个抽代码的问题了,头大……有啥进展我再回来更新,对了,如果你有啥好思路,欢迎在评论区交流啊,咱们一起把这冷门玩意儿给啃透了!
本文为个人经验分享,仅供技术交流学习,请勿用于非法用途。