一、序言

目前Android市场充斥着大量的盗版软件,开发者的官方应用被“打包党”们恶意篡改。如何使程序代码免受盗版篡改就成了开发者面临的头等大事,今天我们将分析一个不错的解决方案---梆梆加固(http://www.secneo.com/appProtect/)。
通过对App进行加固保护。梆梆可以有效防止移动应用在运营推广过程中被破解、盗版、二次打包、注入、反编译等破坏,保障程序的安全性、稳定性,对移动应用的整体逻辑结构进行保护,保证了移动应用的用户体验。

二、梆梆加固逆向分析过程

首先我们通过对APK加固前后文件结构的比较,来了解梆梆加固对APK文件所做的处理。为了使分析过程足够简单,我新建一个最简单的测试程序,并上传到梆梆加固,整个加固过程大概需要4天的时间才可以完成,这是一个漫长的等待过程。
该测试程序包含了Activity、Service、ContentProvider、BroadcastRecevier四大组件、Application、普通类、Jni调用等7类对象,目的就是全面的了解梆梆的加固效果。

 1、apk加固前后静态文件结构及动态运行时对比分析
(1) 加固前后静态文件结构变化(左为加固前,右为加固后)

加固后apk新增以下文件:

  • assets\meta-data\manifest.mf  //APK文件列表SHA1-Digest
  • assets\meta-data\rsa.pub        //RSA公钥信息
  • assets\meta-data\rsa.sig         //数字签名文件
  • assets\classes.jar                    //已加密原classes.dex文件
  • assets\com.example.hellojni    //ARM平台二进制可执行文件
  • assets\com.example.hellojni.x86  //x86功能同上
  • libs\armeabi\libsecexe.so        //ARM平台共享库文件
  • libs\x86\libsecexe.so               //x86功能同上

加固后修改文件:
 AndroidMainfest.xml  //(如果应用配置有Application信息,则该文件加固前后相同,如果应用未配置Application信息,则该文件加固前后不相同,梆梆会配置Application信息为自己实现类)
classes.dex
对classes.dex进行反编译,观察代码树结构变化:(左为加固前,右为加固后)

(2)加固前后动态运行时变化
运行原程序,系统仅创建一个相关进程,但是加固的程序,系统会为其同时创建三个相关程序进程:
进程启动顺序:597进程创建605进程,605进程又创建了607进程

通过查看maps文件获取597进程映射文件信息
通过map文件可以看出,597进程为主进程,android各组件在该进程中运行。
605和607进程并无与apk文件相关文件信息,通过cmdline查看启动参数:

初步怀疑该进程为assets\com.example.hellojni 可执行文件运行结果。
2、梆梆加固保护效果分析
我们通过逆向分析加固后的app,来看看梆梆加固对app的保护效果。
程序代码的第一执行点是Application对象,首先查看TestApplication类对象。

程序的Util类完成大部分的java层逻辑

ACall类主要完成对libsecexe.so JNI的调用:

查看libsecexe.so文件导出函数,发现所有函数名都经过加密处理,与我们平时jni调用产生的函数名并不同。平时jni产生的函数名应该为这样格式Java_com_secapk_wrapper_ACall_{函数名}

抗静态分析:
Util类通过MyClassLoader完成对加密classes.jar的动态加载,内存中解密classes.jar,完成动态加载。
jni方法对应so函数名的混淆。
抗动态调试: 
当使用IDA动态调试该程序时,程序无法建立连接调试。
梆梆加固可以有效常用的逆向分析方法。

三、梆梆加固技术实现关键点猜想

(1)如何使DexClassLoader动态加载组件具有生命周期?
根据APK文件是否在AndroidManifest.xml配置Applicaiton信息,梆梆加固会做不同的处理:
通过上传Applicaiton不同配置的APK文件,我们发现:
当APK配置有Applicaition信息时,梆梆加固重写Application类
当APK未配置Application信息时,梆梆加固新建类,并在AndroidManifest.xml中配置自己Application类

因此Applicaiton就是程序的第一执行点。
我们知道DexClassLoader加载的类是没有组件生命周期的,也就是说即使DexClassLoader通过对dex的动态加载完成了对组件类的加载,当系统启动该组件时,还会出现加载类失败的异常。我已经在“Android APK加壳技术方案”
(http://blog.csdn.net/jiazhijun/article/details/8809542)中提出了一种使DexClassLoader加载组件类具有生命周期的方法。
运行加固后的程序并通过Mat内存分析工具查看类加载情况:

如上图所示,组件类的加载类已经被修改为com.secapk.wrapper.MyClassLoader类,可以得出结论,该方式和我提出方式基本相同,通过修改系统组件类ClassLoader来实现。

(2)如何混淆native方法在so库函数对应关系?
jni方法注册方式有两种,
1、通过javah产生函数头,该种方式产生的方法具有固定的格式。该方式使逆向分析人员比较容易获取java层native方法对应的本地方 法。
 2、在JNI_OnLoad方法中手动注册jni方法,不易查找对应关系。
使用第二种方式可以实现混淆java层native方法和so函数的对应关系。

#include <string.h>
#include <jni.h>  JNIEXPORT jstring JNICALL abcdefghijklmn( JNIEnv* env,jobject thiz )
{  return (*env)->NewStringUTF(env, "Hello from JNI !");
}  JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
{  JNIEnv* env = NULL;  jint result = -1;  if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {  return JNI_ERR;  }  JNINativeMethod gMethods[] = {  { "stringFromJNI", "()Ljava/lang/String;", (void*)abcdefghijklmn },  };  jclass clazz = (*env)->FindClass(env, "com/example/hellojni/HelloJni");  if (clazz == NULL) {  return JNI_ERR;  }  if ((*env)->RegisterNatives(env, clazz, gMethods, sizeof(gMethods) / sizeof(gMethods[0])) < 0){  return JNI_ERR;  }  /* success -- return valid version number */  result = JNI_VERSION_1_4;  return result;
}  

以上代码中的字符串都是明文(比如“stringFromJNI”),如果这些文明字符串都换成密文的话,再通过运行时解密,相应的对应关系更不易看出。
(3)如何使DexClassLoader加载加密的dex文件?
 虽然不了解梆梆加固是怎么做的,不过通过分析它的运行逻辑,我推测了一种可行的实现方案:了解该方案需要对Android         DexClassLoader的整个加载流程需要有清晰的了解。
首先推断assets\classes.jar是一个加密的jar包。
正常的DexClassLoader加载的流程如下:会有一个DexOpt产生odex过程

但是梆梆加固后的应用DexClassLoader加载过程并没有该过程的log信息。
 推断加密的jar包里面含有odex文件,如果不是odex文件的话,DexClassLoader肯定会在运行时释放未加密的odex文件到目录,这样的话被保护的逻辑也就泄露了。
DexClassLoader加载过程会在java层和C层产生不同的数据结构,java层并没有实质性的数据,所有的数据都在c层,我们可用通过底层代码完成dex数据的解析。底层dex分析是可以支持byte[]数组的,解密odex数据,传递过去就行了。这样java层就可以调用了。
 以下是大概伪代码实现步骤:

int loadDex(char * dexFileName)
{char *dvm_lib_path = "/system/lib/libdvm.so";void * handle;DvmGlobals gDvm;handle = dlopen( dvm_lib_path, int mode);

1、读取dexFileName文件内容并解密到byte数组。
2、调用dexFileParse函数解析byte数组为DexFile
\dalvik\libdex\DexFile.c
DexFile* dexFileParse(const u1* data, size_t length, int flags)//dlsym(handle, "dexFileParse");
3、调用allocateAuxStructures转换DexFile为DvmDex,(由于该方法为static方法,因此需要按照其逻辑自行实现)
\dalvik\vm\DvmDex.c
static DvmDex* allocateAuxStructures(DexFile* pDexFile) 
4、添加DvmDex到gDvm.userDexFiles
\dalvik\vm\Init.c
struct DvmGlobals gDvm; //gDvm = dlsym(handle, "gDvm");
5、修改MyDexClassLoader中的mDexs对象的mCookie值,mCookie主要用于映射底层DvmDex数据
DexClassLoader.mDexs[0].mCookie值

}
(4)so如何实现程序的反调试?
同linux反调试基本原理相同,这里提供一种方式就是在JNI_Onload中调用ptrace方法,ptrace被广泛用于调试(比如IDA)和进程代码注入(比如LBE,金山等权限管理功能实现),一个进程只能被一个进程ptrace,如果你自己调用ptarce,这样其它程序就无法通过ptrace调试或者 向您程序进程注入代码。
ptrace(PTRACE_TRACEME,0 ,0 ,0);
通过本人实验,该种方式可以实现so的反调试。

三、总结

通过以上分析,梆梆加固的确可以有效防止移动应用在运营推广过程中被破解、盗版、二次打包、注入、反编译等破坏,不过如果Android恶意软件也通过这种方式加固保护,这将会给移动安全分析人员带来巨大的挑战,因为安全分析人员经常使用的代码静态逻辑分析和动态调试分析在该情况下都失效了。
梆梆官方声称不会对恶意软件进行加固,的确在加固的过程中发现存在安全软件扫描信息和云测试处理流程,不过这些措施只能减少而不能彻底杜绝恶意软件通过梆梆加固保护。如何不被恶意软件利用是梆梆需要解决的问题。

【移动安全高级篇】————5、Andorid APK反逆向解决方案---梆梆加固原理探寻相关推荐

  1. Andorid APK反逆向解决方案:梆梆加固原理探寻

    一.序言 目前Android市场充斥着大量的盗版软件,开发者的官方应用被"打包党"们恶意篡改.如何使程序代码免受盗版篡改就成了开发者面临的头等大事,今天我们将分析一个不错的解决方案 ...

  2. Andorid APK反逆向解决方案---梆梆加固原理探寻

    本文章由Jack_Jia编写,转载请注明出处.   文章链接: http://blog.csdn.net/jiazhijun/article/details/8892635 作者:Jack_Jia   ...

  3. Andorid APK反逆向

    Andorid APK反逆向解决方案---梆梆加固原理探寻 http://blog.csdn.net/androidsecurity/article/details/8892635 Android A ...

  4. Andorid APK反编译

    原创文章,如有转载,请注明出处:http://blog.csdn.net/myth13141314/article/details/54973094 Android 反编译主要需要3个工具: dex2 ...

  5. 【MySQL从入门到精通】【高级篇】(一)字符集的修改与底层原理

    您好,我是码农飞哥,感谢您阅读本文,欢迎一键三连哦.

  6. Andorid Tools--强大的Apk反编译,Rom提取工具,从此告别枯燥的命令

    Andorid Tools--强大的Apk反编译,Rom提取工具,从此告别枯燥的命令 零.说明 1.本软件为兴趣而写,如有侵权,请告知. 2.本软件为本人所编写,未经允许,不得转载. 一.软件界面(当 ...

  7. 【移动安全高级篇】————7、APK 的自我保护

    由于 Android 应用程序中的大部分代码使用 Java 语言编写,而 Java 语言又比较容易进行逆向,所以 Android 应用程序的自我保护具有一定的意义.本文总结了 Android 中可以使 ...

  8. 当你写爬虫抓不到APP请求包的时候该怎么办?【高级篇-混淆导致通用Hook工具失效】...

    提示:因为高级篇以后的APP将无法使用很通用的方式处理,每种类型甚至是每个APP的反抓包处理方式都会有差别,所以这个系列以后会以[高级篇-具体类型]的形式来写. 这篇文章的主要内容是解决在遇到APP没 ...

  9. APK反编译得工具总结(转载)

    Android反编译技术总结 转自UncleChen's Blog,作者:UncleChen 一.Apk反编译工具及其使用方法 1.原理 学习反编译之前,建议先学习一下Apk打包的过程,明白打包完成后 ...

最新文章

  1. apex英雄机器人探路者怎么玩_《Apex英雄》探路者机器人怎么玩 探路者机器人技能特性及玩法...
  2. 独家 | 综述:情感树库上语义组合的递归深层模型
  3. STM32启动模式详解
  4. 直接拿来用!最火的Android开源项目(完结篇)(转)
  5. javaweb可部署目录结构
  6. 用python画个三维地球_如何用Python制作三维散点图?
  7. Docker启动MySql后连接报1251处理方法
  8. 柯达新款Wi-Fi数码相机闪亮登场
  9. SSM框架笔记10:Spring AOP基础
  10. matlab求曲线极值程序,matlab函数求极值matlab函数求极值.ppt
  11. 日记 [2007年03月10日]重回blog,开始2007
  12. 28.开始画面和异形窗口
  13. 路由与交换技术(复习知识点-全)
  14. Windows调试技巧工具
  15. python爬取qq邮箱_使用Python模拟登录QQ邮箱获取QQ好友列表
  16. java gui界面设计qq_Java swing界面开发(仿QQ登录界面)
  17. 错误1053: 服务没有及时地响应启动或控制请求
  18. 3.3 典型交易流程
  19. RADARSAT-1数据下载
  20. 学习笔记 | c++中的smart pointer四个智能指针 shared_ptr、unique_ptr、weak_ptr、auto_ptr

热门文章

  1. Python解析DBLP的xml文件
  2. 魔兽世界8.0哪个服务器稳定,魔兽世界8.0国服开服了!为了不落后!这九件事急需了解掌握...
  3. JPMML调用PMML机器学习模型零基础总结(内含新版本jpmml解决方法)
  4. KD tree (K dimensional tree)多维空间搜索 近邻
  5. Gateway网关简介及使用。Spring Cloud Alibaba---Gateway概述、简单示例。什么是Gataway网关?网关能干什么?Spring Cloud如何搭建一个网关。
  6. 记一次tomcat、gateway配置SSL,使用https访问
  7. spring cloud gateway实现https访问
  8. 在北京的互联网公司工作多少年可以买房?
  9. 东大22春电子政务X《电子政务》在线平时作业3参考非答案
  10. 智汀智能家居知识普及篇——家居智能控制方式及控制系统的特点,你知道几个?