android基础11-dex文件改造-

学习笔记,自用,整理中

摘要:

面试:

apk打包流程:as电脑里面有给appdata/local/android/sdk/build-tools/aapt aidl

一系列工具完成的;gradle处理了。

运行时解密;

attachbasecontext 开始解密;

tinker:腾讯热修复

hook 勾子 :反射技术去反射 android源码的过程

大部分手机是23以上的

------------------------------------------------------------------------------------

内容:









--------------------------------------------------------------------------------------------------------------------

加密:

public class MyMain {

public static void main(String[] args)throws Exception {

byte[] mainDexData; //�洢Դapk�е�Դdex�ļ�

      byte[] aarData;    // �洢���еĿ�dex�ļ�

      byte[] mergeDex;    // �洢��dex ��Դdex �ĺϲ�����dex�ļ�

      File tempFileApk =new File("source/apk/temp");

      if (tempFileApk.exists()) {

File[]files = tempFileApk.listFiles();

        for(File file: files){

if (file.isFile()) {

file.delete();

            }

}

}

File tempFileAar =new File("source/aar/temp");

      if (tempFileAar.exists()) {

File[]files = tempFileAar.listFiles();

        for(File file: files){

if (file.isFile()) {

file.delete();

            }

}

}

/**

* ��һ�� ����ԭʼapk ����dex

*

*/

        AES.init(AES.DEFAULT_PWD);

        //��ѹapk

        File apkFile =new File("source/apk/app-debug.apk");

        File newApkFile =new File(apkFile.getParent() + File.separator +"temp");

        if(!newApkFile.exists()) {

newApkFile.mkdirs();

        }

File mainDexFile = AES.encryptAPKFile(apkFile,newApkFile);

        if (newApkFile.isDirectory()) {

File[] listFiles = newApkFile.listFiles();

        for (File file : listFiles) {

if (file.isFile()) {

if (file.getName().endsWith(".dex")) {

String name = file.getName();

                  System.out.println("rename step1:"+name);

                  int cursor = name.indexOf(".dex");

                  String newName = file.getParent()+ File.separator + name.substring(0, cursor) +"_" +".dex";

                  System.out.println("rename step2:"+newName);

                  file.renameTo(new File(newName));

              }

}

}

}

/**

* �ڶ��� ����aar ��ÿ�dex

*/

      File aarFile =new File("source/aar/mylibrary-debug.aar");

        File aarDex  = Dx.jar2Dex(aarFile);

//        aarData = Utils.getBytes(aarDex);  //��dex�ļ�����byte ����

        File tempMainDex =new File(newApkFile.getPath() + File.separator +"classes.dex");

        if (!tempMainDex.exists()) {

tempMainDex.createNewFile();

      }

//        System.out.println("MyMain" + tempMainDex.getAbsolutePath());

        FileOutputStream fos =new FileOutputStream(tempMainDex);

        byte[] fbytes = Utils.getBytes(aarDex);

        fos.write(fbytes);

        fos.flush();

        fos.close();

        /**

* ��3�� ���ǩ��

*/

        File unsignedApk =new File("result/apk-unsigned.apk");

        unsignedApk.getParentFile().mkdirs();

//        File disFile = new File(apkFile.getAbsolutePath() + File.separator+ "temp");

        Zip.zip(newApkFile, unsignedApk);

        //���ò���Ͳ����Զ�ʹ��ԭapk��ǩ��...

        File signedApk =new File("result/apk-signed.apk");

        Signature.signature(unsignedApk, signedApk);

    }

private static FilegetMainDexFile(File apkFile) {

// TODO Auto-generated method stub

      File disFile =new File(apkFile.getAbsolutePath() +"unzip");

      Zip.unZip(apkFile, disFile);

      File[] files = disFile.listFiles(new FilenameFilter() {

@Override

        public boolean accept(File dir, String name) {

if (name.endsWith(".dex")) {

return true;

            }

return false;

        }

});

      for (File file: files) {

if (file.getName().endsWith("classes.dex")) {

return file;

        }

}

return null;

  }

}

----------------------------------------------------------------------------------------------------------------------------

解密:

