快捷搜索:  网络  后门  CVE  渗透  木马  扫描  黑客  as

借你一双慧眼,鸟瞰二进制全国的隐秘

*

本文先容了一款用以抬举逆向效劳的,可在真机上查看二进制代码运行逻辑信息的小工具。

由于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.PNG

图1

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

2.png图2

从图2可以看到DVM加载so文件(libjiagu104569824.so)后起首调用JNI_OnLoad函数。注意看JNI_OnLoad退出时左边的行号,说明在全部初始化阶段发生了近十万次函数调用。而其中又多为8534,83f0,8044这几个函数,见图3。种种反动态调试检测以及核心初始化操作都被疏散于这几个函数调用之间,见图4。图中显示其正在检测TracerPid,反动态调试的例行操作。

3.png图3

4.PNG图4

这么支配的目的自然是为了增添动态调试的难度。一键运行易掉坑,单步执行又费时费力。云云复杂冗杂的调用逻辑估计不是靠人力写就。否则,这位程序员的经历够写上N篇“凌晨三点……”的鸡汤文。编译器Obfuscator-LLVM的控制流平整化功能应该可以杀青此结果。

当部分检测通过后,最先解压并加载主so,然后调用其JNI_OnLoad函数,见图5。工具支持多so文件,包括显式以及隐式。由于壳so以及主so文件里的libname名称往往一致,为了区别,主so重命名为InnerLib。

5.PNG图5

图5说明二进制代码正在通过JNI操纵Java全国,并动态注册几个新的JNI函数,为两个“全国”搭建新的桥梁。以后,企业黑客,创建入口函数相同的两个线程,见图6。从图中可知,两个线程操作的参数各异,实际上对应着待解密两个dex文件,不同地址不同大小。

6.PNG图6

JNI_OnLoad执行完毕,就由Java代码提议调用刚才注册的动态JNI接口,见图7。一样是实现一些必要的初始化工作。

7.png图7

所有预备工作就绪,执行权交还给原来的营业代码。由于Dalvik指令已被替代,所以仍需由C代码来诠释,并通过JNI方式执行,见图8。

8.png图8

图9是应用自身创建的线程,由libsmsdk.so文件负责处理一些“清场”措施,例如检查是否ROOT,是否存在两大支流hook框架——Xposed以及Cydia Substrate,提取包括cache在内的硬件、软件及手机周围环境等大批数据。由于太懒,没有过滤这些小我私人数据,所以暂时没法提供这些运行信息文件的下载。

9.png图9

从这也能够看出,安卓体系对隐衷数据的维护存在架构上的缺点。即使其权限治理日趋细化,实际上照样防正人不防小人,很多数据无需权限也能够通过native代码获取。这类要领目前已成惯例,不论正轨商业应用照样恶意软件,都喜好绕过安卓体系,直接与底层操作体系对话。

把大批安全相干操作置于二进制全国,的确抬举了应用的安全性,但同时也使得恶意软件的检测变得更为难题。从手艺角度看,除非深度改造操作体系,否则目前根本没法在客户端(用户侧)自动检测到新的恶意样本。

要是工具加上预处理(去冗余信息等)和图形化等功能,信赖可以在短时间内纵览程序运行逻辑全局,为后续逆向操作指引方向。

此工具的优点也是瑕玷,只能像侦查机在空中侦查。若要“袭击”一些症结堡垒——破解译码逻辑、加解密过程、协定等等,还得靠重装部队(动态调试)。二者自然可以配合步履,在症结点处停息运行,加入动态调试。这统统,都是为了抬举逆向效劳,争取时间。

当然,也能够用作他途,比如与“蜜罐”配合,自动网络、检测、阐发各类恶意应用。

PS:

请允许在此打个小广告,近期打算换个环境,若有合适职位提供,请与我联系,感谢!

*

您可能还会对下面的文章感兴趣: