fix: BaseApk for QQ 8.9.63

This commit is contained in:
klxiaoniu
2023-06-28 10:53:38 +08:00
parent 74b7ff24ac
commit 53ee6f9068
3 changed files with 78 additions and 48 deletions

View File

@@ -22,6 +22,7 @@
package cc.ioctl.hook.file; package cc.ioctl.hook.file;
import static io.github.qauxv.util.QQVersion.QQ_8_6_0; import static io.github.qauxv.util.QQVersion.QQ_8_6_0;
import static io.github.qauxv.util.QQVersion.QQ_8_9_63;
import android.app.Activity; import android.app.Activity;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
@@ -42,14 +43,19 @@ import io.github.qauxv.base.annotation.UiItemAgentEntry;
import io.github.qauxv.dsl.FunctionEntryRouter.Locations.Auxiliary; import io.github.qauxv.dsl.FunctionEntryRouter.Locations.Auxiliary;
import io.github.qauxv.hook.CommonConfigFunctionHook; import io.github.qauxv.hook.CommonConfigFunctionHook;
import io.github.qauxv.util.Initiator; import io.github.qauxv.util.Initiator;
import io.github.qauxv.util.dexkit.DexKit;
import io.github.qauxv.util.dexkit.DexKitTarget;
import io.github.qauxv.util.dexkit.TroopSendFile_QQNT;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.Objects;
import kotlin.Unit; import kotlin.Unit;
import kotlin.jvm.functions.Function3; import kotlin.jvm.functions.Function3;
import kotlinx.coroutines.flow.MutableStateFlow; import kotlinx.coroutines.flow.MutableStateFlow;
//重命名base.apk //重命名base.apk
@FunctionHookEntry @FunctionHookEntry
@UiItemAgentEntry @UiItemAgentEntry
@@ -58,7 +64,7 @@ public class BaseApk extends CommonConfigFunctionHook {
public static final BaseApk INSTANCE = new BaseApk(); public static final BaseApk INSTANCE = new BaseApk();
private BaseApk() { private BaseApk() {
super(); super(new DexKitTarget[]{TroopSendFile_QQNT.INSTANCE});
} }
@NonNull @NonNull
@@ -91,7 +97,29 @@ public class BaseApk extends CommonConfigFunctionHook {
@Override @Override
public boolean initOnce() throws Exception { public boolean initOnce() throws Exception {
if (HostInfo.requireMinQQVersion(QQ_8_6_0)) { if (HostInfo.requireMinQQVersion(QQ_8_9_63)) {
HookUtils.hookBeforeIfEnabled(this, DexKit.requireMethodFromCache(TroopSendFile_QQNT.INSTANCE), param -> {
Field[] fs = param.thisObject.getClass().getDeclaredFields();
Field f = null;
for (Field field : fs) {
field.setAccessible(true);
if (field.get(param.thisObject).getClass().getName().contains("TroopFileTransferManager$Item")) {
f = field;
break;
}
}
Object item = f.get(param.thisObject);
Field fileName = item.getClass().getSuperclass().getDeclaredField("FileName");
if (Objects.equals(fileName.get(item), "base.apk")) {
String localFile = (String) item.getClass().getSuperclass().getDeclaredField("LocalFile").get(item);
File file = new File(localFile);
if (!file.exists()) {
throw new FileNotFoundException("file not found: path='" + localFile + "'");
}
fileName.set(item, getFormattedFileNameByPath(localFile));
}
});
} else if (HostInfo.requireMinQQVersion(QQ_8_6_0)) {
Class c = Initiator.load("com.tencent.mobileqq.utils.FileUtils"); Class c = Initiator.load("com.tencent.mobileqq.utils.FileUtils");
XposedHelpers.findAndHookMethod(c, "getFileName", String.class, new XC_MethodHook() { XposedHelpers.findAndHookMethod(c, "getFileName", String.class, new XC_MethodHook() {
@Override @Override
@@ -104,63 +132,35 @@ public class BaseApk extends CommonConfigFunctionHook {
return; return;
} }
if (fileName.equals("base.apk")) { if (fileName.equals("base.apk")) {
PackageManager packageManager = HostInfo.getApplication().getPackageManager();
File file = new File(localFile); File file = new File(localFile);
if (!file.exists()) { if (!file.exists()) {
throw new FileNotFoundException("file not found: path='" + localFile + "', name='" + fileName + "'"); throw new FileNotFoundException("file not found: path='" + localFile + "', name='" + fileName + "'");
} }
PackageInfo packageArchiveInfo = packageManager.getPackageArchiveInfo(localFile, param.setResult(getFormattedFileNameByPath(localFile));
PackageManager.GET_ACTIVITIES);
ApplicationInfo applicationInfo = packageArchiveInfo.applicationInfo;
applicationInfo.sourceDir = localFile;
applicationInfo.publicSourceDir = localFile;
String format = RikkaBaseApkFormatDialog.getCurrentBaseApkFormat();
if (format != null) {
String result = format
.replace("%n", applicationInfo.loadLabel(packageManager).toString())
.replace("%p", applicationInfo.packageName)
.replace("%v", packageArchiveInfo.versionName)
.replace("%c", String.valueOf(packageArchiveInfo.versionCode));
param.setResult(result);
}
} }
} catch (Exception e) { } catch (Exception e) {
traceError(e); traceError(e);
} }
} }
}); });
return true; } else {
} final Class<?> _ItemManagerClz = Initiator.load(
final Class<?> _ItemManagerClz = Initiator.load( "com.tencent.mobileqq.troop.utils.TroopFileTransferManager$Item");
"com.tencent.mobileqq.troop.utils.TroopFileTransferManager$Item"); for (Method m : Initiator._TroopFileUploadMgr().getDeclaredMethods()) {
for (Method m : Initiator._TroopFileUploadMgr().getDeclaredMethods()) { if (Modifier.isPrivate(m.getModifiers()) && !Modifier.isStatic(m.getModifiers())
if (Modifier.isPrivate(m.getModifiers()) && !Modifier.isStatic(m.getModifiers()) && m.getReturnType().equals(int.class)) {
&& m.getReturnType().equals(int.class)) { Class<?>[] argt = m.getParameterTypes();
Class<?>[] argt = m.getParameterTypes(); if (argt.length == 3 && argt[0] == long.class
if (argt.length == 3 && argt[0] == long.class && argt[1] == _ItemManagerClz && argt[2] == Bundle.class) {
&& argt[1] == _ItemManagerClz && argt[2] == Bundle.class) { HookUtils.hookBeforeIfEnabled(this, m, param -> {
HookUtils.hookBeforeIfEnabled(this, m, param -> { Object item = param.args[1];
Object item = param.args[1]; Field localFile = XposedHelpers.findField(_ItemManagerClz, "LocalFile");
Field localFile = XposedHelpers.findField(_ItemManagerClz, "LocalFile"); Field fileName = XposedHelpers.findField(_ItemManagerClz, "FileName");
Field fileName = XposedHelpers.findField(_ItemManagerClz, "FileName"); if (fileName.get(item).equals("base.apk")) {
if (fileName.get(item).equals("base.apk")) { fileName.set(item, getFormattedFileNameByPath((String) localFile.get(item)));
PackageManager packageManager = HostInfo.getApplication().getPackageManager();
PackageInfo packageArchiveInfo = packageManager
.getPackageArchiveInfo((String) localFile.get(item), PackageManager.GET_ACTIVITIES);
ApplicationInfo applicationInfo = packageArchiveInfo.applicationInfo;
applicationInfo.sourceDir = (String) localFile.get(item);
applicationInfo.publicSourceDir = (String) localFile.get(item);
String format = RikkaBaseApkFormatDialog.getCurrentBaseApkFormat();
if (format != null) {
String result = format
.replace("%n", applicationInfo.loadLabel(packageManager).toString())
.replace("%p", applicationInfo.packageName)
.replace("%v", packageArchiveInfo.versionName)
.replace("%c", String.valueOf(packageArchiveInfo.versionCode));
fileName.set(item, result);
} }
} });
}); }
} }
} }
} }
@@ -176,4 +176,24 @@ public class BaseApk extends CommonConfigFunctionHook {
public void setEnabled(boolean enabled) { public void setEnabled(boolean enabled) {
// nop // nop
} }
private String getFormattedFileNameByPath(String path) {
PackageManager packageManager = HostInfo.getApplication().getPackageManager();
PackageInfo packageArchiveInfo = packageManager
.getPackageArchiveInfo(path, PackageManager.GET_ACTIVITIES);
ApplicationInfo applicationInfo = packageArchiveInfo.applicationInfo;
applicationInfo.sourceDir = path;
applicationInfo.publicSourceDir = path;
String format = RikkaBaseApkFormatDialog.getCurrentBaseApkFormat();
String result;
if (format != null) {
result = format
.replace("%n", applicationInfo.loadLabel(packageManager).toString())
.replace("%p", applicationInfo.packageName)
.replace("%v", packageArchiveInfo.versionName)
.replace("%c", String.valueOf(packageArchiveInfo.versionCode));
} else
throw new RuntimeException("format is null");
return result;
}
} }

View File

@@ -93,4 +93,7 @@ public class QQVersion {
public static final long QQ_8_9_35 = 3814; public static final long QQ_8_9_35 = 3814;
public static final long QQ_8_9_53 = 3964; public static final long QQ_8_9_53 = 3964;
public static final long QQ_8_9_55 = 4030; public static final long QQ_8_9_55 = 4030;
// The first NT version
public static final long QQ_8_9_63 = 4194;
} }

View File

@@ -699,3 +699,10 @@ data object Reply_At_QQNT : DexKitTarget.UsingStr() {
override val declaringClass = "" override val declaringClass = ""
override val filter = DexKitFilter.strInClsName("com/tencent/mobileqq/aio/input") override val filter = DexKitFilter.strInClsName("com/tencent/mobileqq/aio/input")
} }
data object TroopSendFile_QQNT : DexKitTarget.UsingStr() {
override val findMethod: Boolean = true
override val traitString = arrayOf("send local to troop file use nt, filePath:")
override val declaringClass = ""
override val filter = DexKitFilter.allowAll
}