B) 从壳程序DEX中得到源程序APK文件
/** * 释放被加壳的apk文件,so文件 * @param data * @throws IOException */private void splitPayLoadFromDex(byte[] apkdata) throws IOException { int ablen = apkdata.length; //取被加壳apk的长度 这里的长度取值,对应加壳时长度的赋值都可以做些简化 byte[] dexlen = new byte[4]; System.arraycopy(apkdata, ablen - 4, dexlen, 0, 4); ByteArrayInputStream bais = new ByteArrayInputStream(dexlen); DataInputStream in = new DataInputStream(bais); int readInt = in.readInt(); System.out.println(Integer.toHexString(readInt)); byte[] newdex = new byte[readInt]; //把被加壳的源程序apk内容拷贝到newdex中 System.arraycopy(apkdata, ablen - 4 - readInt, newdex, 0, readInt); //这里应该加上对于apk的解密操作,若加壳是加密处理的话 // 对源程序Apk进行解密 newdex = decrypt(newdex);// 写入apk文件File file = new File(apkFileName); try { FileOutputStream localFileOutputStream = new FileOutputStream(file); localFileOutputStream.write(newdex); localFileOutputStream.close(); } catch (IOException localIOException) { throw new RuntimeException(localIOException); }// 分析被加壳的apk文件 ZipInputStream localZipInputStream = new ZipInputStream( new BufferedInputStream(new FileInputStream(file))); while (true) { ZipEntry localZipEntry = localZipInputStream.getNextEntry(); // 这个也遍历子目录 if (localZipEntry == null) { localZipInputStream.close(); break; } // 取出被加壳apk用到的so文件,放到libPath中(data/data/包名/payload_lib) String name = localZipEntry.getName(); if (name.startsWith("lib/") && name.endsWith(".so")) { File storeFile = new File(libPath + "/" + name.substring(name.lastIndexOf('/'))); storeFile.createNewFile(); FileOutputStream fos = new FileOutputStream(storeFile); byte[] arrayOfByte = new byte[1024]; while (true) { int i = localZipInputStream.read(arrayOfByte); if (i == -1) break; fos.write(arrayOfByte, 0, i); } fos.flush(); fos.close(); } localZipInputStream.closeEntry(); } localZipInputStream.close();}C) 解密源程序APK
//直接返回数据,读者可以添加自己解密方法private byte[] decrypt(byte[] srcdata) { for(int i=0;i<srcdata.length;i++){ srcdata[i] = (byte)(0xFF ^ srcdata[i]); } return srcdata;}
- 找到源程序的Application程序,让其运行
@Overridepublic void onCreate() { { //loadResources(apkFileName); Log.i("demo", "onCreate"); // 如果源应用配置有Appliction对象,则替换为源应用Applicaiton,以便不影响源程序逻辑 。String appClassName = null; try { ApplicationInfo ai = this.getPackageManager() .getApplicationInfo(this.getPackageName(), PackageManager.GET_META_DATA); Bundle bundle = ai.metaData; if (bundle != null && bundle.containsKey("APPLICATION_CLASS_NAME")) { appClassName = bundle.getString("APPLICATION_CLASS_NAME");//className 是配置在xml文件中的 。} else { Log.i("demo", "have no application class name"); return; } } catch (NameNotFoundException e) { Log.i("demo", "error:"+Log.getStackTraceString(e)); e.printStackTrace(); } //有值的话调用该Applicaiton Object currentActivityThread = RefInvoke.invokeStaticMethod( "android.app.ActivityThread", "currentActivityThread", new Class[] {}, new Object[] {}); Object mBoundApplication = RefInvoke.getFieldOjbect( "android.app.ActivityThread", currentActivityThread, "mBoundApplication"); Object loadedApkInfo = RefInvoke.getFieldOjbect( "android.app.ActivityThread$AppBindData", mBoundApplication, "info"); //把当前进程的mApplication 设置成了null RefInvoke.setFieldOjbect("android.app.LoadedApk", "mApplication", loadedApkInfo, null); Object oldApplication = RefInvoke.getFieldOjbect( "android.app.ActivityThread", currentActivityThread, "mInitialApplication"); //http://www.codeceo.com/article/android-context.html ArrayList<Application> mAllApplications = (ArrayList<Application>) RefInvoke .getFieldOjbect("android.app.ActivityThread", currentActivityThread, "mAllApplications"); mAllApplications.remove(oldApplication); // 删除oldApplicationApplicationInfo appinfo_In_LoadedApk = (ApplicationInfo) RefInvoke .getFieldOjbect("android.app.LoadedApk", loadedApkInfo, "mApplicationInfo"); ApplicationInfo appinfo_In_AppBindData = https://www.isolves.com/it/cxkf/ydd/Android/2019-09-04/(ApplicationInfo) RefInvoke .getFieldOjbect("android.app.ActivityThread$AppBindData", mBoundApplication, "appInfo"); appinfo_In_LoadedApk.className = appClassName; appinfo_In_AppBindData.className = appClassName; Application app = (Application) RefInvoke.invokeMethod( "android.app.LoadedApk", "makeApplication", loadedApkInfo, new Class[] { boolean.class, Instrumentation.class }, new Object[] { false, null }); // 执行 makeApplication(false,null) RefInvoke.setFieldOjbect("android.app.ActivityThread", "mInitialApplication", currentActivityThread, app); ArrayMap mProviderMap = (ArrayMap) RefInvoke.getFieldOjbect( "android.app.ActivityThread", currentActivityThread, "mProviderMap"); Iterator it = mProviderMap.values().iterator(); while (it.hasNext()) { Object providerClientRecord = it.next(); Object localProvider = RefInvoke.getFieldOjbect( "android.app.ActivityThread$ProviderClientRecord", providerClientRecord, "mLocalProvider"); RefInvoke.setFieldOjbect("android.content.ContentProvider", "mContext", localProvider, app); } Log.i("demo", "app:"+app); app.onCreate(); }}
推荐阅读
-
-
-
“侯贵平”陆思宇:为《沉默的真相》减重15斤、全程戴假发
-
花卉网|天冷后立刻放到房间里,避免冻伤,有养这3种花的要注意了
-
腕表之家|看别人的表暗下决心 升级天梭入手万国葡计
-
车与舆■迎合市场需求的英菲尼迪QX60,你会考虑吗,空间大、低油耗
-
蜂蜜|又酥又脆又香,简单几步就搞定,0失败0难度自制低脂健康小零食
-
肝脏|肝脏好不好,睡觉就知道!睡觉时出现3种“迹象”,趁早检查肝功
-
北京青年报|美联航21日起恢复 中美不经停直飞航线
-
[迷彩虎]700人惨遭隔离,怎么感染上的?,又一铁证!美战略核潜艇中招
-
汉中陶大夫|这些数据告诉你吸烟还会使人“伤心”,吸烟只会把肺“熏黑”?非也
-
「系统架构」使用微信公众号支付?这个地方你需要注意一下
-
-
-
烹饪|60元一个的爆浆蛋糕,自己在家做10块钱都不用,比蒸馒头简单
-
花边|最近火了一种裙子叫“芙蓉裙”,灵动飘逸不显胖,看江疏影就知道
-
生肖@5月下旬,财神临门,不用为钱发愁,日子富得流油的生肖
-
元梅说历史|南打印度,东征大唐,还夺取长安,消失千年神秘古国:西征阿拉伯
-
科学1978年NASA发现金星生命,为何没公布,一失误饮恨终身
-