利用Xposed秒抢微信红包

2025-10-19 22:18:13 8273

免责申明: 本文只讨论技术,项目不用于任何利益行为,如因此产生的纠纷,本人概不负责。

前言

在阅读本文之前,假设你的手机已经root,并且已经成功安装好了 XposedInstaller。

正文

就我知道的,微信自动抢红包存在着两种方式,一种是利用安卓帮助残障用户使用android设备和应用的AccessibilityService进行模拟点击(本文不做讨论),第二种方式是直接hook微信本身的方法进行自动抢。第一种方式受限太多,比如手机本身性能等,并且抢的速度在不考虑手机性能的情况下第二种会快一些。 我们需要一个方法去实现 IXposedHookLoadPackage 这个接口,重写它内部提供的方法。此间我们会用到的是微信的包地址(com.tencent.mm)和数据库地址(com.tencent.wcdb.database.SQLiteDatabase)这里先给出。 首先第一步我们需要插入数据库进行操作,获取一些必要的信息: 1)hook数据库insert操作,打印是否成功插入 2)判断插入的数据是否是发送过来的消息 3)判断是否是红包消息类型 4)处理红包消息

//hook数据库插入操作

private void hookDatabaseInsert(final XC_LoadPackage.LoadPackageParam loadPackageParam) {

Class findClassIfExists = XposedHelpers.findClassIfExists(WECHAT_DATABASE_PACKAGE_NAME, loadPackageParam.classLoader);

if (findClassIfExists == null) {

XposedBridge.log("hook数据库insert操作:未找到类com.tencent.wcdb.database.SQLiteDatabase");

return;

}

XposedHelpers.findAndHookMethod(findClassIfExists, "insertWithOnConflict", new Object[]{String.class, String.class, ContentValues.class, Integer.TYPE, new XC_MethodHook() {

/* access modifiers changed from: protected */

public void afterHookedMethod(XC_MethodHook.MethodHookParam methodHookParam) throws Throwable {

Integer asInteger;

//打印插入的信息

XposedBridge.log("------------------------insert start---------------------\n\n");

XposedBridge.log("param args1:" + ((String) methodHookParam.args[0]));

XposedBridge.log("param args1:" + ((String) methodHookParam.args[1]));

ContentValues contentValues = (ContentValues) methodHookParam.args[2];

XposedBridge.log("param args3 contentValues:");

for (Map.Entry next : contentValues.valueSet()) {

if (next.getValue() != null) {

XposedBridge.log(((String) next.getKey()) + "---------" + next.getValue().toString());

} else {

XposedBridge.log(((String) next.getKey()) + "---------null");

}

}

XposedBridge.log("------------------------insert over---------------------\n\n");

//判断插入的数据是否是发送过来的消息

String str = (String) methodHookParam.args[0];

XposedBridge.log("消息类型:" + contentValues.getAsInteger("type"));

if (!TextUtils.isEmpty(str) && str.equals("message") && (asInteger = contentValues.getAsInteger("type")) != null && asInteger.intValue() == 436207665) {

//处理红包消息

XposedInit.this.handleLuckyMoney(contentValues, loadPackageParam);

}

}

}});

}

其次需要在红包出现的界面做一些操作: 1)hook 微信主界面的onCreate方法,获得主界面对象 2)hook领取红包页面的onCreate方法,打印Intent中的参数(只起到调试作用) 3)hook红包界面初始化“开”按钮的方法,在该方法完成后自动点击开按钮领取红包

