Dump调度优化

pull/1/head
Milk 4 years ago
parent 6bd50258cf
commit b1a4ad20fe
  1. 11
      Bcore/src/main/aidl/top/niunaijun/blackbox/core/system/dump/IBDumpManagerService.aidl
  2. 7
      Bcore/src/main/aidl/top/niunaijun/blackbox/core/system/dump/IBDumpMonitor.aidl
  3. 3
      Bcore/src/main/aidl/top/niunaijun/blackbox/entity/dump/DumpResult.aidl
  4. 22
      Bcore/src/main/java/top/niunaijun/blackbox/BlackBoxCore.java
  5. 61
      Bcore/src/main/java/top/niunaijun/blackbox/BlackDexCore.java
  6. 15
      Bcore/src/main/java/top/niunaijun/blackbox/app/BActivityThread.java
  7. 8
      Bcore/src/main/java/top/niunaijun/blackbox/app/configuration/ClientConfiguration.java
  8. 4
      Bcore/src/main/java/top/niunaijun/blackbox/core/system/ServiceManager.java
  9. 56
      Bcore/src/main/java/top/niunaijun/blackbox/core/system/dump/BDumpManagerService.java
  10. 2
      Bcore/src/main/java/top/niunaijun/blackbox/core/system/pm/BPackageManagerService.java
  11. 82
      Bcore/src/main/java/top/niunaijun/blackbox/entity/dump/DumpResult.java
  12. 60
      Bcore/src/main/java/top/niunaijun/blackbox/fake/frameworks/BDumpManager.java
  13. 2
      Bcore/src/main/java/top/niunaijun/blackbox/proxy/ProxyActivity.java
  14. 14
      Bcore/src/main/java/top/niunaijun/blackbox/utils/NativeUtils.java
  15. 17
      Bcore/src/main/jni/DexDump.cpp
  16. 11
      app/src/main/java/top/niunaijun/blackdex/App.java
  17. 30
      app/src/main/java/top/niunaijun/blackdex/MainActivity.java

@ -0,0 +1,11 @@
// IBDumpService.aidl
package top.niunaijun.blackbox.core.system.dump;
import android.os.IBinder;
import top.niunaijun.blackbox.entity.dump.DumpResult;
interface IBDumpManagerService {
void registerMonitor(IBinder monitor);
void unregisterMonitor(IBinder monitor);
void noticeMonitor(in DumpResult result);
}

@ -0,0 +1,7 @@
package top.niunaijun.blackbox.core.system.dump;
import top.niunaijun.blackbox.entity.dump.DumpResult;
interface IBDumpMonitor {
void onDump(in DumpResult result);
}

@ -0,0 +1,3 @@
package top.niunaijun.blackbox.entity.dump;
parcelable DumpResult;

@ -14,6 +14,7 @@ import android.os.IBinder;
import android.os.Process;
import top.niunaijun.blackbox.app.configuration.ClientConfiguration;
import top.niunaijun.blackbox.fake.frameworks.BDumpManager;
import top.niunaijun.blackbox.proxy.ProxyManifest;
import top.niunaijun.blackbox.app.configuration.AppLifecycleCallback;
import top.niunaijun.blackbox.fake.hook.HookManager;
@ -118,6 +119,7 @@ public class BlackBoxCore extends ClientConfiguration {
get().getService(ServiceManager.ACTIVITY_MANAGER);
get().getService(ServiceManager.PACKAGE_MANAGER);
get().getService(ServiceManager.STORAGE_MANAGER);
get().getService(ServiceManager.DUMP_MANAGER);
}
public static Object mainThread() {
@ -140,25 +142,11 @@ public class BlackBoxCore extends ClientConfiguration {
return BStorageManager.get();
}
public boolean dumpDex(String packageName) {
InstallResult installResult = installPackage(packageName);
if (installResult.success) {
return launchApk(packageName);
} else {
return false;
}
}
public boolean dumpDex(File file) {
InstallResult installResult = installPackage(file);
if (installResult.success) {
return launchApk(installResult.packageName);
} else {
return false;
}
public static BDumpManager getBDumpManager() {
return BDumpManager.get();
}
private boolean launchApk(String packageName) {
public boolean launchApk(String packageName) {
Intent launchIntentForPackage = getBPackageManager().getLaunchIntentForPackage(packageName, USER_ID);
if (launchIntentForPackage == null) {
return false;

@ -0,0 +1,61 @@
package top.niunaijun.blackbox;
import android.content.Context;
import java.io.File;
import top.niunaijun.blackbox.app.configuration.ClientConfiguration;
import top.niunaijun.blackbox.core.system.dump.IBDumpMonitor;
import top.niunaijun.blackbox.entity.pm.InstallResult;
/**
* Created by Milk on 2021/5/22.
* * _
* (`ω
*  つ0
* しーJ
* 此处无Bug
*/
public class BlackDexCore {
public static final String TAG = "BlackBoxCore";
private static final BlackDexCore sBlackDexCore = new BlackDexCore();
public static BlackDexCore get() {
return sBlackDexCore;
}
public void doAttachBaseContext(Context context, ClientConfiguration clientConfiguration) {
BlackBoxCore.get().doAttachBaseContext(context, clientConfiguration);
}
public void doCreate() {
BlackBoxCore.get().doCreate();
}
public boolean dumpDex(String packageName) {
InstallResult installResult = BlackBoxCore.get().installPackage(packageName);
if (installResult.success) {
return BlackBoxCore.get().launchApk(packageName);
} else {
return false;
}
}
public boolean dumpDex(File file) {
InstallResult installResult = BlackBoxCore.get().installPackage(file);
if (installResult.success) {
return BlackBoxCore.get().launchApk(installResult.packageName);
} else {
return false;
}
}
public void registerDumpMonitor(IBDumpMonitor monitor) {
BlackBoxCore.getBDumpManager().registerMonitor(monitor.asBinder());
}
public void unregisterDumpMonitor(IBDumpMonitor monitor) {
BlackBoxCore.getBDumpManager().unregisterMonitor(monitor.asBinder());
}
}

@ -13,7 +13,9 @@ import android.os.ConditionVariable;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Process;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -26,6 +28,7 @@ import top.niunaijun.blackbox.core.IBActivityThread;
import top.niunaijun.blackbox.core.VMCore;
import top.niunaijun.blackbox.entity.AppConfig;
import top.niunaijun.blackbox.core.IOCore;
import top.niunaijun.blackbox.entity.dump.DumpResult;
import top.niunaijun.blackbox.utils.Slog;
import top.niunaijun.blackbox.utils.compat.ContextCompat;
import top.niunaijun.blackbox.BlackBoxCore;
@ -122,6 +125,9 @@ public class BActivityThread extends IBActivityThread.Stub {
}
public void bindApplication(final String packageName, final String processName) {
if (mAppConfig == null) {
return;
}
if (Looper.myLooper() != Looper.getMainLooper()) {
final ConditionVariable conditionVariable = new ConditionVariable();
new Handler(Looper.getMainLooper()).post(() -> {
@ -135,6 +141,10 @@ public class BActivityThread extends IBActivityThread.Stub {
}
public synchronized void handleBindApplication(String packageName, String processName) {
DumpResult result = new DumpResult();
result.packageName = packageName;
result.dir = new File(BlackBoxCore.get().getDexDumpDir(), packageName).getAbsolutePath();
try {
PackageInfo packageInfo = BlackBoxCore.getBPackageManager().getPackageInfo(packageName, PackageManager.GET_PROVIDERS, BActivityThread.getUserId());
if (packageInfo == null)
return;
@ -173,7 +183,7 @@ public class BActivityThread extends IBActivityThread.Stub {
Application application = null;
BlackBoxCore.get().getAppLifecycleCallback().beforeCreateApplication(packageName, processName, packageContext);
try {
try {
application = LoadedApk.makeApplication.call(loadedApk, false, null);
} catch (Throwable e) {
@ -192,7 +202,10 @@ public class BActivityThread extends IBActivityThread.Stub {
}
} catch (Throwable e) {
e.printStackTrace();
result.dumpError(e.getMessage());
} finally {
mAppConfig = null;
BlackBoxCore.getBDumpManager().noticeMonitor(result);
BlackBoxCore.get().uninstallPackage(packageName);
}
}

@ -1,8 +1,6 @@
package top.niunaijun.blackbox.app.configuration;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import top.niunaijun.blackbox.BlackBoxCore;
import top.niunaijun.blackbox.utils.FileUtils;
@ -16,16 +14,16 @@ import top.niunaijun.blackbox.utils.FileUtils;
* 此处无Bug
*/
public abstract class ClientConfiguration {
private File mExternalFilesDir;
private File mExternalDir;
public final void init() {
mExternalFilesDir = BlackBoxCore.getContext().getExternalCacheDir().getParentFile();
mExternalDir = BlackBoxCore.getContext().getExternalCacheDir().getParentFile();
}
public abstract String getHostPackageName();
public String getDexDumpDir() {
File dump = new File(mExternalFilesDir, "dump");
File dump = new File(mExternalDir, "dump");
FileUtils.mkdirs(dump);
return dump.getAbsolutePath();
}

@ -6,6 +6,7 @@ import java.util.HashMap;
import java.util.Map;
import top.niunaijun.blackbox.core.system.am.BActivityManagerService;
import top.niunaijun.blackbox.core.system.dump.BDumpManagerService;
import top.niunaijun.blackbox.core.system.os.BStorageManagerService;
import top.niunaijun.blackbox.core.system.pm.BPackageManagerService;
import top.niunaijun.blackbox.core.system.user.BUserManagerService;
@ -24,7 +25,7 @@ public class ServiceManager {
public static final String PACKAGE_MANAGER = "package_manager";
public static final String STORAGE_MANAGER = "storage_manager";
public static final String USER_MANAGER = "user_manager";
public static final String Xposed_MANAGER = "Xposed_manager";
public static final String DUMP_MANAGER = "dump_manager";
private final Map<String, IBinder> mCaches = new HashMap<>();
@ -48,6 +49,7 @@ public class ServiceManager {
mCaches.put(PACKAGE_MANAGER, BPackageManagerService.get());
mCaches.put(STORAGE_MANAGER, BStorageManagerService.get());
mCaches.put(USER_MANAGER, BUserManagerService.get());
mCaches.put(DUMP_MANAGER, BDumpManagerService.get());
}
public IBinder getServiceInternal(String name) {

@ -0,0 +1,56 @@
package top.niunaijun.blackbox.core.system.dump;
import android.os.IBinder;
import android.os.RemoteException;
import java.util.ArrayList;
import java.util.List;
import top.niunaijun.blackbox.entity.dump.DumpResult;
/**
* Created by Milk on 2021/5/22.
* * _
* (`ω
*  つ0
* しーJ
* 此处无Bug
*/
public class BDumpManagerService extends IBDumpManagerService.Stub {
private static final BDumpManagerService sService = new BDumpManagerService();
private final List<IBinder> mMonitors = new ArrayList<>();
public static BDumpManagerService get() {
return sService;
}
@Override
public void registerMonitor(IBinder monitor) {
try {
monitor.linkToDeath(new DeathRecipient() {
@Override
public void binderDied() {
monitor.unlinkToDeath(this, 0);
mMonitors.remove(monitor);
}
}, 0);
} catch (RemoteException ignored) {
}
mMonitors.add(monitor);
}
@Override
public void unregisterMonitor(IBinder monitor) {
mMonitors.remove(monitor);
}
@Override
public void noticeMonitor(DumpResult result) throws RemoteException {
for (IBinder monitor : mMonitors) {
if (monitor.isBinderAlive()) {
IBDumpMonitor ibDumpMonitor = IBDumpMonitor.Stub.asInterface(monitor);
ibDumpMonitor.onDump(result);
}
}
}
}

@ -50,7 +50,7 @@ import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
* 此处无Bug
*/
public class BPackageManagerService extends IBPackageManagerService.Stub implements ISystemService {
public static final String TAG = "VPackageManagerService";
public static final String TAG = "BPackageManagerService";
public static BPackageManagerService sService = new BPackageManagerService();
private final Settings mSettings = new Settings();
private final ComponentResolver mComponentResolver;

@ -0,0 +1,82 @@
package top.niunaijun.blackbox.entity.dump;
import android.os.Parcel;
import android.os.Parcelable;
import top.niunaijun.blackbox.entity.pm.InstallResult;
import top.niunaijun.blackbox.utils.Slog;
/**
* Created by Milk on 2021/5/22.
* * _
* (`ω
*  つ0
* しーJ
* 此处无Bug
*/
public class DumpResult implements Parcelable {
public static final String TAG = "DumpResult";
public boolean success = true;
public String packageName;
public String msg;
public String dir;
public void dumpError(String msg) {
this.msg = msg;
this.success = false;
Slog.d(TAG, msg);
}
@Override
public String toString() {
return "DumpResult{" +
"success=" + success +
", packageName='" + packageName + '\'' +
", msg='" + msg + '\'' +
", dir='" + dir + '\'' +
'}';
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeByte(this.success ? (byte) 1 : (byte) 0);
dest.writeString(this.packageName);
dest.writeString(this.msg);
dest.writeString(this.dir);
}
public void readFromParcel(Parcel source) {
this.success = source.readByte() != 0;
this.packageName = source.readString();
this.msg = source.readString();
this.dir = source.readString();
}
public DumpResult() {
}
protected DumpResult(Parcel in) {
this.success = in.readByte() != 0;
this.packageName = in.readString();
this.msg = in.readString();
this.dir = in.readString();
}
public static final Creator<DumpResult> CREATOR = new Creator<DumpResult>() {
@Override
public DumpResult createFromParcel(Parcel source) {
return new DumpResult(source);
}
@Override
public DumpResult[] newArray(int size) {
return new DumpResult[size];
}
};
}

@ -0,0 +1,60 @@
package top.niunaijun.blackbox.fake.frameworks;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.storage.StorageVolume;
import top.niunaijun.blackbox.BlackBoxCore;
import top.niunaijun.blackbox.core.system.ServiceManager;
import top.niunaijun.blackbox.core.system.dump.IBDumpManagerService;
import top.niunaijun.blackbox.core.system.os.IBStorageManagerService;
import top.niunaijun.blackbox.entity.dump.DumpResult;
/**
* Created by Milk on 4/14/21.
* * _
* (`ω
*  つ0
* しーJ
* 此处无Bug
*/
public class BDumpManager {
private static final BDumpManager sDumpManager = new BDumpManager();
private IBDumpManagerService mService;
public static BDumpManager get() {
return sDumpManager;
}
public void registerMonitor(IBinder monitor) {
try {
getService().registerMonitor(monitor);
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void unregisterMonitor(IBinder monitor) {
try {
getService().unregisterMonitor(monitor);
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void noticeMonitor(DumpResult result) {
try {
getService().noticeMonitor(result);
} catch (RemoteException e) {
e.printStackTrace();
}
}
private IBDumpManagerService getService() {
if (mService != null && mService.asBinder().isBinderAlive()) {
return mService;
}
mService = IBDumpManagerService.Stub.asInterface(BlackBoxCore.get().getService(ServiceManager.DUMP_MANAGER));
return getService();
}
}

@ -2,6 +2,7 @@ package top.niunaijun.blackbox.proxy;
import android.app.Activity;
import android.os.Bundle;
import android.os.Process;
import android.util.Log;
import androidx.annotation.Nullable;
@ -26,6 +27,7 @@ public class ProxyActivity extends Activity {
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
finish();
Process.killProcess(Process.myPid());
}
public static class P0 extends ProxyActivity {

@ -38,13 +38,13 @@ public class NativeUtils {
findAndCopyNativeLib(zipfile, "armeabi", nativeLibDir);
} finally {
Log.d(TAG, "Done! +" + (System.currentTimeMillis() - startTime) + "ms");
//Log.d(TAG, "Done! +" + (System.currentTimeMillis() - startTime) + "ms");
}
}
private static boolean findAndCopyNativeLib(ZipFile zipfile, String cpuArch, File nativeLibDir) throws Exception {
Log.d(TAG, "Try to copy plugin's cup arch: " + cpuArch);
//Log.d(TAG, "Try to copy plugin's cup arch: " + cpuArch);
boolean findLib = false;
boolean findSo = false;
byte buffer[] = null;
@ -65,12 +65,12 @@ public class NativeUtils {
if (buffer == null) {
findSo = true;
Log.d(TAG, "Found plugin's cup arch dir: " + cpuArch);
//Log.d(TAG, "Found plugin's cup arch dir: " + cpuArch);
buffer = new byte[8192];
}
String libName = entryName.substring(entryName.lastIndexOf('/') + 1);
Log.d(TAG, "verify so " + libName);
//Log.d(TAG, "verify so " + libName);
// File abiDir = new File(nativeLibDir, cpuArch);
// if (!abiDir.exists()) {
// abiDir.mkdirs();
@ -78,16 +78,16 @@ public class NativeUtils {
File libFile = new File(nativeLibDir, libName);
if (libFile.exists() && libFile.length() == entry.getSize()) {
Log.d(TAG, libName + " skip copy");
//Log.d(TAG, libName + " skip copy");
continue;
}
FileOutputStream fos = new FileOutputStream(libFile);
Log.d(TAG, "copy so " + entry.getName() + " of " + cpuArch);
//Log.d(TAG, "copy so " + entry.getName() + " of " + cpuArch);
copySo(buffer, zipfile.getInputStream(entry), fos);
}
if (!findLib) {
Log.d(TAG, "Fast skip all!");
//Log.d(TAG, "Fast skip all!");
return true;
}

@ -16,8 +16,6 @@
using namespace std;
static int beginOffset = -2;
static int sizeOffset = -2;
void init(JNIEnv *env) {
jlongArray emptyCookie = VmCore::loadEmptyDex(env);
@ -36,8 +34,7 @@ void init(JNIEnv *env) {
for (int ii = 0; ii < 10; ++ii) {
auto value = *(size_t *) (dex + ii * sizeof(size_t));
if (value == 1872) {
sizeOffset = ii;
beginOffset = sizeOffset - 1;
beginOffset = ii - 1;
// auto dexBegin = *(size_t *) (dex + beginOffset * sizeof(size_t));
// HexDump(reinterpret_cast<char *>(dexBegin), 10, 0);
env->ReleaseLongArrayElements(emptyCookie, long_data, 0);
@ -47,34 +44,36 @@ void init(JNIEnv *env) {
}
env->ReleaseLongArrayElements(emptyCookie, long_data, 0);
beginOffset = -1;
sizeOffset = -1;
}
void DexDump::dumpDex(JNIEnv *env, jlong cookie, jstring dir) {
if (beginOffset == -2 || sizeOffset == -2) {
if (beginOffset == -2) {
init(env);
}
if (beginOffset == -1 || sizeOffset == -1) {
if (beginOffset == -1) {
ALOGD("dumpDex not support!");
return;
}
char magic[8] = {0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x35, 0x00};
auto base = reinterpret_cast<char *>(cookie);
auto begin = *(size_t *) (base + beginOffset * sizeof(size_t));
auto size = *(size_t *) (base + sizeOffset * sizeof(size_t));
// auto size = *(size_t *) (base + sizeOffset * sizeof(size_t));
if (!PointerCheck::check(reinterpret_cast<void *>(begin))) {
return;
}
auto dirC = env->GetStringUTFChars(dir, 0);
auto dexSizeOffset = ((unsigned long ) begin) + 0x20;
size_t size = *(size_t *) dexSizeOffset;
auto buffer = malloc(size);
memcpy(buffer, reinterpret_cast<const void *>(begin), size);
// fix magic
memcpy(buffer, magic, sizeof(magic));
char path[1024];
sprintf(path, "%s/dex_%ld.dex", dirC, size);
sprintf(path, "%s/dex_%d.dex", dirC, size);
auto fd = open(path, O_CREAT | O_WRONLY, 0600);
ssize_t w = write(fd, buffer, size);
fsync(fd);

@ -3,7 +3,7 @@ package top.niunaijun.blackdex;
import android.app.Application;
import android.content.Context;
import top.niunaijun.blackbox.BlackBoxCore;
import top.niunaijun.blackbox.BlackDexCore;
import top.niunaijun.blackbox.app.configuration.ClientConfiguration;
/**
@ -18,17 +18,22 @@ public class App extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
BlackBoxCore.get().doAttachBaseContext(base, new ClientConfiguration() {
BlackDexCore.get().doAttachBaseContext(base, new ClientConfiguration() {
@Override
public String getHostPackageName() {
return base.getPackageName();
}
@Override
public String getDexDumpDir() {
return super.getDexDumpDir();
}
});
}
@Override
public void onCreate() {
super.onCreate();
BlackBoxCore.get().doCreate();
BlackDexCore.get().doCreate();
}
}

@ -1,9 +1,15 @@
package top.niunaijun.blackdex;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.io.File;
import top.niunaijun.blackbox.BlackBoxCore;
import top.niunaijun.blackbox.BlackDexCore;
import top.niunaijun.blackbox.core.system.dump.IBDumpMonitor;
import top.niunaijun.blackbox.entity.dump.DumpResult;
public class MainActivity extends AppCompatActivity {
public static final String TAG = "MainActivity";
@ -12,8 +18,28 @@ public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 注册dump监听
BlackDexCore.get().registerDumpMonitor(mMonitor);
findViewById(R.id.btn_click).setOnClickListener(v -> {
BlackBoxCore.get().dumpDex(new File("/sdcard/huluxia.apk"));
// 此方法会阻塞
boolean b = BlackDexCore.get().dumpDex(new File("/sdcard/huluxia.apk"));
if (!b) {
Log.d(TAG, "dumpDex: error.");
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
BlackDexCore.get().unregisterDumpMonitor(mMonitor);
}
private final IBDumpMonitor mMonitor = new IBDumpMonitor.Stub() {
@Override
public void onDump(DumpResult result) {
Log.d(TAG, "onDump: " + result.toString());
}
};
}

Loading…
Cancel
Save