赞
踩
享学堂
import java.io.File; import java.io.FileFilter; import java.io.FileOutputStream; import java.io.FilenameFilter; 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 File getMainDexFile(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; } }
import java.io.File; import java.io.FileOutputStream; import java.io.FilenameFilter; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.SecretKeySpec; /** * Created by xiang on 16/6/8. */ public class AES { public static final String DEFAULT_PWD = "abcdefghijklmnop"; private static final String algorithmStr = "AES/ECB/PKCS5Padding"; private static Cipher encryptCipher; private static Cipher decryptCipher; public static void init(String password) { try { // 生成一个实现指定转换的 Cipher 对象。 encryptCipher = Cipher.getInstance(algorithmStr); decryptCipher = Cipher.getInstance(algorithmStr);// algorithmStr byte[] keyStr = password.getBytes(); SecretKeySpec key = new SecretKeySpec(keyStr, "AES"); encryptCipher.init(Cipher.ENCRYPT_MODE, key); decryptCipher.init(Cipher.DECRYPT_MODE, key); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } } /** * * @param srcAPKfile 源文件所在位置 * @param dstApkFile 目标文件 * @return 加密后的新dex 文件 * @throws Exception */ public static File encryptAPKFile(File srcAPKfile, File dstApkFile) throws Exception { if (srcAPKfile == null) { System.out.println("encryptAPKFile :srcAPKfile null"); return null; } // File disFile = new File(srcAPKfile.getAbsolutePath() + "unzip"); // Zip.unZip(srcAPKfile, disFile); Zip.unZip(srcAPKfile, dstApkFile); //获得所有的dex (需要处理分包情况) File[] dexFiles = dstApkFile.listFiles(new FilenameFilter() { @Override public boolean accept(File file, String s) { return s.endsWith(".dex"); } }); File mainDexFile = null; byte[] mainDexData = null; for (File dexFile: dexFiles) { //读数据 byte[] buffer = Utils.getBytes(dexFile); //加密 byte[] encryptBytes = AES.encrypt(buffer); if (dexFile.getName().endsWith("classes.dex")) { mainDexData = encryptBytes; mainDexFile = dexFile; } //写数据 替换原来的数据 FileOutputStream fos = new FileOutputStream(dexFile); fos.write(encryptBytes); fos.flush(); fos.close(); } return mainDexFile; } public static byte[] encrypt(byte[] content) { try { byte[] result = encryptCipher.doFinal(content); return result; } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } return null; } public static byte[] decrypt(byte[] content) { try { byte[] result = decryptCipher.doFinal(content); return result; } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } return null; } public static void main(String[] args) throws Exception { // byte[] newfs = Utils.int2Bytes(2312312); // byte[] refs = new byte[4]; // //楂樹綅鍦ㄥ墠锛屼綆浣嶅湪鍓嶆帀涓釜 // for (int i = 0; i < 4; i++) { // refs[i] = newfs[newfs.length - 1 - i]; // } // System.out.println(Arrays.toString(newfs)); // System.out.println(Arrays.toString(refs)); // // ByteBuf byteBuf = Unpooled.buffer(); // // byteBuf.writeInt(2312312); // byte[] a = new byte[4]; // byteBuf.order(ByteOrder.LITTLE_ENDIAN); // byteBuf.readBytes(a); // System.out.println(Arrays.toString(a)); // AES.init(AES.DEFAULT_PWD); // String msg = Base64.encode(AES.encrypt(new byte[]{1, 2, 3, 4, 5})); // System.out.println(msg); // byte[] aes = AES.decrypt(Base64.decode(msg)); // System.out.println(Arrays.toString(aes)); File zip = new File("/Users/xiang/develop/source.apk"); String absolutePath = zip.getAbsolutePath(); File dir = new File(absolutePath.substring(0, absolutePath.lastIndexOf("."))); Zip.unZip(zip,dir); File zip2 = new File("/Users/xiang/develop/app-debug2.apk"); Zip.zip(dir,zip2); String[] argv = { "jarsigner","-verbose", "-sigalg", "MD5withRSA", "-digestalg", "SHA1", "-keystore", "/Users/xiang/develop/debug.keystore", "-storepass","android", "-keypass", "android", "-signedjar", "/Users/xiang/develop/app-debug2-sign.apk", "/Users/xiang/develop/app-debug2.apk", "androiddebugkey" }; Process pro = null; try { pro = Runtime.getRuntime().exec(argv); //destroy the stream try { pro.waitFor(); } catch (InterruptedException e) { e.printStackTrace(); } } finally { if (pro != null) { pro.destroy(); } } } }
import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; /** * Created by LK on 2017/9/5. * */ public class Dx { public static File jar2Dex(File aarFile) throws IOException, InterruptedException { File fakeDex = new File(aarFile.getParent() + File.separator + "temp"); System.out.println("jar2Dex: aarFile.getParent(): " + aarFile.getParent()); //解压aar到 fakeDex 目录下 Zip.unZip(aarFile, fakeDex); //过滤找到对应的fakeDex 下的classes.jar File[] files = fakeDex.listFiles(new FilenameFilter() { @Override public boolean accept(File file, String s) { return s.equals("classes.jar"); } }); if (files == null || files.length <= 0) { throw new RuntimeException("the aar is invalidate"); } File classes_jar = files[0]; // 将classes.jar 变成classes.dex File aarDex = new File(classes_jar.getParentFile(), "classes.dex"); //我们要将jar 转变成为dex 需要使用android tools 里面的dx.bat //使用java 调用windows 下的命令 Dx.dxCommand(aarDex, classes_jar); return aarDex; } public static void dxCommand(File aarDex, File classes_jar) throws IOException, InterruptedException { Runtime runtime = Runtime.getRuntime(); Process process = runtime.exec("cmd.exe /C dx --dex --output=" + aarDex.getAbsolutePath() + " " + classes_jar.getAbsolutePath()); try { process.waitFor(); } catch (InterruptedException e) { e.printStackTrace(); throw e; } if (process.exitValue() != 0) { InputStream inputStream = process.getErrorStream(); int len; byte[] buffer = new byte[2048]; ByteArrayOutputStream bos = new ByteArrayOutputStream(); while((len=inputStream.read(buffer)) != -1){ bos.write(buffer,0,len); } System.out.println(new String(bos.toByteArray(),"GBK")); throw new RuntimeException("dx run failed"); } process.destroy(); } }
import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; /** * Created by LK on 2017/9/4. * */ public class Signature { public static void signature(File unsignedApk, File signedApk) throws InterruptedException, IOException { String cmd[] = {"cmd.exe", "/C ","jarsigner", "-sigalg", "MD5withRSA", "-digestalg", "SHA1", "-keystore", "C:/Users/allen/.android/debug.keystore", "-storepass", "android", "-keypass", "android", "-signedjar", signedApk.getAbsolutePath(), unsignedApk.getAbsolutePath(), "androiddebugkey"}; Process process = Runtime.getRuntime().exec(cmd); System.out.println("start sign"); // BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); // String line; // while ((line = reader.readLine()) != null) // System.out.println("tasklist: " + line); try { int waitResult = process.waitFor(); System.out.println("waitResult: " + waitResult); } catch (InterruptedException e) { e.printStackTrace(); throw e; } System.out.println("process.exitValue() " + process.exitValue() ); if (process.exitValue() != 0) { InputStream inputStream = process.getErrorStream(); int len; byte[] buffer = new byte[2048]; ByteArrayOutputStream bos = new ByteArrayOutputStream(); while((len=inputStream.read(buffer)) != -1){ bos.write(buffer,0,len); } System.out.println(new String(bos.toByteArray(),"GBK")); throw new RuntimeException("签名执行失败"); } System.out.println("finish signed"); process.destroy(); } }
import java.io.File; import java.io.RandomAccessFile; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.zip.Adler32; /** * Created by xiang on 2017/5/17. */ public class Utils { // public static byte[] int2Bytes(int number) { // byte[] b = new byte[4]; // for (int i = 3; i >= 0; i--) { // b[i] = (byte) (number % 256); // number >>= 8; // } // return b; // } public static byte[] int2Bytes(int value) { byte[] src = new byte[4]; src[3] = (byte) ((value >> 24) & 0xFF); src[2] = (byte) ((value >> 16) & 0xFF); src[1] = (byte) ((value >> 8) & 0xFF); src[0] = (byte) (value & 0xFF); return src; } public static int bytes2Int(byte[] src) { int value; value = (int) ((src[0] & 0xFF) | ((src[1] & 0xFF)<<8) | ((src[2] & 0xFF)<<16) | ((src[3] & 0xFF)<<24)); return value; } public static void changeSignature(byte[] newDex) throws NoSuchAlgorithmException { System.out.println("更换dex文件 签名信息..."); MessageDigest md = MessageDigest.getInstance("SHA-1"); //从32个字节开始 计算sha1值 md.update(newDex, 32, newDex.length - 32); byte[] sha1 = md.digest(); //从第12位开始拷贝20字节内容 //替换signature System.arraycopy(sha1, 0, newDex, 12, 20); System.out.println("更换dex文件 checksum..."); } public static void changeCheckSum(byte[] newDex) { Adler32 adler = new Adler32(); adler.update(newDex, 12, newDex.length - 12); int value = (int) adler.getValue(); byte[] checkSum = Utils.int2Bytes(value); System.arraycopy(checkSum, 0, newDex, 8, 4); } public static byte[] getBytes(File dexFile) throws Exception { RandomAccessFile fis = new RandomAccessFile(dexFile, "r"); byte[] buffer = new byte[(int)fis.length()]; fis.readFully(buffer); fis.close(); return buffer; } public static void changeFileSize(byte[] mainDexData, byte[] newDex, byte[] aarData ) { byte[] bytes = Utils.int2Bytes(mainDexData.length); System.out.println("拷贝原来dex长度到新的dex:" + Utils.bytes2Int(bytes)); //更该文件头长度信息 //修改 System.out.println("更换dex 文件头长度信息..."); byte[] file_size = Utils.int2Bytes(newDex.length); System.arraycopy(file_size, 0, newDex, 32, 4); } // public static void main(String[] args) throws Exception { // ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer(); // byteBuf.writeInt(241241143); // byte[] a = new byte[4]; // byteBuf.markReaderIndex(); // byteBuf.readBytes(a); // byteBuf.resetReaderIndex(); // // System.out.println(Arrays.toString(a)); // System.out.println(Arrays.toString(int2Bytes(241241143))); // System.out.println(Arrays.toString(intToBytes(241241143))); // } }
import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.util.Enumeration; import java.util.zip.CRC32; import java.util.zip.CheckedOutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; /** * Created by xiang on 2017/5/17. */ public class Zip { public static void unZip(File zip, File dir) { try { dir.delete(); ZipFile zipFile = new ZipFile(zip); Enumeration<? extends ZipEntry> entries = zipFile.entries(); while (entries.hasMoreElements()) { ZipEntry zipEntry = entries.nextElement(); String name = zipEntry.getName(); if (name.equals("META-INF/CERT.RSA") || name.equals("META-INF/CERT.SF") || name .equals("META-INF/MANIFEST.MF")) { continue; } if (!zipEntry.isDirectory()) { File file = new File(dir, name); if (!file.getParentFile().exists()) file.getParentFile().mkdirs(); FileOutputStream fos = new FileOutputStream(file); InputStream is = zipFile.getInputStream(zipEntry); byte[] buffer = new byte[1024]; int len; while ((len = is.read(buffer)) != -1) { fos.write(buffer, 0, len); } is.close(); fos.close(); } } zipFile.close(); } catch (Exception e) { e.printStackTrace(); } } public static void zip(File dir, File zip) throws Exception { zip.delete(); // 对输出文件做CRC32校验 CheckedOutputStream cos = new CheckedOutputStream(new FileOutputStream( zip), new CRC32()); ZipOutputStream zos = new ZipOutputStream(cos); compress(dir, zos, ""); zos.flush(); zos.close(); } private static void compress(File srcFile, ZipOutputStream zos, String basePath) throws Exception { if (srcFile.isDirectory()) { compressDir(srcFile, zos, basePath); } else { compressFile(srcFile, zos, basePath); } } private static void compressDir(File dir, ZipOutputStream zos, String basePath) throws Exception { File[] files = dir.listFiles(); // 构建空目录 if (files.length < 1) { ZipEntry entry = new ZipEntry(basePath + dir.getName() + "/"); zos.putNextEntry(entry); zos.closeEntry(); } for (File file : files) { // 递归压缩 compress(file, zos, basePath + dir.getName() + "/"); } } private static void compressFile(File file, ZipOutputStream zos, String dir) throws Exception { String dirName = dir + file.getName(); String[] dirNameNew = dirName.split("/"); StringBuffer buffer = new StringBuffer(); if (dirNameNew.length > 1) { for (int i = 1; i < dirNameNew.length; i++) { buffer.append("/"); buffer.append(dirNameNew[i]); } } else { buffer.append("/"); } ZipEntry entry = new ZipEntry(buffer.toString().substring(1)); zos.putNextEntry(entry); BufferedInputStream bis = new BufferedInputStream(new FileInputStream( file)); int count; byte data[] = new byte[1024]; while ((count = bis.read(data, 0, 1024)) != -1) { zos.write(data, 0, count); } bis.close(); zos.closeEntry(); } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.protectapp"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:name="com.example.mylibrary.ShellApplication" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
package com.example.protectapp;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
package com.example.mylibrary; import android.app.Application; import android.content.Context; import android.os.Build; import android.util.Log; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.RandomAccessFile; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; /** * @author 享学课堂 Alvin * @package com.xiangxue.alvin.applibrary * @fileName ShellApplication * @date on 2019/4/21 * @qq 2464061231 **/ public class ShellApplication extends Application { private static final String TAG = "ShellApplication"; public static String getPassword(){ 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 Field findField(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 Method findMethod(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<File> 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<File> files, File optimizedDirectory, ArrayList<IOException> 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<File> files, File optimizedDirectory, ArrayList<IOException> 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; } }
package com.example.mylibrary; import java.io.File; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.SecretKeySpec; /** * Created by xiang on 16/6/8. */ public class AES { public static final String DEFAULT_PWD = "abcdefghijklmnop"; private static final String algorithmStr = "AES/ECB/PKCS5Padding"; private static Cipher encryptCipher; private static Cipher decryptCipher; public static void init(String password) { try { // 生成一个实现指定转换的 Cipher 对象。 encryptCipher = Cipher.getInstance(algorithmStr); decryptCipher = Cipher.getInstance(algorithmStr);// algorithmStr byte[] keyStr = password.getBytes(); SecretKeySpec key = new SecretKeySpec(keyStr, "AES"); encryptCipher.init(Cipher.ENCRYPT_MODE, key); decryptCipher.init(Cipher.DECRYPT_MODE, key); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } } public static byte[] encrypt(byte[] content) { try { byte[] result = encryptCipher.doFinal(content); return result; } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } return null; } public static byte[] decrypt(byte[] content) { try { byte[] result = decryptCipher.doFinal(content); return result; } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } return null; } public static void main(String[] args) throws Exception { File zip = new File("/Users/xiang/develop/app-debug.apk"); String absolutePath = zip.getAbsolutePath(); File dir = new File(absolutePath.substring(0, absolutePath.lastIndexOf("."))); Zip.unZip(zip,dir); File zip2 = new File("/Users/xiang/develop/app-debug2.apk"); Zip.zip(dir,zip2); String[] argv = { "jarsigner","-verbose", "-sigalg", "MD5withRSA", "-digestalg", "SHA1", "-keystore", "/Users/xiang/develop/debug.keystore", "-storepass","android", "-keypass", "android", "-signedjar", "/Users/xiang/develop/app-debug2-sign.apk", "/Users/xiang/develop/app-debug2.apk", "androiddebugkey" }; Process pro = null; try { pro = Runtime.getRuntime().exec(argv); //destroy the stream try { pro.waitFor(); } catch (InterruptedException e) { e.printStackTrace(); } } finally { if (pro != null) { pro.destroy(); } } } }
package com.example.mylibrary; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; /** * Created by xiang on 16/5/11. */ public final class Base64 { private static final char[] legalChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" .toCharArray(); public static String encode(byte[] data) { int start = 0; int len = data.length; StringBuffer buf = new StringBuffer(data.length * 3 / 2); int end = len - 3; int i = start; int n = 0; while (i <= end) { int d = ((((int) data[i]) & 0x0ff) << 16) | ((((int) data[i + 1]) & 0x0ff) << 8) | (((int) data[i + 2]) & 0x0ff); buf.append(legalChars[(d >> 18) & 63]); buf.append(legalChars[(d >> 12) & 63]); buf.append(legalChars[(d >> 6) & 63]); buf.append(legalChars[d & 63]); i += 3; if (n++ >= 14) { n = 0; buf.append(" "); } } if (i == start + len - 2) { int d = ((((int) data[i]) & 0x0ff) << 16) | ((((int) data[i + 1]) & 255) << 8); buf.append(legalChars[(d >> 18) & 63]); buf.append(legalChars[(d >> 12) & 63]); buf.append(legalChars[(d >> 6) & 63]); buf.append("="); } else if (i == start + len - 1) { int d = (((int) data[i]) & 0x0ff) << 16; buf.append(legalChars[(d >> 18) & 63]); buf.append(legalChars[(d >> 12) & 63]); buf.append("=="); } return buf.toString(); } private static int decode(char c) { if (c >= 'A' && c <= 'Z') return ((int) c) - 65; else if (c >= 'a' && c <= 'z') return ((int) c) - 97 + 26; else if (c >= '0' && c <= '9') return ((int) c) - 48 + 26 + 26; else switch (c) { case '+': return 62; case '/': return 63; case '=': return 0; default: throw new RuntimeException("unexpected code: " + c); } } /** * Decodes the given Base64 encoded String to a new byte array. The byte * array holding the decoded data is returned. */ public static byte[] decode(String s) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { decode(s, bos); } catch (IOException e) { throw new RuntimeException(); } byte[] decodedBytes = bos.toByteArray(); try { bos.close(); bos = null; } catch (IOException ex) { System.err.println("Error while decoding BASE64: " + ex.toString()); } return decodedBytes; } private static void decode(String s, OutputStream os) throws IOException { int i = 0; int len = s.length(); while (true) { while (i < len && s.charAt(i) <= ' ') i++; if (i == len) break; int tri = (decode(s.charAt(i)) << 18) + (decode(s.charAt(i + 1)) << 12) + (decode(s.charAt(i + 2)) << 6) + (decode(s.charAt(i + 3))); os.write((tri >> 16) & 255); if (s.charAt(i + 2) == '=') break; os.write((tri >> 8) & 255); if (s.charAt(i + 3) == '=') break; os.write(tri & 255); i += 4; } } }
package com.example.mylibrary; /** * Created by xiang on 2017/5/17. */ public class Utils { // public static byte[] int2Bytes(int number) { // byte[] b = new byte[4]; // for (int i = 3; i >= 0; i--) { // b[i] = (byte) (number % 256); // number >>= 8; // } // return b; // } public static byte[] int2Bytes(int value) { byte[] src = new byte[4]; src[3] = (byte) ((value >> 24) & 0xFF); src[2] = (byte) ((value >> 16) & 0xFF); src[1] = (byte) ((value >> 8) & 0xFF); src[0] = (byte) (value & 0xFF); return src; } public static int bytes2Int(byte[] src) { int value; value = (int) ((src[0] & 0xFF) | ((src[1] & 0xFF)<<8) | ((src[2] & 0xFF)<<16) | ((src[3] & 0xFF)<<24)); return value; } public static void main(String[] args) throws Exception { // ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer(); // byteBuf.writeInt(241241143); // byte[] a = new byte[4]; // byteBuf.markReaderIndex(); // byteBuf.readBytes(a); // byteBuf.resetReaderIndex(); // // System.out.println(Arrays.toString(a)); // System.out.println(Arrays.toString(int2Bytes(241241143))); // System.out.println(Arrays.toString(intToBytes(241241143))); } }
package com.example.mylibrary; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.util.Enumeration; import java.util.zip.CRC32; import java.util.zip.CheckedOutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; /** * Created by xiang on 2017/5/17. */ public class Zip { public static void unZip(File zip, File dir) { try { dir.delete(); ZipFile zipFile = new ZipFile(zip); Enumeration<? extends ZipEntry> entries = zipFile.entries(); while (entries.hasMoreElements()) { ZipEntry zipEntry = entries.nextElement(); String name = zipEntry.getName(); if (name.equals("META-INF/CERT.RSA") || name.equals("META-INF/CERT.SF") || name .equals("META-INF/MANIFEST.MF")) { continue; } if (!zipEntry.isDirectory()) { File file = new File(dir, name); if (!file.getParentFile().exists()) file.getParentFile().mkdirs(); FileOutputStream fos = new FileOutputStream(file); InputStream is = zipFile.getInputStream(zipEntry); byte[] buffer = new byte[1024]; int len; while ((len = is.read(buffer)) != -1) { fos.write(buffer, 0, len); } is.close(); fos.close(); } } zipFile.close(); } catch (Exception e) { e.printStackTrace(); } } public static void zip(File dir, File zip) throws Exception { zip.delete(); // 对输出文件做CRC32校验 CheckedOutputStream cos = new CheckedOutputStream(new FileOutputStream( zip), new CRC32()); ZipOutputStream zos = new ZipOutputStream(cos); compress(dir, zos, ""); zos.flush(); zos.close(); } private static void compress(File srcFile, ZipOutputStream zos, String basePath) throws Exception { if (srcFile.isDirectory()) { compressDir(srcFile, zos, basePath); } else { compressFile(srcFile, zos, basePath); } } private static void compressDir(File dir, ZipOutputStream zos, String basePath) throws Exception { File[] files = dir.listFiles(); // 构建空目录 if (files.length < 1) { ZipEntry entry = new ZipEntry(basePath + dir.getName() + "/"); zos.putNextEntry(entry); zos.closeEntry(); } for (File file : files) { // 递归压缩 compress(file, zos, basePath + dir.getName() + "/"); } } private static void compressFile(File file, ZipOutputStream zos, String dir) throws Exception { String dirName = dir + file.getName(); String[] dirNameNew = dirName.split("/"); StringBuffer buffer = new StringBuffer(); if (dirNameNew.length > 1) { for (int i = 1; i < dirNameNew.length; i++) { buffer.append("/"); buffer.append(dirNameNew[i]); } } else { buffer.append("/"); } ZipEntry entry = new ZipEntry(buffer.toString().substring(1)); zos.putNextEntry(entry); BufferedInputStream bis = new BufferedInputStream(new FileInputStream( file)); int count; byte data[] = new byte[1024]; while ((count = bis.read(data, 0, 1024)) != -1) { zos.write(data, 0, count); } bis.close(); zos.closeEntry(); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。