public class ShellApplicationextends Application {

private static final StringTAG ="ShellApplication";

    public static StringgetPassword(){

return "abcdefghijklmnop";

    }

//    static {

//        System.loadLibrary("native-lib");

//    }

    @Override

    protected void attachBaseContext(Context base) {

super.attachBaseContext(base);

        AES.init(getPassword());

        File apkFile =new File(getApplicationInfo().sourceDir);

        //data/data/包名/files/fake_apk/

        File unZipFile = getDir("fake_apk", MODE_PRIVATE);

        File app =new File(unZipFile, "app");

        if (!app.exists()) {

Zip.unZip(apkFile, app);

            File[] files = app.listFiles();

            for (File file : files) {

String name = file.getName();

                if (name.equals("classes.dex")) {

}else if (name.endsWith(".dex")) {

try {

byte[] bytes = getBytes(file);

                            FileOutputStream fos =new FileOutputStream(file);

                            byte[] decrypt = AES.decrypt(bytes);

//                        fos.write(bytes);

                            fos.write(decrypt);

                            fos.flush();

                            fos.close();

                        }catch (Exception e) {

e.printStackTrace();

                    }

}

}

}

List list =new ArrayList<>();

        Log.d("FAKE", Arrays.toString(app.listFiles()));

        for (File file : app.listFiles()) {

if (file.getName().endsWith(".dex")) {

list.add(file);

            }

}

Log.d("FAKE", list.toString());

        try {

V19.install(getClassLoader(), list, unZipFile);

        }catch (IllegalAccessException e) {

e.printStackTrace();

        }catch (NoSuchFieldException e) {

e.printStackTrace();

        }catch (InvocationTargetException e) {

e.printStackTrace();

        }catch (NoSuchMethodException e) {

e.printStackTrace();

        }

}

private static FieldfindField(Object instance, String name)throws NoSuchFieldException {

Class clazz = instance.getClass();

        while (clazz !=null) {

try {

Field e = clazz.getDeclaredField(name);

                if (!e.isAccessible()) {

e.setAccessible(true);

                }

return e;

            }catch (NoSuchFieldException var4) {

clazz = clazz.getSuperclass();

            }

}

throw new NoSuchFieldException("Field " + name +" not found in " + instance.getClass());

    }

private static MethodfindMethod(Object instance, String name, Class... parameterTypes)

throws NoSuchMethodException {

Class clazz = instance.getClass();

//        Method[] declaredMethods = clazz.getDeclaredMethods();

//        System.out.println("  findMethod ");

//        for (Method m : declaredMethods) {

//            System.out.print(m.getName() + "  : ");

//            Class[] parameterTypes1 = m.getParameterTypes();

//            for (Class clazz1 : parameterTypes1) {

//                System.out.print(clazz1.getName() + " ");

//            }

//            System.out.println("");

//        }

        while (clazz !=null) {

try {

Method e = clazz.getDeclaredMethod(name, parameterTypes);

                if (!e.isAccessible()) {

e.setAccessible(true);

                }

return e;

            }catch (NoSuchMethodException var5) {

clazz = clazz.getSuperclass();

            }

}

throw new NoSuchMethodException("Method " + name +" with parameters " + Arrays.asList

                (parameterTypes) +" not found in " + instance.getClass());

    }

private static void expandFieldArray(Object instance, String fieldName, Object[]

extraElements)throws NoSuchFieldException, IllegalArgumentException,

            IllegalAccessException {

Field jlrField =findField(instance, fieldName);

        Object[] original = (Object[]) ((Object[]) jlrField.get(instance));

        Object[] combined = (Object[]) ((Object[]) Array.newInstance(original.getClass()

.getComponentType(), original.length + extraElements.length));

        System.arraycopy(original, 0, combined, 0, original.length);

        System.arraycopy(extraElements, 0, combined, original.length, extraElements.length);

        jlrField.set(instance, combined);

    }

private static final class V19 {

private V19() {

}

private static void install(ClassLoader loader, List additionalClassPathEntries,

                                    File optimizedDirectory)throws IllegalArgumentException,

                IllegalAccessException, NoSuchFieldException, InvocationTargetException,