public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam loadPackageParam) {

//调用hook数据库插入

hookDatabaseInsert(loadPackageParam);

//**************红包专用开始**************

//hook微信主界面的onCreate方法,获得主界面对象

XposedHelpers.findAndHookMethod("com.tencent.mm.ui.LauncherUI", loadPackageParam.classLoader, "onCreate", new Object[]{Bundle.class, new XC_MethodHook() {

/* access modifiers changed from: protected */

public void afterHookedMethod(XC_MethodHook.MethodHookParam methodHookParam) throws Throwable {

XposedBridge.log("com.tencent.mm.ui.LauncherUI onCreated\n");

Activity unused = XposedInit.launcherUiActivity = (Activity) methodHookParam.thisObject;

}

}});

//hook领取红包页面的onCreate方法,打印Intent中的参数(只起到调试作用)

XposedHelpers.findAndHookMethod("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI", loadPackageParam.classLoader, "onCreate", new Object[]{Bundle.class, new XC_MethodHook() {

/* access modifiers changed from: protected */

public void afterHookedMethod(XC_MethodHook.MethodHookParam methodHookParam) throws Throwable {

Activity activity = (Activity) methodHookParam.thisObject;

String stringExtra = activity.getIntent().getStringExtra("key_native_url");

String stringExtra2 = activity.getIntent().getStringExtra("key_username");

int intExtra = activity.getIntent().getIntExtra("key_way", 0);

XposedBridge.log("key_native_url: " + stringExtra + "\n");

XposedBridge.log("key_way: " + intExtra + "\n");

XposedBridge.log("key_username: " + stringExtra2 + "\n");

}

}});

//hook红包界面初始化“开”按钮的方法,在该方法完成后自动点击“开”按钮领取红包

XposedHelpers.findAndHookMethod("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI", loadPackageParam.classLoader, "d", new Object[]{Integer.TYPE, Integer.TYPE, String.class, XposedHelpers.findClass("com.tencent.mm.ab.l", loadPackageParam.classLoader), new XC_MethodHook() {

/* access modifiers changed from: protected */

public void afterHookedMethod(XC_MethodHook.MethodHookParam methodHookParam) throws Throwable {

XposedBridge.log("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI: Method d called\n");

((Button) XposedHelpers.findField(methodHookParam.thisObject.getClass(), "kMG").get(methodHookParam.thisObject)).performClick();

}

}});

}

//**************红包专用结束**************

最后到了最关键的一步: 1)从插入的数据库中获得nativeurl 2)启动红包页面 3)至于抢的操作Xposed内置的 callStaticMethod 已经帮我们完成了

//处理红包消息

public void handleLuckyMoney(ContentValues contentValues, XC_LoadPackage.LoadPackageParam loadPackageParam) throws Exception {

String asString = contentValues.getAsString("talker");

//从插入的数据库中获得nativeurl

String asString2 = contentValues.getAsString("content");

if (!asString2.startsWith("

asString2 = asString2.substring(asString2.indexOf("

}

String string = new XmlToJson.Builder(asString2).build().toJson().getJSONObject(NotificationCompat.CATEGORY_MESSAGE).getJSONObject("appmsg").getJSONObject("wcpayinfo").getString("nativeurl");

XposedBridge.log("nativeurl: " + string + "\n");

//启动红包页面

if (launcherUiActivity != null) {

XposedBridge.log("call method com.tencent.mm.bm.d b, start LuckyMoneyReceiveUI\n");

Intent intent = new Intent();

intent.putExtra("key_way", 1);

intent.putExtra("key_native_url", string);

intent.putExtra("key_username", asString);

XposedHelpers.callStaticMethod(XposedHelpers.findClass("com.tencent.mm.bg.d", loadPackageParam.classLoader), "b", new Object[]{launcherUiActivity, "luckymoney", ".ui.LuckyMoneyReceiveUI", intent});

return;

}

XposedBridge.log("launcherUiActivity == null\n");

}

技巧: 获取每个页面的关键类信息,可以通过DDMS进行进程追踪(动手google或者百度)或者通过UI工具去实现查找,当然这里我介绍一种最最最最不折磨人的方式各大应用市场搜TopActivity(神器啊!想了解这个的同学可以去gayhub找源码看)。

附:编译好的APK程序

写在最后 学之深,则越发觉得世界之大,你我皆如井底之蛙,奋斗不息,方达彼岸。 不定期更新博客,期待和大家一起进步。