Android逆向之旅—最右App的签名算法解析(ARM指令学习恶心篇)

Android技术篇 尼古拉斯.赵四 5343℃

一、前言

今天开始我们后续会开展三篇左右的arm指令学习,因为之前一直都有同学和我说有没有详细的arm指令分析,这个之前的确一直没有好的样本,有的人可能说可以用自己写的C代码然后反编译so来学习,那样因为都知道了原始代码所以解析来就没啥难度,这一次正好用最右这个app的签名算法作为样本学习,为什么用它的呢?因为之前有同学找我分析了一下,分析过程中觉得是个学习指令的好样本就分享给大家,因为他的签名算法稍微有点复杂,所以就分为三篇来介绍,希望通过这一系列的文章之后大家能够了解到arm指令的常规语法,能够简单的分析so代码逻辑。

 

二、逆向分析

接下来我们首先看这个应用的签名算法调用的so和方法,这个后续会提供样本,我们用Jadx打开应用找到他的native方法:

然后找到了so文件之后,用IDA直接打开,找到核心的加密函数sub_5070,这个后面文章会详细介绍如何找到这个函数的,因为本文的目的是为了解析arm指令集的知识,我们查看这个函数的伪代码:

通过分析,第一个参数是加密内容,第二个参数是长度,第三个参数是加密之后的字符串:

我们本文就要把这段代码解析出来,看着其实也不复杂,但是这个加密算法后续还有好几个这样的循环操作,都是字节的位操作,首先不着急,我们先把初始化的代码看一下:

这里有一段初始化代码,不过我们通过简单分析之后发现其实没那么难,这一段可以直接阅读以下,这里会判断当前字符串的信息是否大于64,如果小于64就把后面的数据补0,这里可以看到是分组进行数据操作,一组数据是64个字节,会把加密数据用分组的形式进行操作。

 

三、Hook加密函数

我们先用Frida去hook这个函数,把加密的信息打印出来然后在分析arm指令,最后用代码实现这个算法来看看结果是否正确:

看到这里把参数和结果都打印出来了,看到我们在后续的分析过程中会动态调试就用这个原始加密信息,然后看看hook代码:

这里看到一个小技巧:我们在之前的Frdia框架学习中知道如何hook未导出的函数,都是通过查看maps文件得到so地址,然后加上需要hook的函数地址就是这个函数的绝对地址了,但是这样每次都要查看maps文件太麻烦了,所以这里可以借助已经导出的函数绝对地址减去相对地址就是基地址,然后在加上需要hook的未导出的函数相对地址就是这个函数的绝对地址了:

这里看到JNI_OnLoad是一个导出函数,然后减去他的相对地址就是so在内存中的基地址了,最后加上我们需要hook的函数地址即可。不了解Frida框架的同学可以看这篇文章:Android中的Hook家族Frida框架用法解析

四、动态调试

有了这个原始加密信息,接下来我们就开始动态调试来解读那段arm指令吧,我们还是按照以前的套路,把应用的so拷贝到自己的工程中,然后把native的类原封不动的拷贝过来: