CrackMe.apk
Download file
package com.facebook.soloader;
import android.content.Context;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.Arrays;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.annotation.Nullable;
public final class NativeDepsUnpacker {
private static final String APK_IDENTIFIER_FILE_NAME = "apk_id";
private static final String LOCK_FILE_NAME = "lock";
private static final String NATIVE_DEPS_DIR_NAME = "native_deps";
private static final String NATIVE_DEPS_FILE_APK_PATH = "assets/native_deps.txt";
private static final String NATIVE_DEPS_FILE_NAME = "deps";
private static final byte STATE_CLEAN = 1;
private static final byte STATE_DIRTY = 0;
private static final String STATE_FILE_NAME = "state";
private NativeDepsUnpacker() {
}
public static File getNativeDepsFilePath(Context context) {
return new File(getNativeDepsDir(context), NATIVE_DEPS_FILE_NAME);
}
public static File getNativeDepsDir(Context context) {
return new File(context.getApplicationInfo().dataDir, NATIVE_DEPS_DIR_NAME);
}
public static void ensureNativeDepsAvailable(Context context) throws IOException {
File nativeDepsDir = getNativeDepsDir(context);
if (ensureDirExists(nativeDepsDir)) {
FileLocker orCreateLockOnDir = SysUtil.getOrCreateLockOnDir(nativeDepsDir, new File(nativeDepsDir, LOCK_FILE_NAME), true);
try {
byte readState = readState(nativeDepsDir);
if (readState == 1 && apkChanged(context, nativeDepsDir)) {
readState = 0;
}
if (readState != 1) {
writeState(nativeDepsDir, (byte) 0);
extractNativeDeps(context);
writeApkIdentifier(context, nativeDepsDir);
SysUtil.fsyncRecursive(nativeDepsDir);
writeState(nativeDepsDir, (byte) 1);
if (orCreateLockOnDir != null) {
orCreateLockOnDir.close();
return;
}
return;
} else if (orCreateLockOnDir != null) {
orCreateLockOnDir.close();
return;
} else {
return;
}
} catch (Throwable th) {
th.addSuppressed(th);
}
} else {
return;
}
throw th;
}
private static boolean ensureDirExists(File file) {
if (file.exists() && !file.isDirectory()) {
file.delete();
}
if (!file.exists()) {
file.mkdir();
}
return file.isDirectory();
}
private static byte[] getApkIdentifier(Context context) throws IOException {
return SysUtil.makeApkDepBlock(new File(context.getApplicationInfo().sourceDir), context);
}
static byte[] readAllBytes(InputStream inputStream, int i) throws IOException {
byte[] bArr = new byte[i];
int i2 = 0;
while (i2 < i) {
int read = inputStream.read(bArr, i2, i - i2);
if (read != -1) {
i2 += read;
if (i2 > i) {
throw new IllegalStateException("Read more bytes than expected");
}
} else {
throw new EOFException("EOF found unexpectedly");
}
}
return bArr;
}
static byte[] readNativeDepsFromDisk(Context context) throws IOException {
File nativeDepsFilePath = getNativeDepsFilePath(context);
FileInputStream fileInputStream = new FileInputStream(nativeDepsFilePath);
try {
byte[] readAllBytes = readAllBytes(fileInputStream, (int) nativeDepsFilePath.length());
fileInputStream.close();
return readAllBytes;
} catch (Throwable th) {
th.addSuppressed(th);
}
throw th;
}
static byte[] readNativeDepsFromApk(Context context) throws IOException {
InputStream inputStream;
ZipFile zipFile = new ZipFile(new File(context.getApplicationInfo().sourceDir));
try {
ZipEntry entry = zipFile.getEntry(NATIVE_DEPS_FILE_APK_PATH);
if (entry != null) {
inputStream = zipFile.getInputStream(entry);
if (inputStream != null) {
byte[] readAllBytes = readAllBytes(inputStream, (int) entry.getSize());
if (inputStream != null) {
inputStream.close();
}
zipFile.close();
return readAllBytes;
}
throw new FileNotFoundException("Failed to read native_deps file from APK");
}
throw new FileNotFoundException("Could not find native_deps file in APK");
} catch (Throwable th) {
try {
zipFile.close();
} catch (Throwable th2) {
th.addSuppressed(th2);
}
throw th;
}
throw th;
}
private static void extractNativeDeps(Context context) throws IOException {
byte[] readNativeDepsFromApk = readNativeDepsFromApk(context);
byte[] apkIdentifier = getApkIdentifier(context);
int length = readNativeDepsFromApk.length;
RandomAccessFile randomAccessFile = new RandomAccessFile(getNativeDepsFilePath(context), "rw");
try {
randomAccessFile.write(apkIdentifier);
randomAccessFile.writeInt(length);
randomAccessFile.write(readNativeDepsFromApk);
randomAccessFile.setLength(randomAccessFile.getFilePointer());
randomAccessFile.close();
return;
} catch (Throwable th) {
th.addSuppressed(th);
}
throw th;
}
private static void writeApkIdentifier(Context context, File file) throws IOException {
File file2 = new File(file, APK_IDENTIFIER_FILE_NAME);
byte[] apkIdentifier = getApkIdentifier(context);
RandomAccessFile randomAccessFile = new RandomAccessFile(file2, "rw");
try {
randomAccessFile.write(apkIdentifier);
randomAccessFile.setLength(randomAccessFile.getFilePointer());
randomAccessFile.close();
return;
} catch (Throwable th) {
th.addSuppressed(th);
}
throw th;
}
private static void writeState(File file, byte b) throws IOException {
RandomAccessFile randomAccessFile = new RandomAccessFile(new File(file, STATE_FILE_NAME), "rw");
try {
randomAccessFile.seek(0);
randomAccessFile.write(b);
randomAccessFile.setLength(randomAccessFile.getFilePointer());
randomAccessFile.getFD().sync();
randomAccessFile.close();
return;
} catch (Throwable th) {
th.addSuppressed(th);
}
throw th;
}
private static byte readState(File file) throws IOException {
RandomAccessFile randomAccessFile = new RandomAccessFile(new File(file, STATE_FILE_NAME), "rw");
byte b = 0;
try {
byte readByte = randomAccessFile.readByte();
if (readByte == 1) {
b = readByte;
}
} catch (EOFException unused) {
} catch (Throwable th) {
th.addSuppressed(th);
}
randomAccessFile.close();
return b;
throw th;
}
@Nullable
private static byte[] getExistingApkIdentifier(Context context, File file) throws IOException {
RandomAccessFile randomAccessFile = new RandomAccessFile(new File(file, APK_IDENTIFIER_FILE_NAME), "rw");
try {
int length = (int) randomAccessFile.length();
byte[] bArr = new byte[length];
if (randomAccessFile.read(bArr) != length) {
randomAccessFile.close();
return null;
}
randomAccessFile.close();
return bArr;
} catch (Throwable th) {
th.addSuppressed(th);
}
throw th;
}
private static boolean apkChanged(Context context, File file) throws IOException {
byte[] existingApkIdentifier = getExistingApkIdentifier(context, file);
byte[] apkIdentifier = getApkIdentifier(context);
if (existingApkIdentifier == null || apkIdentifier == null || existingApkIdentifier.length != apkIdentifier.length) {
return true;
}
return !Arrays.equals(existingApkIdentifier, apkIdentifier);
}
}
Download file