support Avoiding package siganture veriication

This commit is contained in:
Windy 2019-04-14 22:52:59 +08:00
parent 0d62107b36
commit bf9db1ee30
5 changed files with 168 additions and 2 deletions

Binary file not shown.

View File

@ -3,6 +3,7 @@ package com.storm.wind.xpatch;
import com.storm.wind.xpatch.base.BaseCommand; import com.storm.wind.xpatch.base.BaseCommand;
import com.storm.wind.xpatch.task.ApkModifyTask; import com.storm.wind.xpatch.task.ApkModifyTask;
import com.storm.wind.xpatch.task.BuildAndSignApkTask; import com.storm.wind.xpatch.task.BuildAndSignApkTask;
import com.storm.wind.xpatch.task.SaveApkSignatureTask;
import com.storm.wind.xpatch.task.SoAndDexCopyTask; import com.storm.wind.xpatch.task.SoAndDexCopyTask;
import com.storm.wind.xpatch.util.FileUtils; import com.storm.wind.xpatch.util.FileUtils;
import com.storm.wind.xpatch.util.ManifestParser; import com.storm.wind.xpatch.util.ManifestParser;
@ -34,6 +35,10 @@ public class MainCommand extends BaseCommand {
@Opt(opt = "l", longOpt = "log", hasArg = false, description = "show all the debug logs") @Opt(opt = "l", longOpt = "log", hasArg = false, description = "show all the debug logs")
private boolean showAllLogs = false; private boolean showAllLogs = false;
@Opt(opt = "c", longOpt = "crach", hasArg = false,
description = "disable craching the apk's signature.")
private boolean disableCrackSignature = false;
// 原来apk中dex文件的数量 // 原来apk中dex文件的数量
private int dexFileCount = 0; private int dexFileCount = 0;
@ -93,12 +98,14 @@ public class MainCommand extends BaseCommand {
return; return;
} }
System.out.println(" !!!!! output apk path --> " + output); System.out.println(" !!!!! output apk path --> " + output +
" disableCrackSignature --> " + disableCrackSignature);
String apkFileName = getBaseName(srcApkFile); String apkFileName = getBaseName(srcApkFile);
// 中间文件临时存储的位置 // 中间文件临时存储的位置
String tempFilePath = srcApkFileParentPath + File.separator + currentTimeStr() + "-tmp" + File.separator; String tempFilePath = srcApkFileParentPath + File.separator +
currentTimeStr() + "-tmp" + File.separator;
// apk文件解压的目录 // apk文件解压的目录
unzipApkFilePath = tempFilePath + apkFileName + "-" + UNZIP_APK_FILE_NAME + File.separator; unzipApkFilePath = tempFilePath + apkFileName + "-" + UNZIP_APK_FILE_NAME + File.separator;
@ -108,6 +115,11 @@ public class MainCommand extends BaseCommand {
"\n unzipApkFilePath = " + unzipApkFilePath); "\n unzipApkFilePath = " + unzipApkFilePath);
} }
if (!disableCrackSignature) {
// save the apk original signature info, to support crach signature.
new SaveApkSignatureTask(apkPath, unzipApkFilePath).run();
}
// 先解压apk到指定目录下 // 先解压apk到指定目录下
FileUtils.decompressZip(apkPath, unzipApkFilePath); FileUtils.decompressZip(apkPath, unzipApkFilePath);

View File

@ -0,0 +1,41 @@
package com.storm.wind.xpatch.task;
import com.storm.wind.xpatch.util.ApkSignatureHelper;
import com.storm.wind.xpatch.util.FileUtils;
import java.io.File;
/**
* Created by Wind
*/
public class SaveApkSignatureTask implements Runnable {
private String apkPath;
private String dstFilePath;
private final static String SIGNATURE_INFO_ASSET_PATH = "assets/xpatch_asset/original_signature_info.ini";
public SaveApkSignatureTask(String apkPath, String unzipApkFilePath) {
this.apkPath = apkPath;
this.dstFilePath = (unzipApkFilePath + SIGNATURE_INFO_ASSET_PATH).replace("/", File.separator);
}
@Override
public void run() {
// First, get the original signature
String originalSignature = ApkSignatureHelper.getApkSignInfo(apkPath);
if (originalSignature == null || originalSignature.isEmpty()) {
System.out.println(" Get original signature failed !!!!");
return;
}
// Then, save the signature chars to the asset file
File file = new File(dstFilePath);
File fileParent = file.getParentFile();
if (!fileParent.exists()) {
fileParent.mkdirs();
}
FileUtils.writeFile(dstFilePath, originalSignature);
}
}

View File

@ -0,0 +1,82 @@
package com.storm.wind.xpatch.util;
import java.io.InputStream;
import java.security.cert.Certificate;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* Created by Wind
*/
public class ApkSignatureHelper {
private static char[] toChars(byte[] mSignature) {
byte[] sig = mSignature;
final int N = sig.length;
final int N2 = N * 2;
char[] text = new char[N2];
for (int j = 0; j < N; j++) {
byte v = sig[j];
int d = (v >> 4) & 0xf;
text[j * 2] = (char) (d >= 10 ? ('a' + d - 10) : ('0' + d));
d = v & 0xf;
text[j * 2 + 1] = (char) (d >= 10 ? ('a' + d - 10) : ('0' + d));
}
return text;
}
private static Certificate[] loadCertificates(JarFile jarFile, JarEntry je, byte[] readBuffer) {
try {
InputStream is = jarFile.getInputStream(je);
while (is.read(readBuffer, 0, readBuffer.length) != -1) {
}
is.close();
return (Certificate[]) (je != null ? je.getCertificates() : null);
} catch (Exception e) {
}
return null;
}
public static String getApkSignInfo(String apkFilePath) {
byte[] readBuffer = new byte[8192];
Certificate[] certs = null;
try {
JarFile jarFile = new JarFile(apkFilePath);
Enumeration<?> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry je = (JarEntry) entries.nextElement();
if (je.isDirectory()) {
continue;
}
if (je.getName().startsWith("META-INF/")) {
continue;
}
Certificate[] localCerts = loadCertificates(jarFile, je, readBuffer);
if (certs == null) {
certs = localCerts;
} else {
for (int i = 0; i < certs.length; i++) {
boolean found = false;
for (int j = 0; j < localCerts.length; j++) {
if (certs[i] != null && certs[i].equals(localCerts[j])) {
found = true;
break;
}
}
if (!found || certs.length != localCerts.length) {
jarFile.close();
return null;
}
}
}
}
jarFile.close();
System.out.println(" getApkSignInfo result --> " + certs[0]);
return new String(toChars(certs[0].getEncoded()));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

View File

@ -2,6 +2,7 @@ package com.storm.wind.xpatch.util;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.Closeable; import java.io.Closeable;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -9,6 +10,7 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.zip.CRC32; import java.util.zip.CRC32;
@ -205,6 +207,35 @@ public class FileUtils {
} }
} }
public static void writeFile(String filePath, String content) {
if (filePath == null || filePath.isEmpty()) {
return;
}
if (content == null || content.isEmpty()) {
return;
}
File dstFile = new File(filePath);
if (!dstFile.getParentFile().exists()) {
dstFile.getParentFile().mkdirs();
}
FileOutputStream outputStream = null;
BufferedWriter writer = null;
try {
outputStream = new FileOutputStream(dstFile);
writer = new BufferedWriter(new OutputStreamWriter(outputStream));
writer.write(content);
writer.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
close(outputStream);
close(writer);
}
}
private static void close(Closeable closeable) { private static void close(Closeable closeable) {
try { try {
if (closeable != null) { if (closeable != null) {