[原创]Ali 阿里聚安全加固的libdemolishdata.so格式分析及代码还原的一种方案
将apk上传到阿里云进行快速加固,下载下来可以发现最新的加固和参考资料(1)中的类似,libdemolishdata.so的位置放在了assets\ali中,不过格式不变。
但很可惜该资料中并没有给出将阿里云抽取到libdemolishdata.so二进制代码还原回dex的方法,修改代价高(伸手党做不成了),所以需要继续分析(本文在参考资料(1)的基础上分析,建议先阅读参考资料(1))。
想着动态调试太麻烦于是直接开始猜,用winhex打开libdemolishdata.so,如图:

可以发现位于0x10(表示由0x10-0x10+3构成的DWORD,下同),0x20,0x30的位置的内容恰好是fixfunc调用的内容。
那么可以推测0xC表示待修复方法个数。
用baksmali输出method(java -jar baksmali.jar list methods dex文件地址),可以发现0x18,0x28,0x38对应着三个被修改为"native"方法的methodIdx。
学习了参考资料(2)后,可以发现0x1c,0x2c,0x3c作为offset指向的内容恰好是DexCode格式,所以关键是修复codeoff。
又尝试上传了一个有multidex的apk,可以猜出libdemolishdata.so其他全部信息的含义(过程省略),如下(所有名称都是我为了方便随便命名的)
文件宏观组成如下
struct libDemolishData{
AliFixFuncInfo aliFixFuncInfos[dexNum];//每个AliFixFuncInfo对应一个dex的修复信息
AliCheckSumInfo aliCheckSumInfo[dexNum];//每个AliCheckSumInfo 对应一个dex的CheckSum
uint dexNum; //dex数量,如:有classes.dex和classes2.dex,则为2;只有classes.dex,则为1
};AliCheckSumInfo的组成比较简单,如下(可能用于检验加固后的内容是否被修改)
struct AliCheckSumInfo{
uint multiDexId;//dex标识,0表示classes.dex,否则表示classes{$multiDexId}.dex,如2表示classes2.dex
uint checksum;//该dex的alder32,与DexHeader.checksum相同
uint hash;//该dexSha1的一部分,与DexHeader.signature的前4字节相同
};AliFixFuncInfo则由三部分组成,如下
struct AliFixFuncInfo{
struct Header{
char magic[4];//魔数,恒为 <ali
uint multiDexId;//dex标识,0表示classes.dex,否则表示classes{$multiDexId}.dex,如2表示classes2.dex
uint dataLen;//这一AliFixFuncInfo的长度,可以借此定位下一个AliFixFuncInfo在哪
uint funcsNum;//需要修复的方法数
} header;
struct FixFunc{
uint id;//方法标志,同fixfunc调用的参数,如class调用 fixfunc(int[]{id1,id2,...}) 时,id1,id2,...就是这个id
uint multiDexId;//dex标识,0表示classes.dex,否则表示classes{$multiDexId}.dex,如2表示classes2.dex(表示似乎冗余了,为0x16对齐?)
uint methodIdx;//待修复方法的methodIdx,methodIdx含义见参考资料(2)
uint codeOffset;//指向待修复方法的真实DexCode信息,注意表示的是真实DexCode信息相对于当前AliFixFuncInfo的偏移,而并不完全相当于相对于文件头的偏移
} fixFuncs[funcsNum];
char realDexCodeInfo[dataLen-sizeof(header)-sizeof(fixFuncs)];
};分析到这里可以说是很开心,以为只要在dex文件中找到codeOff改掉即可,然而codeOff是Uleb128类型的,这是一种变长类型,一旦改掉,需要修复很多偏移信息。
于是想到我们可以修改baksmali读取到的codeOff啊,再smali回去即可。
可以想象(伸手党放心,这部分附件有成品),先增加几个类,用于读取 libdemolishdata.so,在读取dex文件的函数中将 libdemolishdata.so 的内容复制在存储dex内容的byte[]末尾,然后修正读取到的accessFlag(去除native标记【0x100】),修正读取到的codeOff(获取到相对于当前AliFixFuncInfo的偏移后要加上AliFixFuncInfo相对于libdemolishdata.so文件头的偏移和前文中的byte[]中libdemolishdata.so信息的偏移),这样就可以了。
附件中modifiedJava.zip是修改后的java源代码(仅修改的部分,修改前的baksmali程序的java源代码可在github下载,编译采用javac -cp 编译好的.jar;. ***.java,然后将新生成的*.class用压缩软件复制到jar内对应目录即可);
bakdemolish-2.2.1.jar是修改编译后的成品(使用说明:
1.正常dex和修复后dex都用正常baksmali即可,不要用这个。
2.操作命令同正常baksmali,如java -jar bakdemolish-2.2.1.jar d classes.dex。
3.但须注意,将assets\ali(我获得的最新加固后文件)或lib\**\(参考资料(1)中加固后文件,2017.01)下的libdemolishdata.so、bakdemolish-2.2.1.jar、classes.dex文件放到相同文件夹下,并保证命令提示符当前目录也cd到这一目录时才能确保正常工作【其实就是libdemolishdata.so直接是用FileInputStream("libdemolishdata.so")取读的问题,没有测试其他情况】
4.dex文件名不能改【用来获取前文提到的multiDexId,如apk内是classes2.dex,就是classes2.dex】
5.dex可以直接解压获取,也可以用apktool d -s apk文件 获取)
有了这个工具,可以想象如下修复步骤(没有完全测试过)
1.apktool d -s apk文件
2.获得libdemolishdata.so后用bakdemolish-2.2.1.jar获得smali Code
3.适当修复,最简单的是将com\ali\fixHelper.smali中所有方法内容都删除,然后删除fixfunc方法的native属性,补上.locals 0,return-void,如下
.method public static fixfunc([IZ)V .locals 0 return-void .end method
也可以用一些规则匹配删除所有<clinit>中调用fixfunc的代码
注意处理后的文件仍有一些暗桩似乎和a/does/not/Exists*.smali有联系,可能需要处理
4.用smali-*.jar回编译
5.用apktool b <dir>生成新apk,签名
参考资料:
1.Caln ali 加固(17年1月)逆向分析 http://bbs.pediy.com/thread-217235.htm
2.太尼玛菜了 Android Dex文件格式(一) http://www.cnblogs.com/dacainiao/p/6035274.html
Android Dex文件格式(二) http://www.cnblogs.com/dacainiao/p/6036834.html
