`
shuai1234
  • 浏览: 932603 次
  • 性别: Icon_minigender_1
  • 来自: 山西
社区版块
存档分类
最新评论

梆梆加固破解

 
阅读更多

本文假设你已经使用过梆梆加固,手头至少有个一个通过梆梆加固后的apk,并且要求您对xposed框架有一定的了解,以下的所有hook方法都是通过xposed来实现的。

     BTW:本人实现了一个hook动态库的功能,无需root就能hook住动态库的对外接口,后面会写文章介绍方法

梆梆加固的原理,这里就不仔细描述了,可以将加固后的apk反编译后分析一下,看看梆梆在里面都加了什么内容,我总结一下梆梆加固做了哪些事情:

1、创建.cache目录,/data/data/packageName/.cache/"

2、自定义DexClassLoader:

      dexPath: /data/data/packagename/.cache/classes.jar

      optimizedDirectory: /data/data/packagename/.cache

      libraryPath: /data/data/packagename/lib

3、通过自定义dexclassloader的方式,可以将真正的dex进行隐藏,在运行时动态load该dex,

4、 由于dex在安装时会被转换为odex存放在/data/dalvik-cache目录下,梆梆加固后的app在该目录下的odex文件非真正运行的odex文件。

  小结:万变不离其宗,不管梆梆加固怎么伪装,原理上都是通过自定义DexClassLoader来实现的,这也是破解梆梆加固的根本。

  BTW:梆梆加固为了防破解还是做了很多工作的,比如笔者之前试着通过用gdb来挂进程,并通过dump内存的方式来破解,但是一挂上进程后,程序就异常终止了。

破解办法:由于梆梆加固将真实的dex进行了隐藏,所以咱们现在要做的就是想办法把真实的dex给挖出来,通过静态的文件分析没什么好办法,但是有一点可能是所有的加固软件都没办法解决的问题,就是在程序运行时,需要把dex文件加载到内存里来。这是我们破解的入口,以下内容也是围绕着这个目标来展开的。

1、 要获取dex文件的信息,必须获得系统的ClassLoaer ,每个apk运行起来后都有一个对应的数据结构:如下:

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. public final class LoadedApk {  
  2.   
  3.     private static final String TAG = "LoadedApk";  
  4.   
  5.     private final ActivityThread mActivityThread;  
  6.     private final ApplicationInfo mApplicationInfo;  
  7.     final String mPackageName;  
  8.     private final String mAppDir;  
  9.     private final String mResDir;  
  10.     private final String[] mSharedLibraries;  
  11.     private final String mDataDir;  
  12.     private final String mLibDir;  
  13.     private final File mDataDirFile;  
  14.     private final ClassLoader mBaseClassLoader;  
  15.     private final boolean mSecurityViolation;  
  16.     private final boolean mIncludeCode;  
  17.     private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();  
  18.     Resources mResources;  
  19.     private ClassLoader mClassLoader;  
  20.     private Application mApplication;  
  21.   
  22.     private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers  
  23.         = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();  
  24.     private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers  
  25.         = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();  
  26.     private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices  
  27.         = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();  
  28.     private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices  
  29.         = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();  
  30.   
  31.     int mClientCount = 0;  

          如果能拿到这个数据结构,就能拿到对应的ClassLoader信息,还能拿到所有的services、receivers信息。这个可以通过hook类

Android.app.ActivityThread.AppBindData中的handleBindApplication方法来实现。

2、拿到ClassLoader后,就能拿到dex文件路径、library路径、odex文件路径,dexPath对应的类为dalvik.system.DexPathList,包含一个成员变量Element数组用来存放所有的odex文件,Element数据结构如下:

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. static class Element {  
  2.         private final File file;  
  3.         private final boolean isDirectory;  
  4.         private final File zip;  
  5.         private final DexFile dexFile;  
  6.   
  7.         private ZipFile zipFile;  
  8.         private boolean initialized;  

        其中DexFile就是odex文件的描述,而在该类中有个变量mCookie,如下图:

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. public final class DexFile {  
  2.     private int mCookie;  
  3.     private final String mFileName;  
  4.     private final CloseGuard guard = CloseGuard.get();  

 

这个就是咱们要找的东西啦,这个整形变量存储的是native层的指针值,指向的是dex在内存里的地址,也就是咱们的最终目标,mCookie指向的结构体如下图。

 

[cpp] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. typedef struct DexOrJar {  
  2.     char*          fileName;  
  3.     bool           isDex; //是dex文件还是jar包  
  4.     bool           okayToFree;  
  5.     RawDexFile*    pRawDexFile;  
  6.     JarFile*       pJarFile;  //如果是jar包,则指向JarFile结构  
  7.     u1* pDexMemory; //如果是dex,则指向dex内存区  
  8. } DexOrJar;  

         思考:如何建立dexPath和DexOrJar结构体之间的映射关系呢?方法是:hook住dalvik.system.DexFile 中的openDexFileNative方法。在应用程序启动时,都会load dex文件,最终都会调用该方法,openDexFileNative方法为native方法,实现定义在dalvik_system_DexFile.cpp文件中的Dalvik_dalvik_system_DexFile_openDexFileNative方法中)然后根据dexpath取出DexOrJar对象指针,有了这个对象拿出odex只是时间的问题了。

   从上述结构体中可以看出,根据扩展名是dex还是jar来决定内存的组织。有了指针我们就可以将其强转换为DexOrJar对象,其实到此处就已经拿到了odex文件对应的内存内容,下一步需要将该内容导出为smali,然后做dexodex to smali,最终得到smali文件后通过baksmali,就可以还原为dex文件。得到dex文件后,通过dex2jar可以转为Java文件,如下图为用梆梆加固后的陌陌解密后导出的dex文件反编译后内容:


 

  

在得到了dex和工程资源文件后,就可以将程序跑起来,还可以在外面加一层壳后跑起来,后面会写一篇文章详细描述这个过程。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics