Xposed支付宝收款示例代码 实测可用 兼容edxposed

2021-03-04  乐帮网

支付宝 xposed

原文地址:https://www.52pojie.cn/thread-867703-1-1.html
经过验证此方法依然有效,可做为初学者的入门教程使用。

一、前言
前不久在吾爱论坛上看见有大佬搞了个《XPosed插件自动生成支付宝收款二维码》,我正好想要在网上卖点东西,如果我自己搞了个支付宝收款、转账监控的话,那是不是就能节约大量我核实订单这些时间了?答案当然是能的,于是我就开干了。
PS:许多人留言需要成品,最后我还准备放上成品给大家看。

二、突破口
首先收款和转账都是有notification通知的,于是我准备从这里入手。但是大家都是知道,这种收款什么的都是新开一个push进程然后IPC和主进程通讯。如果用monitor来抓取方法栈堆效果并不是很明显,而我则决定打印log和monitor双管齐下。
首先我们用Jadx打开alipay,随便找一个Java类打开查看他们的日志打印工具。

code

大家可以很清楚的看见LoggerFactory这个类,而熟悉Android开发设计模式的人都知道这是工厂模式,点开一看,下面封装了许多的logger。

public static final String TAG = "LoggerFactory";
private static ProcessInfo a = new NullProcessInfo();
private static DeviceProperty b = new NullDeviceProperty();
private static LogContext c = new NullLogContext();
private static TraceLogger d = new NullTraceLogger();
private static BehavorLogger e = new NullBehavorLogger();
private static MonitorLogger f = new NullMonitorLogger();
private static EventLogger g = new NullEventLogger();
private static AtomicBoolean h = new AtomicBoolean(false);

每个对象的具体作用是什么我就不描述了,可以自行查看。但是alipay打印log正是用的TraceLogger,于是我们就自需要hook住TraceLogger这个类就行。接下来我们看下TraceLogger的代码。

class NullTraceLogger implements TraceLogger {
        private NullTraceLogger() {
        }
 
        public void debug(String str, String str2) {
            new IllegalMonitorStateException("need invoke bind before use");
        }
 
        public void error(String str, String str2) {
            new IllegalMonitorStateException("need invoke bind before use");
        }
 
        public void error(String str, String str2, Throwable th) {
            new IllegalMonitorStateException("need invoke bind before use");
        }
 
        public void error(String str, Throwable th) {
            new IllegalMonitorStateException("need invoke bind before use");
        }
 
        public void info(String str, String str2) {
            new IllegalMonitorStateException("need invoke bind before use");
        }
 
        public void print(String str, String str2) {
            new IllegalMonitorStateException("need invoke bind before use");
        }
 
        public void print(String str, Throwable th) {
            new IllegalMonitorStateException("need invoke bind before use");
        }
 
        public void verbose(String str, String str2) {
            new IllegalMonitorStateException("need invoke bind before use");
        }
 
        public void warn(String str, String str2) {
            new IllegalMonitorStateException("need invoke bind before use");
        }
 
        public void warn(String str, String str2, Throwable th) {
            new IllegalMonitorStateException("need invoke bind before use");
        }
 
        public void warn(String str, Throwable th) {
            new IllegalMonitorStateException("need invoke bind before use");
        }
    }

很简单的方法,经过我的查看我们只需要hook参数为两个string的方法就行,而含有throwable参数的多半是为了打印错误信息,这不是我们所需要的。
你以为到这里就结束了吗?当然不是,因为我发现alipay居然还有一个打印的log的。找寻方法呢很简单跟上面差不多,我就不讲了,直接上hook代码。

package com.yymjr.android.xposedpay;
 
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
 
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
 
public class MainHook implements IXposedHookLoadPackage {
    private final static String TAG = "XposedPay-MainHook";
    private Class<?> NullTraceLoggerClazz;
    private Class<?> LogOutClazz;
    private Class<?> H5LogClazz;
 
    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
        if (!lpparam.packageName.equals("com.eg.android.AlipayGphone")) return;
        Log.d(TAG, "Hook alipay begin......");
        XposedHelpers.findAndHookMethod("com.alipay.mobile.quinox.LauncherApplication",lpparam.classLoader, "attachBaseContext", Context.class, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                Log.d(TAG, "Hook attachBaseContext successful......" );
                ClassLoader classLoader = ((Context) param.args[0]).getClassLoader();
                try {
                    NullTraceLoggerClazz = classLoader.loadClass("com.alipay.mobile.common.logging.api.LoggerFactory$NullTraceLogger");
                    LogOutClazz = classLoader.loadClass("com.alipay.pushsdk.util.log.LogUtil");
                    findAndookNullTraceLogger("debug");
                    findAndookNullTraceLogger("error");
                    findAndookNullTraceLogger("info");
                    findAndookNullTraceLogger("print");
                    findAndookNullTraceLogger("verbose");
                    findAndookNullTraceLogger("warn");
                    findAndHookMethod(LogOutClazz,"LogOut", int.class, String.class, String.class, new XC_MethodHook() {
                        @Override
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                            super.afterHookedMethod(param);
                            Log.d(TAG, "Hook LogUtil.LogOut successful.....");
                            Log.d(TAG, param.args[1].toString());
                            Log.d(TAG, param.args[2].toString());
                        }
                    });
                    findAndHookLogUtil("d");
                    findAndHookLogUtil("e");
                    findAndHookLogUtil("i");
                    findAndHookLogUtil("w");
                }catch (ClassNotFoundException e){
                    e.printStackTrace();
                }
            }
        });
    }
 
    private void findAndHookLogUtil(final String methodName){
        findAndHookMethod(LogOutClazz, methodName, String.class, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                Log.d(TAG, "Hook LogUtil."+methodName+" successful....." );
                Log.d(TAG, param.args[0].toString());
            }
        });
    }
 
    private void findAndookNullTraceLogger(final String methodName){
        findAndHookMethod(NullTraceLoggerClazz, methodName, String.class, String.class, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                Log.d(TAG, "Hook NullTraceLogger."+methodName+" successful....." );
                Log.d(TAG, param.args[0].toString() );
                Log.d(TAG, param.args[1].toString() );
            }
        });
    }
 
    private void findAndHookMethod(Class clazz, String methodName, Object... parameterTypesAndCallback){
        XposedHelpers.findAndHookMethod(clazz, methodName, parameterTypesAndCallback);
    }
}

这个里有些知识点需要讲解,首先就是第一个hook的是LauncherApplication的attachBaseContext,因为alipay是多dex,采用multiDex加载的,如果直接hook,将会爆出classnotfound的错误,只有拿到alipay的contextx去hook才不会。这里我是CV了@XOR 的代码。PS:我从不写代码,我直接代码的搬运工!手动滑稽。
当然还有第二种方法,那就是hook住Class.loadClass,拿到Class,这样子用class.getname来取出你想要的class。但是不知道为什么这种办法在alipay里面getname会爆nullpoity错误,所以最终我就采用了这个办法。
好的,接下来我们看一下日志。<数据很多,我只选的其中最重要的>

log

这里清晰的打印很多数据,我们json格式化下。

image

重要数据部分我都在图片里面标明了。当然还有个最重要的东西就是monitor。抓取的方法我就不说了,自行操作,接下来我说下结论。


三、结论
自行操作,接下来我说下结论。
1.push获取到数据交给amnet处理。
2.amnet数据处理后IPC通讯
3.交给主进程PushDirectMainProcessService处理。
4.PushDirectMainProcessService进行判断后交给PushNoticeDisplay处理。
5.PushNoticeDisplay,这里就是实现notification通知的地方了。

四、成品

package com.yymjr.android.xposedpay;
 
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
 
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
 
public class MainHook implements IXposedHookLoadPackage {
    private final static String TAG = "XposedPay-MainHook";
    private Bundle PushNoticeDisplayBundle = null;
    private Class<?> PushNoticeDisplayClazz;
 
    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
        if (!lpparam.packageName.equals("com.eg.android.AlipayGphone")) return;
        Log.d(TAG, "Hook alipay begin......");
        XposedHelpers.findAndHookMethod("com.alipay.mobile.quinox.LauncherApplication",lpparam.classLoader, "attachBaseContext", Context.class, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                Log.d(TAG, "Hook attachBaseContext successful......" );
                ClassLoader classLoader = ((Context) param.args[0]).getClassLoader();
                try {
                    PushNoticeDisplayClazz = classLoader.loadClass("com.alipay.mobile.rome.pushservice.integration.d");
                    XposedHelpers.findAndHookConstructor(PushNoticeDisplayClazz, Context.class, Bundle.class, new XC_MethodHook() {
                        @Override
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                            super.afterHookedMethod(param);
                            Log.d(TAG, "Hook PushNoticeDispaly.d successful......");
                            PushNoticeDisplayBundle = (Bundle) param.args[1];
                            if (PushNoticeDisplayBundle == null) return;
                            LogPushNoticeDisplay("push_show_title");
                            LogPushNoticeDisplay("push_show_text");
                            JSONObject jsonObject_data = new JSONObject(PushNoticeDisplayBundle.getString("push_msg_data"));
                            JSONObject paramsJsonObject = jsonObject_data.getJSONObject("params");
                            Log.d(TAG, "订单:"+paramsJsonObject.getString("tradeNO"));
                            JSONObject jsonObject_ext = new JSONObject(PushNoticeDisplayBundle.getString("push_show_ext"));
                            Log.d(TAG, "支付金额:"+jsonObject_ext.getString("soundValue"));
                        }
                    });
                }catch (ClassNotFoundException e){
                    e.printStackTrace();
                }
            }
        });
    }
 
    private void LogPushNoticeDisplay(String PushExtConstants){
        Log.d(TAG, PushNoticeDisplayBundle.getString(PushExtConstants));
    }
 
    private void findAndHookMethod(Class clazz, String methodName, Object... parameterTypesAndCallback){
        XposedHelpers.findAndHookMethod(clazz, methodName, parameterTypesAndCallback);
    }
}

该版本仅仅支持个人收款。

毕竟涉及alipay,所以我就没有一步步的讲解,更是省略了许多,这也是无奈之举。但是想要做的同学通过日志其实是能自己独立完成的。一点后言吧。
1.收款码收款,是没有订单信息的,用过收款码的同学都知道点开notification直接就是进入一个webview,如果真的想要拿到订单信息的话,就开启H5log,像@jiangwei212 大佬的文章里面一样,把网页数据给拿出来,只不过比较麻烦。
2.转账的话你点开也是一个webview,但是他的url中带的有订单信息,所以能直接得到订单。
3.备注这个我暂时是没有发现,估计只能是在webview里面查看。

公众号二维码

关注我的微信公众号
在公众号里留言交流
投稿邮箱:1052839972@qq.com

庭院深深深几许?杨柳堆烟,帘幕无重数。
玉勒雕鞍游冶处,楼高不见章台路。
雨横风狂三月暮。门掩黄昏,无计留春住。
泪眼问花花不语,乱红飞过秋千去。

欧阳修

付款二维码

如果感觉对您有帮助
欢迎向作者提供捐赠
这将是创作的最大动力