应用程序文件Android安全分析挑战:运行时篡改Dalvik字节码
发一下牢骚和主题无关:
文章接链:http://blog.csdn.net/jiazhijun/article/details/8833710
作者:Jack_Jia 邮箱: 309zhijun@163.com
动移互联网已是一种势趋,仅2012年就有45亿应用程序载下量。伴随着动移互联网的火爆,浩繁攻击者也被吸引到这个台平,动移台平意恶软件呈现爆炸式长增态势。与PC台平不同的是,PC台平有量大的反病毒包和意恶软件析分工具,而新兴的动移互联网却乏缺大强的析分工具和技巧。这些工具和技巧将是坚持动移互联网阔别意恶软件和意恶应用程序的键关。它们一般来自于学术界和全安界的研讨员人,但是它们都有必定的陷缺,不并合适有所的情况,入加全安社区可以帮助我们习学和开展android应用的析分方法。
一、分析
首先分析一下动移应用程序的析分方法和景背。我们可以采取很多工具来对应用程序行进析分,Android应用程序的析分一般都是基于APK文件,APK文件代表了一个应用程序。
它存储了以下内容:
1、程序逻辑:dex字节码和so地本库。
2、元据数信息:AndroidManifest.xml文件。
3、源资文件:图像或其他类型据数。
析分工具一般采取以下两种应用析分方法:
1、静态析分:该方法搜集有关应用程序的信息,但程序代码不行执。
2、态动析分:该方法行执应用程序,同时搜集应用运行为行。
这两种析分技巧都各有利弊,在Android逆向析分范畴,很多工具都是基于静态析分技巧,也有于用态动析分的沙箱系统,但受限于态动析分系统的交互灵活性,析分师常常在那些分部要需态动析分上没有充足的控制力。在逆向工程中程过,析分员人一旦肯定了感兴趣的应用程序分部,它们更侧重于用使静态析分工具。问题是如何找到那些分部呢?静态析分技巧的另一个要重陷缺是不知道什么被真正行执和程序上下文在某特定点的行执否是有效。当我们假设应用程序代码在运行中程过不会转变时,析分任务将是非常易容的,我们可以通过析分apk文件来识别程序代码逻辑,混杂的应用程序会给析分员人带来必定的战挑。随着运行时改动Dalvik字节码的解讲,我们将暴露这些基于代码流析分的工具的制限和问题。
我们将在接下来的分部描述一下应用程序的基本组成分部,并指出要重的运行时组件。这将使我们更易容白明当运行crackme时发生了什么事情。后之,我们将报告于用欺骗静态析分工具所采取的要重技巧。最后我们会进入crackme战挑的细节。
二、应用程序行执的上下文
应用程序的生命周期开始于zygote程进的fork方法,因为它已先预加载了Android框架,所以应用程序不必再花时间加载这些基础类,同时这也可以有效低降体整的内存开销。在新的程进低降限权后之,它加载了apk文件中的classes.dex文件,该文件包含了可被Dalvik虚拟机(DVM)释解行执的Dalvik字节码,代表了应用程序逻辑。此外,应用程序还带有可以在运行时态动加载的Native库。因为Dalvik虚拟机和Native库运行在统一程进中,因此它们拥有同相的限权。一个型典的(收缩的)应用程序的内存布局如图1所示。
我们可以看到,Android框架和同享库及dex文件一样被映射到我们的程进。我们的dex文件字节码被映射为只读。
三、改动技巧
回到静态析分工具的话题,如果Dalvik字节码在运行时不能转变的话,静态析分工具将能很好的任务。因为我们可以直接从APK文件中提取的出和运行时相匹配的字节码。你可能会说这类假设是建立的,因为dex文件映射为只读,所以Dalvik指令集是不够能修改的字节码本身的。无限的Dalvik指令集使我们不够能改动程序字节码,但我们可以用利捆绑在APK文件中的地本库。地本代码和DVM运行在同相的较低水平,如图2:
图2 地本代码和DVM在统一级别的操纵
地本代码是够能意任操纵自己程进上下文内存的,因此我们可以通过地本代码覆盖已加载Dalvik字节码。但是classes.dex被映射为只读。这意味着,如果我们修改该段内存,内核将会杀掉我们的程进,因此在际实改动我们的应用程序的字节码之前,我们必须从新映射该段内存为可写。后之,我们就够能写我们的新字节码到我们的应用程序。如果程序调用我们改动过的方法,那么将行执新的字节码。没有进一步修改应用程序或DVM的要必。通过这类方法,我们现发“字节码在运行时不能修改”的假设也不是绝对的。只存眷classes.dex文件的静态析分工具没有考虑到这类情况,这样的工具就必须改良以应答这类情况。可以用使静态和态动析分的合组来服克这类制限,但这样的杂复的析分系统是不常见的。
三、示例-Crackme
为了明说我们后面所论讨的一些问题,我们决议建创一个案例研讨“challenge”的应用程序“crackme”,它用使意恶软件用使的混杂技巧行进了处置。您可以用使任何析分技巧和工具,并弄清楚它是如何任务的。找到确准的码密,输入到上面的文本框中。点击按钮,看查否是得到了确准的案答。这将示显按钮上面的文字。
您可以在这里载下crackme的apk文件的副本:https://github.com/blueboxsecurity/DalvikBytecodeTampering/raw/master/delta.apk
止停浏览,如果你算打接受战挑。上面是战挑的案答 -----
首先我们开始析分Action类,这是我们的应用程序的Activity的进口,按钮会发触verify()方法。在这里,我们第一次取获TextField中的输入的文本,并把它转换成一个String。这个String对象不并是java.lang.String类的一个实例而是我们自己的现实。在构造函数中,我们用使第二种方法转变字符串。结果将被储存在私有的域区,和Action类的硬编码在一块。如果码密同相,将被于用示显在屏幕上的消息的密加。
但是String类内所用使的转变文本方法的方法,或者更确准地说,这类方法的字节码,将远永不会被行执。当应用程序启动后,在Action的静态类的构造函数中,这个方法的字节码已被替换掉了。在这里,我们加载地本库'libnet.so'和行执READMEM()函数。在这个库中,我们取获一个指针从堆栈到我们的映射的dex文件,并实验找到文件的头开。这可以很易容地通过正向搜索内存页,直到我们现发dex文件的magic byte。在现我们可以从dex文件的头开析解头文件。当我们析解dex文件时,我们可以找到的我们要改动方法的址地。但正如后面提到的,我们首先要从新映射内存为可写。这可以用使mprotect()函数现实。后之,我们就够能覆盖本来的字节码,并通过从本机代码到类的初始化的返返来成完。类初始化已结束,Activity在Android设备上弹出。在现,当我们按下按钮时,我们行执的是新的字节码,而不是本来dex的字节码。
文章结束给大家分享下程序员的一些笑话语录:
面试官:熟悉哪种语言
应聘者:JAVA
面试官:知道什么叫类么
应聘者:我这人实在,工作努力,不知道什么叫累
面试官:知道什么是包?
应聘者:我这人实在 平常不带包 也不用公司准备了
面试官:知道什么是接口吗?
应聘者:我这个人工作认真。从来不找借口偷懒
面试官:知道什么是继承么
应聘者:我是孤儿没什么可以继承的
面试官:知道什么叫对象么?
应聘者:知道,不过我工作努力,上进心强,暂时还没有打算找对象。
面试官:知道多态么?
应聘者:知道,我很保守的。我认为让心爱的女人为了自已一时的快乐去堕胎是不道德的行为!请问这和C#有什么关系??