support Avoiding package siganture veriication
This commit is contained in:
parent
0d62107b36
commit
bf9db1ee30
Binary file not shown.
|
|
@ -3,6 +3,7 @@ package com.storm.wind.xpatch;
|
|||
import com.storm.wind.xpatch.base.BaseCommand;
|
||||
import com.storm.wind.xpatch.task.ApkModifyTask;
|
||||
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.util.FileUtils;
|
||||
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")
|
||||
private boolean showAllLogs = false;
|
||||
|
||||
@Opt(opt = "c", longOpt = "crach", hasArg = false,
|
||||
description = "disable craching the apk's signature.")
|
||||
private boolean disableCrackSignature = false;
|
||||
|
||||
// 原来apk中dex文件的数量
|
||||
private int dexFileCount = 0;
|
||||
|
||||
|
|
@ -93,12 +98,14 @@ public class MainCommand extends BaseCommand {
|
|||
return;
|
||||
}
|
||||
|
||||
System.out.println(" !!!!! output apk path --> " + output);
|
||||
System.out.println(" !!!!! output apk path --> " + output +
|
||||
" disableCrackSignature --> " + disableCrackSignature);
|
||||
|
||||
String apkFileName = getBaseName(srcApkFile);
|
||||
|
||||
// 中间文件临时存储的位置
|
||||
String tempFilePath = srcApkFileParentPath + File.separator + currentTimeStr() + "-tmp" + File.separator;
|
||||
String tempFilePath = srcApkFileParentPath + File.separator +
|
||||
currentTimeStr() + "-tmp" + File.separator;
|
||||
|
||||
// apk文件解压的目录
|
||||
unzipApkFilePath = tempFilePath + apkFileName + "-" + UNZIP_APK_FILE_NAME + File.separator;
|
||||
|
|
@ -108,6 +115,11 @@ public class MainCommand extends BaseCommand {
|
|||
"\n unzipApkFilePath = " + unzipApkFilePath);
|
||||
}
|
||||
|
||||
if (!disableCrackSignature) {
|
||||
// save the apk original signature info, to support crach signature.
|
||||
new SaveApkSignatureTask(apkPath, unzipApkFilePath).run();
|
||||
}
|
||||
|
||||
// 先解压apk到指定目录下
|
||||
FileUtils.decompressZip(apkPath, unzipApkFilePath);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.storm.wind.xpatch.util;
|
|||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
|
@ -9,6 +10,7 @@ import java.io.FileOutputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Enumeration;
|
||||
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) {
|
||||
try {
|
||||
if (closeable != null) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue