天天看点

对脱壳脚本的一些改进--识别出目标DEX

    通常对于加壳的程序,第一步的操作通常是脱壳,而现在脱壳一般都选择利用<code>frida</code>来进行<code>hook</code>进行脱壳,不谈其他脱壳方式,利用<code>frida</code>脱壳原理大致分为两种:

    1、找到DexFile对象(art虚拟机下是DexFile对象,dalvik虚拟机下是DexFile结构体),获取到DEX文件的起始地址和大小,然后<code>dump</code>下来。常见能够找到<code>DexFile对象</code>的函数有<code>LoadMethod</code>、<code>ResolveMethod</code>函数等,能直接获取到<code>DEX起始地址和大小</code>的常见函数有<code>openMemory</code>、<code>dexparse</code>、<code>dexFileParse</code>、<code>dvmDexFileOpenPartial</code>等函数。<code>frida_unpack</code>便是其中的代表作。

    2、利用frida的搜索内存,通过匹配<code>DEX</code>文件的特征,例如<code>DEX</code>文件的<code>文件头</code>中的<code>magic</code>---<code>dex.035</code>这个特征。<code>frida-Dexdump</code>便是这种脱壳方法的代表作。

    然而不管是上述哪一种原理,在我这个有点<code>强迫症</code>的看来,都有一点小缺陷,这两种方法从原理上决定了经过某个函数的<code>DEX</code>(或者存在于内存中的<code>DEX</code>)都会被<code>dump</code>下来,所以出现了<code>dump</code>下来很多个<code>DEX文件</code>,但是只有其中一个或者几个是我们的<code>目标DEX</code>,为了寻找到<code>目标DEX</code>,只有全部反编译出后来能知道,这就比较浪费时间和精力了,对此,本人对脱壳脚本做了一些改进,通过对<code>dump</code>下来的<code>DEX</code>进行解析,从而识别出那个是我们的<code>目标DEX</code>!!!

    PS:通过类名识别是本人发现识别率最准确、实现代价最小的方法,所以本篇重点主要在这,后面的其他识别方法在某些特殊情况下更好用!!!

    <code>DEX</code>文件的格式可以大致分为<code>文件头</code>、<code>索引区</code>、<code>数据区</code>,<code>文件头</code>这个区域无法找到一个<code>DEX</code>文件的一个<code>唯一特征</code>(ps:<code>sha-1</code>和<code>校验码</code>这两个能作为一个<code>DEX文件</code>唯一特征的前提是我们已经知道这个<code>dex</code>文件所有字节了,所以放在这里并不成立),<code>索引区</code>包括了很多数据的索引,其中便包括<code>字符串</code>的索引,通过这我们可以解析出整个<code>DEX</code>文件使用到的字符串。而我们已知的<code>DEX</code>文件的一些信息便包括<code>包名</code>。

    通过解析一个<code>DEX</code>文件,我们可以发现在<code>DEX</code>中一个类被表示出如下形式--<code>L包名/类名;</code>,例如<code>Lcom/example/test/ManActivity;</code>这种形式,例如下面为使用脚本解析<code>DEX</code>的字符串,获取到的类名的截图:

对脱壳脚本的一些改进--识别出目标DEX

    包名是唯一的,所以我们只需要构造<code>/com/example/test</code>这种形式的特征,便可以很轻易的锁定到<code>目标DEX</code>,但是,在<code>壳程序</code>中,也可能含有这种类型的字符串,我们的特征便不再是唯一的,这个时候,我们便需要一个新的唯一特征。

    在一个APP中,我们通常所写的类不止一个,而是很多个,那么便含有很多个上述所说的<code>特征</code>;而写过加壳程序都应该知道,我们在加壳程序中,最多也就拉起那么一个或几个类。那么,通过这种数量上的差异同样也可以作为唯一特征,以下是<code>脱壳改进脚本脚本</code>运行截图:

对脱壳脚本的一些改进--识别出目标DEX

    1、其他字符串,通过将app安装运行手动观察到的,但是这种方式有点碰运气,只有直接写入到<code>java</code>源码中的才能作为特征,写入到<code>strings.xml</code>便不得行。如下截图(ps:为直接写入到java中的,可以在字符串池中解析出来的),解析字符串池:

对脱壳脚本的一些改进--识别出目标DEX

    2、布局xml文件名、控件名(ps:这种可行性太低,在这里筹字数的,基本不能作为特征)

    3、布局、控件资源ID,这些16进制搜索整个DEX文件也可以作为特征,但是有很其他DEX文件装车的可能。

    4、方法原型,例如一个方法返回值是Double,参数也是Double,那个这个方法原型便是<code>FF</code>,而这个方法原型一定存在于字符串池中,但是也不是很靠谱这个特征,原因如下截图所示(而且还需要知道一个方法才行):

对脱壳脚本的一些改进--识别出目标DEX

    5、对DEX做更深入解析,解析出更多特征,而不仅仅止于解析出字符串池,感兴趣的研究一下,但第一个依靠类名便够用了。

    github地址:https://github.com/windy-purple/dumpshell

继续阅读