前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >网秦安全盾 原理分析

网秦安全盾 原理分析

作者头像
我是小三
发布2018-08-08 17:45:17
9700
发布2018-08-08 17:45:17
举报
文章被收录于专栏:逆向与安全逆向与安全

环境: 手机: 中兴 u887 系统 android2.3.5 调试器: IDA pro 6.5

一:加固前后对比 加固前 classes.dex 大小如下:

加固后 classes.dex 大小如下:

那原来的 classes.dex 去那儿了呢?我们再来对比下资源目录下都多了些什么? 加固前的:

加固后的: 

Lib 目录:

加固后:

比较发现多了些文件,具体这些文件有什么用请看下面分析。

二:java 层概述 1.通过反编译看,从 AndroidManifest.xml 文件中的 application 项可以看出壳的入口为:

2.简单分析 com.nqshield.NqApplication 类都做了些什么? .不能反编译成 java 代码,直接看 smali 代码吧。 在 NqApplication 类 method protected attachBaseContext(Landroid/content/Context;)V 中都分别调用了这些函数: 3..invoke-static{p0},Lcom/nqshield/Common;->loadXShellLib(Landroid/content/Cont ext)V 从名字可以看出是加载 so 库,并注册 JNI 函数。 通过分析 JNI 方法注册到 Dalvik 虚拟机的过程,可以得到 java 层 native 函数与 so 层函数 对应的关系为: native nq10 -> b9df1ce797fd03603fd7137afff2957 native nq11 -> eb5993d402df42eac47e82555b7ae31 native nq12 -> fa3f3a501e8754e88bed48c128ef90 native nq13 -> abc020d3ee6fbc05ab1ed6b4da7252d native nq14 -> e300588cc034bcbaa7d61 (*如有不清楚如何分析这个过程的可以参考学习罗升阳 的文章) 4..invoke-static{p0},Lcom/nqshield/Common;->CopyBinaryFile(Landroid/content/Con text;)V 该函数是将 assets 文件夹中的 DexToLoad.apk 与 nqdata 拷贝到/data/data+包名/.cache 目录中,然后调用 nq10 函数,(该函数会在下面分析)。 5..invoke-static{p0},Lcom/nqshield/jniExport;->getDexClassLoader(Landroid/conte nt/Context;)Ljava/lang/ClassLoader; 该函数通过调用 DEXClassLoader 完成对加密的/data/data+包名/.cache/DexToLoad.apk 的 动态加载,内存中解密 DexToLoad.apk 并组合 odex, 完成动态加载。 (详细过程看 so 层分 析) 。 类似下面的样子:

6.invoke-virtual{v0,p0,v1,v2},Lcom/nqshield/jniExport;->nq12(Landroid/content/C ontext;Ljava/lang/ClassLoader;I)V 传入 getDexClassLoader 返回值。 7.invoke-virtual{v0,v1,v2},Lcom/nqshield/jniExport;->nq13(Ljava/lang/String;I)V so 层分析 8.最后在.method public onCreate()V 中调用 invoke-virtual {v0, v1, v2}, Lcom/nqshield/jniExport;->nq14(Ljava/lang/String;I)V 三:so 层分析: 1.通过 readelf -S libnqshield.so 查看 so 信息,发现 INIT_ARRAY 不为空,

用 IDA 打开 so,G 到 INIT_ARRAY 中的地址去看看.

对应 so 函数名被混淆了,动态分析发现这些函数都是解密字符串用的,根据传进的数字解 密相应的字符。

下面是传入要解密的字符串。

110 代表解密后的字符为: nq10 115 代表解密后的字符为: (Ljava/lang/String;Ljava/lang/String;I)V 111 代表解密后的字符为:nq11 等等...以此类推 2.JNI_OnLoad 中都做了些什么? 第一个函数 fork 一个子进程,并创建一个线程,线程函数如下所示

