Skip to content

Commit 0161230

Browse files
committed
feat: enhance contact verification process with new methods and UI updates
1 parent 78c4d05 commit 0161230

11 files changed

Lines changed: 376 additions & 78 deletions

File tree

app/build.gradle.kts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import kotlinx.coroutines.delay
22
import kotlinx.coroutines.runBlocking
3+
import java.io.FileInputStream
34
import java.util.Locale
45
import java.util.Properties
5-
import java.io.FileInputStream
66

77
plugins {
88
alias(libs.plugins.androidApplication)
@@ -156,7 +156,8 @@ android {
156156

157157
dependencies {
158158
implementation(libs.colorpicker)
159-
implementation(libs.dexkit)
159+
implementation(files("libs/dexkit-android.aar"))
160+
implementation(libs.flatbuffers)
160161
compileOnly(libs.libxposed.legacy)
161162

162163
implementation(libs.androidx.activity)

app/libs/dexkit-android.aar

761 KB
Binary file not shown.

app/libs/dexkit-android.source.jar

390 KB
Binary file not shown.

app/src/main/java/com/wmods/wppenhacer/xposed/core/WppCore.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ public class WppCore {
6666
private static Method cachedMessageStoreKey;
6767
private static Field conversationDelegateField;
6868
private static Field conversationJidField;
69+
private static Field meManagerPhoneJidField;
70+
private static Object meManagerInstance;
6971

7072
public static void Initialize(ClassLoader loader, XSharedPreferences pref) throws Exception {
7173
privPrefs = Utils.getApplication().getSharedPreferences("WaGlobal", Context.MODE_PRIVATE);
@@ -123,6 +125,18 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
123125
}
124126
});
125127

128+
// load me current PhoneJid
129+
130+
Class<?> meManagerClass = Unobfuscator.loadMeManagerClass(loader);
131+
meManagerPhoneJidField = ReflectionUtils.getFieldByType(meManagerClass, FMessageWpp.UserJid.TYPE_PHONEUSERJID);
132+
XposedBridge.hookAllConstructors(meManagerClass, new XC_MethodHook() {
133+
@Override
134+
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
135+
meManagerInstance = param.thisObject;
136+
}
137+
});
138+
139+
126140
// Load wa database
127141
loadWADatabase();
128142

@@ -711,6 +725,15 @@ private static boolean isBridgeConnected() {
711725
return service != null && service.asBinder().isBinderAlive() && service.asBinder().pingBinder();
712726
}
713727

728+
public static FMessageWpp.UserJid getMyUserJid() {
729+
try {
730+
return new FMessageWpp.UserJid(meManagerPhoneJidField.get(meManagerInstance));
731+
} catch (Exception e) {
732+
XposedBridge.log(e);
733+
return null;
734+
}
735+
}
736+
714737
public interface ActivityChangeState {
715738

716739
void onChange(Activity activity, ChangeType type);

app/src/main/java/com/wmods/wppenhacer/xposed/core/components/FMessageWpp.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ public FMessageWpp(Object fMessage) {
5151
public static void initialize(ClassLoader classLoader) {
5252
try {
5353
TYPE = Unobfuscator.loadFMessageClass(classLoader);
54+
UserJid.TYPE_USERJID = Unobfuscator.findFirstClassUsingName(classLoader, StringMatchType.EndsWith, "jid.UserJid");
55+
UserJid.TYPE_JID = Unobfuscator.findFirstClassUsingName(classLoader, StringMatchType.EndsWith, "jid.Jid");
56+
UserJid.TYPE_PHONEUSERJID = Unobfuscator.findFirstClassUsingName(classLoader, StringMatchType.EndsWith, "jid.PhoneUserJid");
57+
UserJid.TYPE_DEVICEJID = Unobfuscator.findFirstClassUsingName(classLoader, StringMatchType.EndsWith, "jid.DeviceJid");
5458
var userJidClass = Unobfuscator.findFirstClassUsingName(classLoader, StringMatchType.EndsWith, "jid.UserJid");
5559
userJidMethod = ReflectionUtils.findMethodUsingFilter(TYPE, method -> method.getParameterCount() == 0 && method.getReturnType() == userJidClass);
5660
keyMessage = Unobfuscator.loadMessageKeyField(classLoader);
@@ -301,6 +305,11 @@ public String toString() {
301305

302306
public static class UserJid {
303307

308+
public static Class<?> TYPE_DEVICEJID;
309+
public static Class<?> TYPE_USERJID;
310+
public static Class<?> TYPE_JID;
311+
public static Class<?> TYPE_PHONEUSERJID;
312+
304313
public Object phoneJid;
305314

306315
public Object userJid;

app/src/main/java/com/wmods/wppenhacer/xposed/core/devkit/Unobfuscator.java

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2443,16 +2443,70 @@ public static Class<?> loadMeManagerClass(ClassLoader classLoader) throws Except
24432443
});
24442444
}
24452445

2446-
public synchronized static Class<?> loadVerifyKeyClass(ClassLoader classLoader) throws Exception {
2446+
public static Class<?> loadVerifyKeyClass(ClassLoader classLoader) throws Exception {
24472447
return UnobfuscatorCache.getInstance().getClass(classLoader, () -> {
2448-
var classList = dexkit.findClass(FindClass.create().matcher(ClassMatcher.create().addMethod(
2449-
MethodMatcher.create().addUsingNumber(2966).paramCount(1).addParamType(int.class)))).singleOrNull();
2448+
var methodMatcher = MethodMatcher.create().addUsingNumber(2966).paramCount(1).addParamType(int.class);
2449+
var result = dexkit.findMethod(FindMethod.create().matcher(methodMatcher));
2450+
if (result.isEmpty())
2451+
throw new RuntimeException("VerifyKey class not found");
2452+
var classList = result.get(0).getDeclaredClass();
24502453
if (classList == null)
24512454
throw new ClassNotFoundException("VerifyKey class not found");
24522455
return classList.getInstance(classLoader);
24532456
});
24542457
}
24552458

2459+
public static Constructor<?> loadVerifyKeyRunnableConstructor(ClassLoader classLoader) throws Exception {
2460+
return UnobfuscatorCache.getInstance().getConstructor(classLoader, () -> {
2461+
var data = dexkit.findMethod(
2462+
FindMethod.create().matcher(MethodMatcher.create()
2463+
.usingStrings("deviceidentityverifier/verify Primary")
2464+
)
2465+
).singleOrNull();
2466+
var clazz = data.getDeclaredClass().getInstance(classLoader);
2467+
return ReflectionUtils.findConstructorUsingFilter(clazz, c -> c.getParameterCount() == 2);
2468+
});
2469+
}
2470+
2471+
public static Number loadVerifyKeyInt(ClassLoader classLoader) throws Exception {
2472+
return UnobfuscatorCache.getInstance().getNumber(classLoader, () -> {
2473+
var method = loadVerifyKeyItemConstructor(classLoader);
2474+
var callers = dexkit.getMethodData(method).getCallers();
2475+
var resultMethod = callers.stream().filter(i -> i.isMethod() && i.getDeclaredClassName().contains("IdentityVerificationActivity")).findFirst().orElse(null);
2476+
var usingNumbers = resultMethod.getUsingNumbers();
2477+
var findMagicNumber = false;
2478+
for (var i = 0; i < usingNumbers.size(); i++) {
2479+
var n = usingNumbers.get(i);
2480+
if (n.intValue() == 2966) {
2481+
findMagicNumber = true;
2482+
} else if (findMagicNumber) {
2483+
return n;
2484+
}
2485+
}
2486+
throw new RuntimeException("VerifyKey int not found");
2487+
});
2488+
}
2489+
2490+
public static Constructor<?> loadVerifyKeyItemConstructor(ClassLoader classLoader) throws Exception {
2491+
return UnobfuscatorCache.getInstance().getConstructor(classLoader, () -> {
2492+
var clazz = dexkit.findClass(FindClass.create().matcher(ClassMatcher.create().className("IdentityVerificationActivity", StringMatchType.EndsWith))).singleOrNull();
2493+
var methodResult = dexkit.findMethod(
2494+
FindMethod.create().matcher(MethodMatcher.create()
2495+
.addUsingNumber(2966)
2496+
).searchInClass(List.of(clazz))
2497+
).singleOrNull();
2498+
var invokes = methodResult.getInvokes();
2499+
for (var invoke : invokes) {
2500+
if (!invoke.isConstructor()) continue;
2501+
var paramTypes = invoke.getParamTypes();
2502+
if (paramTypes.size() != 2) continue;
2503+
if (!paramTypes.get(1).getSimpleName().equals("List")) continue;
2504+
return invoke.getConstructorInstance(classLoader);
2505+
}
2506+
throw new RuntimeException("VerifyKey constructor not found");
2507+
});
2508+
}
2509+
24562510
public synchronized static Method loadMySearchBarMethod(ClassLoader classLoader) throws Exception {
24572511
return UnobfuscatorCache.getInstance().getMethod(classLoader, () -> {
24582512
Method method = findFirstMethodUsingStrings(classLoader, StringMatchType.EndsWith,
@@ -2729,4 +2783,12 @@ public static Class loadProcessImageQualityClass(ClassLoader classLoader) throws
27292783
return classDataList.get(0).getInstance(classLoader);
27302784
});
27312785
}
2786+
2787+
public static Class<?> loadGetProfilePhoto(ClassLoader classLoader) throws Exception {
2788+
return UnobfuscatorCache.getInstance().getClass(classLoader, () -> findFirstClassUsingStrings(classLoader, StringMatchType.Contains, "ProfilePhotoManager/sendGetProfilePhoto"));
2789+
}
2790+
2791+
public static Class<?> loadDialerProfilePictureLoader(ClassLoader classLoader) throws Exception {
2792+
return UnobfuscatorCache.getInstance().getClass(classLoader, () -> findFirstClassUsingStrings(classLoader, StringMatchType.Contains, "DialerProfilePictureLoader/syncFetchProfilePhoto/onPhotoReceived"));
2793+
}
27322794
}

app/src/main/java/com/wmods/wppenhacer/xposed/core/devkit/UnobfuscatorCache.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,48 @@ private void saveConstructor(String key, Constructor constructor) {
487487
sPrefsCacheHooks.edit().putString(key, value).commit();
488488
}
489489

490+
public Number getNumber(ClassLoader loader, FunctionCall<Number> functionCall) throws Exception {
491+
var methodName = getKeyName();
492+
String value = sPrefsCacheHooks.getString(methodName, null);
493+
if (value == null) {
494+
try {
495+
Number result = functionCall.call();
496+
if (result == null) throw new Exception("Number is null");
497+
saveNumber(methodName, result);
498+
return result;
499+
} catch (Exception e) {
500+
throw new Exception("Error getting number " + methodName + ": " + e.getMessage(), e);
501+
}
502+
}
503+
return loadNumber(value);
504+
}
505+
506+
@SuppressWarnings("ApplySharedPref")
507+
private void saveNumber(String key, Number number) {
508+
String value = number.getClass().getName() + ":" + number;
509+
sPrefsCacheHooks.edit().putString(key, value).commit();
510+
}
511+
512+
private Number loadNumber(String value) {
513+
String[] parts = value.split(":", 2);
514+
String className = parts.length == 2 ? parts[0] : Integer.class.getName();
515+
String numberValue = parts.length == 2 ? parts[1] : value;
516+
517+
return switch (className) {
518+
case "java.lang.Integer" -> Integer.valueOf(numberValue);
519+
case "java.lang.Long" -> Long.valueOf(numberValue);
520+
case "java.lang.Float" -> Float.valueOf(numberValue);
521+
case "java.lang.Double" -> Double.valueOf(numberValue);
522+
case "java.lang.Short" -> Short.valueOf(numberValue);
523+
case "java.lang.Byte" -> Byte.valueOf(numberValue);
524+
default -> {
525+
if (numberValue.contains(".")) {
526+
yield Double.valueOf(numberValue);
527+
}
528+
yield Long.valueOf(numberValue);
529+
}
530+
};
531+
}
490532

491533
public interface FunctionCall<T> {
492534
T call() throws Exception;

0 commit comments

Comments
 (0)