开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 31153|回复: 2
收起左侧

[Android逆向] Xposed---收款、转账监控

[复制链接]
发表于 2020-6-27 14:50:54 | 显示全部楼层 |阅读模式   广东省佛山市
一、前言
前不久在吾爱论坛上看见有大佬搞了个《XPosed插件自动生成支付宝收款二维码》,我正好想要在网上卖点东西,如果我自己搞了个支付宝收款、转账监控的话,那是不是就能节约大量我核实订单这些时间了?答案当然是能的,于是我就开干了。
PS:许多人留言需要成品,最后我还准备放上成品给大家看。
二、突破口
首先收款和转账都是有notification通知的,于是我准备从这里入手。但是大家都是知道,这种收款什么的都是新开一个push进程然后IPC和主进程通讯。如果用monitor来抓取方法栈堆效果并不是很明显,而我则决定打印log和monitor双管齐下。
首先我们用Jadx打开alipay,随便找一个Java类打开查看他们的日志打印工具。

大家可以很清楚的看见LoggerFactory这个类,而熟悉Android开发设计模式的人都知道这是工厂模式,点开一看,下面封装了许多的logger。
[Java] [color=rgb(51, 102, 153) !important]纯文本查看 [color=rgb(51, 102, 153) !important]复制代码
[backcolor=rgb(27, 36, 38) !important][color=white !important]
[color=white !important]?

1

2

3

4

5

6

7

8

9

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的代码。
[Java] [color=rgb(51, 102, 153) !important]纯文本查看 [color=rgb(51, 102, 153) !important]复制代码
[backcolor=rgb(27, 36, 38) !important][color=white !important]
[color=white !important]?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

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代码。
[Java] [color=rgb(51, 102, 153) !important]纯文本查看 [color=rgb(51, 102, 153) !important]复制代码
[backcolor=rgb(27, 36, 38) !important][color=white !important]
[color=white !important]?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

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

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

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

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


四、成品
[Java] [color=rgb(51, 102, 153) !important]纯文本查看 [color=rgb(51, 102, 153) !important]复制代码
[backcolor=rgb(27, 36, 38) !important][color=white !important]
[color=white !important]?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

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,把网页数据给拿出来,只不过比较麻烦。
2.转账的话你点开也是一个webview,但是他的url中带的有订单信息,所以能直接得到订单。
3.备注这个我暂时是没有发现,估计只能是在webview里面查看。

签到天数: 1 天

发表于 2021-9-4 21:07:00 | 显示全部楼层   广东省广州市
厉害了,我的哥
回复 支持 反对

使用道具 举报

发表于 2020-11-22 12:32:05 | 显示全部楼层   四川省达州市
支持支持。。。。。。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 793400750,邮箱:wp@125.la
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表