inotify 是一种文件系统的变化通知机制,如文件增加、删除等事件可以立刻让用户态得知, int wd = inotify_add_watch (fd, path, mask); 用于添加一个 watch fd 是 inotify_init() 返回的文件描述符, path 是被监视的目标的路径名(即文件名或目 录名), mask 是事件掩码, 在头文件 linux/inotify.h 中定义了每一位代表的事件。可以 使用同样的方式来修改事件掩码,即改变希望被通知的 inotify 事件。Wd 是 watch 描述 符。 在 arch-arm\usr\include\linux\ inotify.h 头文件中定如下: #define IN_OPEN 0x00000020 ,根据线程函数可以看出它是监视/proc/pid/maps 的打开事件. (*不明白的可以点这里 http://blog.csdn.net/myarrow/article/details/7096460)

我猜测这个线程的功能可能是做反注入用的。 2.解密字符串 传入数字 79 代表解密后的字符为: com/nqshield/jniExport 3.注册 JNI 函数 对应关系 native nq10 -> b9df1ce797fd03603fd7137afff2957 native nq11 -> eb5993d402df42eac47e82555b7ae31 native nq12 -> fa3f3a501e8754e88bed48c128ef90 native nq13 -> abc020d3ee6fbc05ab1ed6b4da7252d native nq14 -> e300588cc034bcbaa7d61 4.下面对这几个函数进行分析 nq10 函数在 java 层 CopyBinaryFile 函数中被调用到,我们在 so 中对 b9df1ce797fd03603fd7137afff2957 函数下断点,动态分析看它都做了些什么? 函数里面调用了 result = initEnv(a5, "DexToLoad.dex", "DexToLoad.apk", &s); 进入该函数分析,该函数对 libdvm.so 与 libnativehelper.so 中的操作文件等一些函数进 行 hook 如下图:

我 们 分 别 对 这 几 个 hook 函数 (myopen,myread 等 ) 下 好 断 点 , 当 java 层 调 用 getDexClassLoader 函数时会走到这些 hook 函数中,b9df1ce797fd03603fd7137afff2957 函数就分析完成了。 5.java 层的 CopyBinaryFile 函数执行完后就要执行 getDexClassLoader 函数了,该函数是 调用 DexClassesLoader 动态加载 DexToLoad.apk,继续动态走,断在 myopenh 函数中,该函数 会判断是不是打开 DexToLoad.apk 文件,如果是就会创建一个 DexToLoad.apk.zip 文件。 接着来到 myopen 函数中,判断是否打开 DexToLoad.apk,如果是会调用函数 access 判断 /data/data/yiqi.bazi/.cache/DexToLoad.apk 是否存在,存在就打开它并将其读取到指定 内存,然后解密,如下图:

6.组合生成 ODEX: 下会根据 ODEX 结构图进行组合:

(*该图来自 “ Android 软件安全与逆向分析” 一书,如有对该结构不明白的地方可以 去阅读这本书,书里有详细讲解)。 首先使用 zlib 函数 inflateInit2_与 inflate 对上面解密出来的 DexToLoad.apk 数据从 classes.dex 标志后进行解压得到 dex 数据, 在 inflateEnd 处下断 F9 执行, 如果要脱壳的 话,这个时候是最佳的 dump 时机,可得到完整的 Dex 数据。(组合完后会对 dex 做些手脚)接 下来会按照上图 odex 结构图进行组合, 在解压出来的 dex 前写入 ODEX 文件头如下图所示:

打开/data/dalvik-cache/mnt@asec@yiqi.bazi-1@pkg.apk@classes.dex 读取依赖库到 dex 后面,如下图:

打开/data/data/yiqi.bazi/.cache/nqdata 读取辅助数据到依赖库后面,如下图:

组合完后就是 vm 加载过程了。 7. 接着 java 层调用 nq12 nq13 nq14 函数 反射调用 LoadedApk.mApplication, LoadedApk.mClassLoader, ActivityThread.mInitialApplication, ActivityThread.mAllApplications 等值,将其重新 指向目标 Application 和 ClassLoader。确保系统 稍后构造组件时能正确的加载到目标类。 三: 到此分析完成,最后,将控制权给目标 Application。

完。

样本及文档下载

http://yunpan.cn/cA3U6hctfwfj3 (提取码:9b1e)

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2014-11-18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档