                NoSuchMethodException {

Field pathListField =findField(loader, "pathList");

            Object dexPathList = pathListField.get(loader);

            ArrayList suppressedExceptions =new ArrayList();

            Log.d(TAG, "Build.VERSION.SDK_INT " + Build.VERSION.SDK_INT);

            if (Build.VERSION.SDK_INT >=23) {

expandFieldArray(dexPathList, "dexElements", makePathElements(dexPathList, new

                                ArrayList(additionalClassPathEntries), optimizedDirectory,

                        suppressedExceptions));

            }else {

expandFieldArray(dexPathList, "dexElements", makeDexElements(dexPathList, new

                                ArrayList(additionalClassPathEntries), optimizedDirectory,

                        suppressedExceptions));

            }

if (suppressedExceptions.size() >0) {

Iterator suppressedExceptionsField = suppressedExceptions.iterator();

                while (suppressedExceptionsField.hasNext()) {

IOException dexElementsSuppressedExceptions = (IOException)

suppressedExceptionsField.next();

                    Log.w("MultiDex", "Exception in makeDexElement",

                            dexElementsSuppressedExceptions);

                }

Field suppressedExceptionsField1 =findField(loader,

                        "dexElementsSuppressedExceptions");

                IOException[] dexElementsSuppressedExceptions1 = (IOException[]) ((IOException[])

suppressedExceptionsField1.get(loader));

                if (dexElementsSuppressedExceptions1 ==null) {

dexElementsSuppressedExceptions1 = (IOException[]) suppressedExceptions

.toArray(new IOException[suppressedExceptions.size()]);

                }else {

IOException[] combined =new IOException[suppressedExceptions.size() +

dexElementsSuppressedExceptions1.length];

                    suppressedExceptions.toArray(combined);

                    System.arraycopy(dexElementsSuppressedExceptions1, 0, combined,

                            suppressedExceptions.size(), dexElementsSuppressedExceptions1.length);

                    dexElementsSuppressedExceptions1 = combined;

                }

suppressedExceptionsField1.set(loader, dexElementsSuppressedExceptions1);

            }

}

private static Object[]makeDexElements(Object dexPathList,

                                                ArrayList files, File

optimizedDirectory,

                                                ArrayList suppressedExceptions)throws

                IllegalAccessException, InvocationTargetException, NoSuchMethodException {

Method makeDexElements =findMethod(dexPathList, "makeDexElements", new

                        Class[]{ArrayList.class, File.class, ArrayList.class});

                return ((Object[]) makeDexElements.invoke(dexPathList, new Object[]{files,

                        optimizedDirectory, suppressedExceptions}));

          }

}

/**

* A wrapper around

    * {@code private static final dalvik.system.DexPathList#makePathElements}.

*/

    private static Object[]makePathElements(

Object dexPathList, ArrayList files, File optimizedDirectory,

            ArrayList suppressedExceptions)

throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {

Method makePathElements;

        try {

makePathElements =findMethod(dexPathList, "makePathElements", List.class, File.class,

                    List.class);

        }catch (NoSuchMethodException e) {

Log.e(TAG, "NoSuchMethodException: makePathElements(List,File,List) failure");

            try {

makePathElements =findMethod(dexPathList, "makePathElements", ArrayList.class, File.class, ArrayList.class);

            }catch (NoSuchMethodException e1) {

Log.e(TAG, "NoSuchMethodException: makeDexElements(ArrayList,File,ArrayList) failure");

                try {

Log.e(TAG, "NoSuchMethodException: try use v19 instead");

                    return V19.makeDexElements(dexPathList, files, optimizedDirectory, suppressedExceptions);

                }catch (NoSuchMethodException e2) {

Log.e(TAG, "NoSuchMethodException: makeDexElements(List,File,List) failure");

                    throw e2;

                }

}

}

return (Object[]) makePathElements.invoke(dexPathList, files, optimizedDirectory, suppressedExceptions);

    }

private byte[]getBytes(File file)throws Exception {

RandomAccessFile r =new RandomAccessFile(file, "r");

        byte[] buffer =new byte[(int) r.length()];

        r.readFully(buffer);

        r.close();

        return buffer;

    }

}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容