Android开发经验谈Android开发Android安全-逆向

Xposed系列之微信装X指南(二)

2020-07-11  本文已影响0人  小不点CC3

需求

比如说每个人都有一个小目标,每天看看自己的目标会更有动力,那么现在实现"一个亿"的小目标,我们让从点击我的Tab开始,
进入支付页面-钱包页面-零钱页面显示的金额都是¥100000000.00

结果

微信Android7.0.16版本,最后代码实现的效果如下:

image

旧版本实现效果

准备工作

Root相关

如果用VirtualXposed或太极或其他虚拟环境的Xposed则可以不用Root,如果用Xposed Installer则需要Root权限,
关于这三者可看上篇文章:Xposed系列之Demo上手指南及源码解析(一)

反编译相关

推荐使用jadx工具反编译,如从微信官网下载的32位版本微信,默认都是会下载上面weixin7016android1700_arm64.apk
如果下载arm64版本则有些x86架构的模拟器不支持微信就不能正常使用了,所以用32位主要是为了方便在模拟器上调试

image
然后将下载下来的weixin7016android1700.apk拖入JadxGUI中,反编译结果如下图:
image
并且我们还可以另存为Gradle项目,在Android Studio或IDEA中查看,操作入口如下:
image

Hook分析相关

adb命令

adb 命令可以参考https://github.com/xbdcc/CCommand, 这里简单介绍这里需要使用的:

adb shell dumpsys activity top > activity_top.txt

当然如果adb命令你已经很熟悉了想快捷输入也可以在环境变量中设置alisa

alias activity_top="adb shell dumpsys activity top > activity_top.txt"

该命令可以输出当前Activity信息,如命令抓取的零钱页面Activity的信息如下:

TASK com.tencent.mm id=184
  ACTIVITY com.tencent.mm/.plugin.wallet.balance.ui.WalletBalanceManagerUI 1fcb6708 pid=1326
    Local Activity 27bbdf64 State:
      mResumed=true mStopped=false mFinished=false
      mLoadersStarted=true
      mChangingConfigurations=false
      mCurrentConfig={1.0 ?mcc?mnc zh_CN ?layoutDir sw360dp w360dp h622dp 480dpi nrml long port finger -keyb/v/h -nav/h s.5mThemeChanged = 0mThemeChangedFlags = 0mFlipFont = 0}
    Active Fragments in 247455f2:
      #0: ReportFragment{22e48443 #0 android.arch.lifecycle.LifecycleDispatcher.report_fragment_tag}
        mFragmentId=#0 mContainerId=#0 mTag=android.arch.lifecycle.LifecycleDispatcher.report_fragment_tag
        mState=5 mIndex=0 mWho=android:fragment:0 mBackStackNesting=0
        mAdded=true mRemoving=false mResumed=true mFromLayout=false mInLayout=false
        mHidden=false mDetached=false mMenuVisible=true mHasMenu=false
        mRetainInstance=false mRetaining=false mUserVisibleHint=true
        mFragmentManager=FragmentManager{247455f2 in WalletBalanceManagerUI{27bbdf64}}
        mActivity=com.tencent.mm.plugin.wallet.balance.ui.WalletBalanceManagerUI@27bbdf64
        Child FragmentManager{a6aeac0 in ReportFragment{22e48443}}:
          FragmentManager misc state:
            mActivity=com.tencent.mm.plugin.wallet.balance.ui.WalletBalanceManagerUI@27bbdf64
            mContainer=android.app.Fragment$1@138ca3f9
            mParent=ReportFragment{22e48443 #0 android.arch.lifecycle.LifecycleDispatcher.report_fragment_tag}
            mCurState=5 mStateSaved=false mDestroyed=false
    Added Fragments:
      #0: ReportFragment{22e48443 #0 android.arch.lifecycle.LifecycleDispatcher.report_fragment_tag}
    FragmentManager misc state:
      mActivity=com.tencent.mm.plugin.wallet.balance.ui.WalletBalanceManagerUI@27bbdf64
      mContainer=android.app.Activity$1@386ddf3e
      mCurState=5 mStateSaved=false mDestroyed=false
    ViewRoot:
      mAdded=true mRemoved=false
      mConsumeBatchedInputScheduled=false
      mConsumeBatchedInputImmediatelyScheduled=false
      mPendingInputEventCount=0
      mProcessInputEventsScheduled=false
      mTraversalScheduled=false
      android.view.ViewRootImpl$NativePreImeInputStage: mQueueLength=0
      android.view.ViewRootImpl$ImeInputStage: mQueueLength=0
      android.view.ViewRootImpl$NativePostImeInputStage: mQueueLength=0
    Choreographer:
      mFrameScheduled=false
      mLastFrameTime=16770070 (150010 ms ago)
    View Hierarchy:
      com.android.internal.policy.impl.PhoneWindow$DecorView{162d5b8c V.ED.... R....... 0,0-1080,1920}
        com.tencent.mm.ui.widget.SwipeBackLayout{15900669 VFE..... ........ 0,0-1080,1920 #7f09245b app:id/g2s}
          com.tencent.mm.ui.statusbar.b{303be18f V.ED.... ........ 0,0-1080,1920}
            android.widget.LinearLayout{1d1aa478 V.E..... ........ 0,54-1080,1920}
              android.view.ViewStub{2f44c751 G.E..... ......I. 0,0-0,0 #1020373}
              android.widget.FrameLayout{ea9bbb6 V.E..... ........ 0,0-1080,1866}
                android.support.v7.widget.ActionBarOverlayLayout{1e0ddd42 V.E..... ........ 0,0-1080,1866 #7f090a81 app:id/b8w}
                  android.support.v7.widget.ContentFrameLayout{6698a90 V.E..... ........ 0,130-1080,1866 #1020002 android:id/content}
                    com.tencent.mm.ui.LayoutListenerView{941b6fc V.E..... ........ 0,0-1080,1736 #7f0917b0 app:id/dp5}
                      android.widget.ScrollView{cc9bba6 VFED.... ........ 0,0-1080,1736}
                        android.widget.RelativeLayout{3887e994 V.E..... ........ 0,0-1080,1736}
                          android.widget.TextView{3781bc3d G.ED.... ......I. 0,0-0,0 #7f09289c app:id/guw}
                          android.widget.LinearLayout{15c40b00 V.E..... ........ 0,0-1080,1736}
                            android.widget.ImageView{1d2df39 V.ED.... ........ 453,130-626,303 #7f09034d app:id/w5}
                            android.widget.TextView{25e2997e V.ED.... ........ 448,389-632,451 #7f09259c app:id/ga5}
                            android.widget.LinearLayout{21b3eedf V.E..... ........ 0,451-1080,721}
                              android.widget.RelativeLayout{bded72c V.E..... ........ 0,43-1080,157}
                                com.tencent.mm.plugin.wallet_core.ui.view.WcPayMoneyLoadingView{b7935f5 V.E..... ........ 375,0-705,114 #7f0928aa app:id/gv_}
                                  com.robinhood.ticker.TickerView{21299fb V.ED.... ........ 0,0-330,114 #7f091794 app:id/dod}
                                android.widget.ProgressBar{1ff83a18 G.ED.... ......I. 0,0-0,0 #7f092905 app:id/gxq}
                              android.widget.LinearLayout{36ce5a56 G.E..... ......I. 0,0-0,0 #7f09033f app:id/vr}
                                android.widget.TextView{29e6dad7 V.ED.... ......ID 0,0-0,0 #7f090340 app:id/vs}
                                android.widget.ImageView{742dfc4 V.ED.... ......ID 0,0-0,0 #7f09033e app:id/vq}
                              android.widget.LinearLayout{d3f2ead G.E..... ......I. 0,0-0,0 #7f09034b app:id/w3}
                                com.tencent.mm.pluginsdk.ui.applet.CdnImageView{28544d73 V.ED.... ......I. 0,0-0,0 #7f09034a app:id/w2}
                                com.tencent.mm.wallet_core.ui.WalletTextView{35703430 V.ED.... ......ID 0,0-0,0 #7f090349 app:id/w1}
                                com.tencent.mm.pluginsdk.ui.applet.CdnImageView{3dcd08a9 V.ED.... ......I. 0,0-0,0 #7f090348 app:id/w0}
                            android.widget.Space{111c4dcf I.ED.... ......I. 0,721-1080,1101}
                            android.widget.LinearLayout{25dc635c V.E..... ........ 0,1187-1080,1295}
                              android.widget.Button{3a448665 VFED..C. ........ 291,0-788,108 #7f0919c4 app:id/e3i}
                              android.widget.Button{b7a5948 GFED..C. ......I. 0,0-0,0 #7f09289d app:id/gux}
                              android.widget.LinearLayout{363e27c7 G.E..... ......I. 0,0-0,0 #7f09141b app:id/d1c}
                                android.widget.TextView{137fc1f4 V.ED.... ......ID 0,0-0,0 #7f09141c app:id/d1d}
                                android.widget.ImageView{31361d1d G.ED.... ......I. 0,0-0,0 #7f09153c app:id/d96}
                            android.widget.LinearLayout{12576b92 V.E..... ........ 464,1554-616,1606}
                              android.widget.TextView{36eb7963 V.ED..C. ........ 0,0-152,52 #7f09289f app:id/guz}
                              android.view.View{181c6e19 G.ED.... ......I. 0,0-0,0 #7f09289e app:id/guy}
                              android.widget.TextView{2dfcaede G.ED.... ......I. 0,0-0,0 #7f09289b app:id/guv}
                            android.widget.TextView{2f9248bf V.ED.... ........ 0,1628-1080,1671 #7f092951 app:id/gzs}
                      android.widget.Button{39a3e185 GFED..C. ......ID 0,0-0,0 #7f0917c6 app:id/dpq}
                  android.support.v7.widget.ActionBarContainer{1e880f89 V.ED.... ........ 0,0-1080,130 #7f090059 app:id/bp}
                    android.support.v7.widget.Toolbar{1a08b8e V.E..... ........ 0,0-1080,130 #7f090057 app:id/bn}
                      android.widget.LinearLayout{88b4a54 V.E..... ........ 0,0-810,130 #7f09005b app:id/br}
                        android.widget.LinearLayout{24ec6dfd V.E...C. ........ 0,0-108,130 #7f0900a0 app:id/dm}
                          com.tencent.mm.ui.widget.imageview.WeImageView{10dc1af2 V.ED.... ........ 22,0-86,130 #7f0900a1 app:id/dn}
                        android.widget.LinearLayout{1e96ecf9 G.E..... ......I. 0,0-0,0 #7f090098 app:id/de}
                          com.tencent.mm.ui.widget.AlbumChooserView{40cf43e V.E...C. ......I. 0,0-0,0 #7f09008a app:id/d1}
                            android.widget.RelativeLayout{13558fec V.E..... ......I. 0,0-0,0}
                              android.widget.TextView{9d05fb5 V.ED.... ......ID 0,0-0,0 #7f090120 app:id/h3}
                              android.widget.FrameLayout{25e0164a V.E..... ......I. 0,0-0,0}
                                com.tencent.mm.ui.widget.imageview.WeImageView{2e7039bb V.ED.... ......ID 0,0-0,0 #7f09011f app:id/h2}
                        android.widget.LinearLayout{1901bed8 V.E..... ......I. 108,0-108,130 #7f0925d1 app:id/gbk}
                          android.widget.LinearLayout{20f44231 V.E..... ......ID 0,0-0,130}
                            android.widget.ImageView{17114d16 G.ED.... ......I. 0,0-0,0 #7f0925d0 app:id/gbj}
                            android.widget.TextView{cdeb697 V.ED.... ......ID 0,34-0,96 #1020014 android:id/text1}
                            android.widget.ProgressBar{263ff084 G.ED.... ......I. 0,0-0,0 #7f091c5e app:id/eki}
                          android.widget.TextView{364d24a2 G.ED.... ......I. 0,0-0,0 #1020015 android:id/text2}
                      android.support.v7.widget.ActionMenuView{c9308ac V.E..... ........ 810,0-1080,130}
                        android.widget.LinearLayout{25f3ae17 V.E..... ........ 0,0-270,130}
                          android.widget.ImageButton{24965204 GFED..C. ......I. 0,0-0,0 #7f09007c app:id/cn}
                          android.widget.TextView{141653ed V.ED..CL ........ 0,0-270,130 #7f090079 app:id/ck}
                          android.widget.LinearLayout{357b14b3 G.E..... ......I. 0,0-0,0 #7f090158 app:id/il}
                            android.widget.ImageView{3b288a70 V.ED.... ......ID 0,0-0,0}
                          android.widget.Button{d1141e9 GFED..CL ......I. 0,0-0,0 #7f090076 app:id/ch}
                          android.widget.RelativeLayout{1908490f V.E..... ......ID 270,65-270,65}
                            com.tencent.mm.ui.widget.imageview.WeImageView{3f63dd9c G.ED.... ......I. 0,0-0,0 #7f090078 app:id/cj}
                            android.widget.ImageView{2db313a5 G.ED.... ......I. 0,0-0,0 #7f090b6f app:id/beb}
                    android.support.v7.widget.ActionBarContextView{18591b45 G.E..... ......I. 0,0-0,0 #7f090065 app:id/c1}
    Looper (main, tid 1) {1f1b79df}
      Message 0: { when=+6m42s348ms what=26 target=com.tencent.mm.sdk.platformtools.ao$2 }
      Message 1: { when=+26m42s267ms what=23 target=com.tencent.mm.sdk.platformtools.ao$2 }
      (Total messages: 2, idling=false, quitting=false)
    Local FragmentActivity 27bbdf64 State:
      mCreated=true mResumed=true mStopped=false    FragmentManager misc state:
      mHost=android.support.v4.app.FragmentActivity$a@1273f2ec
      mContainer=android.support.v4.app.FragmentActivity$a@1273f2ec
      mCurState=4 mStateSaved=false mStopped=false mDestroyed=false

monitor

再介绍三种方便查找id值的方法

假如我们要查看id为dod的值:

通过activity_top查看

在里面找到元素对应的值,为十六进制值。如上面结果中有这样一行,可以看到id为'dod'的值为十六进制值7f091794

com.robinhood.ticker.TickerView{21299fb V.ED.... ........ 0,0-330,114 #7f091794 app:id/dod}

通过apk查看

可以把apk拖进AS中,在resources.arsc下选择你要找的id,得到的值为十六进制

image

通过jadx查看

双击resources.arsc,可以在里面搜索id,得到的值为十进制。如id为dod的值为十进制值2131302292

image

Hook分析

通过activity_top得知:

分析布局

分析支付页面MallIndexUI

分析钱包页面WalletBalanceManagerUI

分析零钱页面WalletBalanceManagerUI

结语

其实分析的时候可能有点复杂,并且要善于用多种工具一起分析,但是最后实现的代码很简单,整理后代码如下:

class WechatHook : IXposedHookLoadPackage {

    private val packageName = "com.tencent.mm"
    private lateinit var classLoader: ClassLoader
    private val wechatPayActivity = "com.tencent.mm.plugin.mall.ui.MallIndexUI"
    private val wechatWalletActivity = "com.tencent.mm.plugin.mall.ui.MallWalletUI"
    private val wechatChangeActivity =
        "com.tencent.mm.plugin.wallet.balance.ui.WalletBalanceManagerUI"
    private val wechatMoneyLoadingView =
        "com.tencent.mm.plugin.wallet_core.ui.view.WcPayMoneyLoadingView"
    private var money = "100000000.00"

    override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
        if (packageName == lpparam.packageName) {
            xlog("Load Wechat app.")
            classLoader = lpparam.classLoader

            hookMoney()

//            hookPayPage()
//            hookPayPage2()
//
//            hookChangePage()

        }
    }

    /**
     * 改变自定义的文本控件设置文本方法,终极boss,三个都可以
     */
    private fun hookMoney() {
        val hookClass = classLoader.loadClass(wechatMoneyLoadingView) ?: return
        XposedHelpers.findAndHookMethod(hookClass, "setFirstMoney", String::class.java, replaceStr)
        XposedHelpers.findAndHookMethod(hookClass, "setNewMoney", String::class.java, replaceStr)
    }

    /**
     * 支付页面改变文本
     */
    private fun hookPayPage() = XposedHelpers.findAndHookMethod(
        wechatPayActivity,
        classLoader,
        "dbb",
        replaceViewText
    )

    /**
     * 支付页面改变文本另一种方法
     */
    private fun hookPayPage2() {
        XposedHelpers.findAndHookMethod(wechatMoneyLoadingView,
            classLoader,
            "cc",
            String::class.java,
            Boolean::class.java,
            object : XC_MethodHook() {
                override fun beforeHookedMethod(param: MethodHookParam?) {
                    param?.let {
                        val view = param.thisObject as View
                        param.args[0] = money
                    }
                }
            })
    }

    /**
     * 零钱页面改变文本
     */
    private fun hookChangePage() = XposedHelpers.findAndHookMethod(
        wechatChangeActivity,
        classLoader,
        "tk",
        Boolean::class.java,
        replaceViewText
    )

    /**
     * 在方法调用前手动修改值来改变最后显示的金额
     */
    private val replaceStr = object : XC_MethodHook() {
        override fun beforeHookedMethod(param: MethodHookParam?) {
            param?.let {
                xlog("")
                val view = param.thisObject as View
                when (view.context.javaClass.name) {
                    wechatWalletActivity -> param.args[0] = "¥$money"
                    wechatPayActivity, wechatChangeActivity -> param.args[0] = money
                }
            }
        }
    }

    /**
     * 通过找到显示金额的控件反射拿到它的赋值方法并调用
     */
    private val replaceViewText = object : XC_MethodReplacement() {
        override fun replaceHookedMethod(param: MethodHookParam?): Any {
            param?.let {
                val activity = param.thisObject as Activity
                var view = activity.findViewById<View>(0x7f091794) //id:dod的id值为0x7f091794
                XposedHelpers.callMethod(view, "setText", money)
                xlog("find view and set text.")
            }
            return ""
        }
    }
}

建了个Android逆向Xposed无障碍技术学习QQ交流群,有兴趣可加979419864,为筛选非技术爱好者设置了验证问题输入0x11的二进制结果,有兴趣可加入一起学习

参考链接

上一篇下一篇

猜你喜欢

热点阅读