armariris字符串加密实现原理

转载自:https://www.leadroyal.cn/?p=968

https://www.anquanke.com/post/id/181051

armariris是上交Gossip的在2016年公开的,在ollvm上添加了额外一个Pass,从而实现字符串加密,由于其特征简单,破解也简单,于是使用unicorn破解掉它的字符串加密。

 

本文的涉及到2个文件,libcms.so请从4.0.0版本的抖音app里解压出来,decrypt_armariris.py 位于该gist下:https://gist.github.com/LeadroyaL/9b0bc6f6a908db1adfc48d85ee43451d

一、armariris字符串加密实现原理

我曾经移植过它,代码位于https://github.com/LeadroyaL/llvm-pass-tutorial/blob/dev/Armariris/StringObfuscation.cpp ,逻辑挺简单的,对于所有的常量字符串,先创建一份可读写的、类型相同、大小相同的全局变量,将原先的字符串xor随机数,存放到这块新的全局变量里。

再将对应的解密逻辑存放到一个函数里,将该函数放到.init_array中,从而在library被第一次加载时,从全局区读数据,再写入全局区,对字符串进行解密,不影响执行过程中对常量字符串的读取。

 

二、主要思路。很简单,因为解密逻辑在.init_array里,全都是exported=true、而且符号名是.datadiv开头,直接把它执行一遍。此时内存中的rwdata就是解密后的,覆盖掉原先的rwdata,再删掉解密函数,即patch完成。

 

三、详细思路

1、根据符号表,找到.datadiv开头的函数

2、加载so文件到unicorn中,依次执行各个字符串解密函数

3、Patch掉rwdata的数据

4、Patch掉字符串解密函数

这个地方是有细节的,解密函数的引用在init_array,会影响到init_arraysize等,需要主动恢复,而且经过观测,init_array的内容会受到重定位的影响,需要把对应重定位项也移除掉。有以下三种方案防止在.init_array里把修好的字符串破坏掉

init_array里的重定位只涉及R_ARM_ABS32,在solinker加载时,重定位会将对应位置写为base+abs32的内容,如果乱Patch会崩溃,因此有两个方案:

方案一:剔除掉重定位项,改为无用的值;剔除掉init_array里的解密函数,将init_array变紧凑;

方案二:在so里寻找bx-lrgadget,即空函数,修改重定位项,将abs32指向它;

还有一个投机取巧的方案:

方案三:将所有的datadiv改为BX LR;

最终采用方案三的方案,因为这样做代价最小。。。

 

 

四、验证成果

懒得手动使用armariris了,就使用了和上篇一样的样本,libcms.so借鉴了armariris的字符串加密,从原来的for循环加xor,改为了自己定义的运算,但方式是一模一样的。运行脚本后,将文件丢到手机里覆盖原先的文件,发现仍然可以正常工作,表明patch成功!

 

posted @ 2020-12-20 21:51  huhuf6  阅读(488)  评论(0编辑  收藏  举报