欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

借你一双慧眼,鸟瞰二进制世界的秘密

来源:本站整理 作者:androiddongjian 时间:2018-06-12 TAG: 我要投稿

本文介绍了一款用以提升逆向效率的,可在真机上查看二进制代码运行逻辑信息的小工具。

由于Java世界的特性所致,安卓应用在代码自身保护方面一直乏善可陈。所谓的Java混淆等技术,也不过是一层簿簿的面纱,极易被撕开,毫无秘密可言。所以,当前也没有谁敢拿“面纱”作为唯一保护措施。
既然Java世界无险可守,大家只好纷纷往底层退守,进入所谓的“二进制世界”。在二进制世界里,使用机器码(machinecode)与底层硬件和操作系统直接沟通,可用的技术和技巧变得相当丰富,保护力度也远超Java世界。
与其它系统不大一样,安卓系统的功能多以Java语言接口对外提供。虽然也提供NDK模式,允许使用JNI方式与安卓系统交互,然而毕竟没有使用Java语言那么直接方便。所以很多应用的数字财产——数据和运行逻辑,依旧保留在Java世界。因而,为安全起见,有必要把这些“财产”迁移至二进制世界,各种安卓应用加密或加固方案借此机会如雨后春笋般诞生。
在加固技术上,从整体dex文件到class或method,再到Dalvik指令,加密粒度不断变小,安全性也得以持续提升。把Dalvik指令集等价替换成为私有指令集,运行时解释私有指令,并通过JNI方式执行,这种技术在目前普遍流行。商业上多称之为VMP(虚拟机保护),不过我个人倒觉得若按技术分类,归为模拟器(Emulator)更为合适。

“源码面前,了无秘密”。当然,在逆向工程师眼里,即使只有目标代码,也能探个究竟。所谓攻防一体,简单介绍常见的逆向思路与对抗措施。
首先就是静态分析。使用反汇编工具把目标代码转换为汇编代码,甚至变成可读性更强的C代码。因此,合格的加固方案必须拥有反反汇编特性。清除各种符号(Symbol)、加密字符串等是例行操作。去除ELF文件的Section Headers是一个常用方法,当然遇上会修复SectionHeaders的人,那就从了吧。还有加入“花指令”也是个不错的方法,只是在专有的反汇编工具面前会真的沦为“花瓶”。故而,加壳是对抗静态分析的杀手锏。
然而,丑媳妇总得见公婆,壳再好,运行时也得卸下,露出核心代码的真容。通过动态调试,逐一审查每条机器指令,再深的秘密也无法藏匿。所以,对抗动态分析也必不可少。
动态调试的技术原理和其运行时暴露的各种特征,是制定反动态调试措施的依据。常见的有获取当前应用是否处于调试连接状态;查看是否存在IDA驻留程序;相应端口号是否被占用;ptrace功能是否启用,或者提前使用ptrace“占位”;设置“哨兵”进程;某段代码运行时长是否异常等等,不一而足。这些措施犹如一个个碉堡,大大延缓了进攻者的前进步伐。
可是,这些“碉堡”迟早要被一个个拔掉。为了进一步迟滞进攻者的推进速度,还可以布下巨大的“八卦阵”——控制流平坦化(ControlFlow Flattening)。这项技术让简单的执行逻辑复杂N倍。把一些核心操作分散置于其中,可以起到相当不错的保护效果,进攻者很容易深陷于一场“人民战争”的汪洋大海之中。
当然,没有攻不破的堡垒,也没有完美的保护。只要能延缓关键代码被暴露的措施,都是好的保护手段。相反,进攻者则希望快速识别和定位关键代码。时间,成了攻防双方所争夺的焦点。那么,有没有比较好的方法可以加速关键代码的定位呢?

显然,获取程序的全面运行信息是快速定位关键代码的基础。运行信息的粒度大小决定了其作用大小。从用户角度看到的程序行为过于粗犷,其作为全面运行信息的一个子集,偶尔能起辅助参考之用。从底层CPU角度可以获取程序的所有运行信息,可惜皆为指令级别,粒度过于细小,不利于人工分析。唯有函数级别的运行信息粒度大小适中,且忠实反映了程序作者的设计意图,是快速了解程序整体运行逻辑的最佳切入点。
提取程序的函数运行信息不是新鲜事。Linux系统上也有不少工具可以获取函数的动态调用关系,例如Systemtap、Ftracer、gprof,还有GCC的instrumentation功能等等。不过,这些工具或者需要内核支持,或者要有源码,的确不大适合只有二进制代码的逆向工程。当然,利用qemu等模拟器提取函数调用关系在技术上不是不可以,只是感觉像在用牛刀杀鸡。再者,如果一些程序存在反模拟器检测,那么必然得不到真实完整的运行信息。
因此,若能在真机上获得二进制代码的函数调用关系信息,将十分有利于对目标应用的进一步分析。于是,本文作者写了一个小工具,来实现此需求。
这个工具的设计思路也很简单:接管目标代码所有函数的序言(prologue)与尾声(epilogue),然后输出相关信息。此工具在某种程度上也可认为是一款轻量级的准虚拟机。

下面,结合实例展示工具的基本功能。
APK样本地址(http://zhushou.360.cn/detail/index/soft_id/3104614#nogo),包名:com.financial360.nicaifu,版本号:2.2.9。静态分析就此略过,反正也得不到更多的有用信息,不如直接让它在真机上跑一遍。
图1展示了工具所捕获的运行信息,不同线程对应不同文件。文件名的格式为:包名_进程ID_线程ID。工具支持多进程多线程。由于Java世界也会创建许多线程,为简单起见,这里只展示有二进制代码(亦即so文件里的native代码)参与的线程信息。

图1
先打开主线程,见图2。每一行数据表示进入(+)或退出(-)某个函数,其中数字表示调用深度,方便后续图形化等处理(作者是个懒人,这个坑十有八九是填不了)。库函数没有区分进入或退出。在同一行内给出了函数的参数(位于函数名后的括号内)和返回结果(位于*符号后面)。除了JNI_OnLoad外,其它native代码函数名的格式统一为:偏移@so文件名。当然,也可以选择显示其实际函数名,前提是没有被去除。

[1] [2]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载