基於xposed Hook框架實現個人免簽支付方案

  • 2019 年 11 月 10 日
  • 筆記

我的個人網站如何實現支付功能?

  想必很多程式設計師都有過想開發一個自己的網站來獲得一些額外的收入,但做這件事會遇到支付這個問題。目前個人網站是無法實現支付功能的。

  今天我就給大家分享一下我的實現方案:《基於xposed逆向微信、支付寶、雲閃付來實現個人免簽支付方案》

  測試頁面(點我)  

  接下來給大家簡單分享一下實現過程,這個過程其實是非常複雜的,關鍵點在於如何逆向微信支付寶雲閃付這些App,找到核心函數鉤子,然後寫一個hook程式來模擬調用這些方法,來實現根據服務端傳過來的金額,訂單號自動調用微信支付寶生成支付二維碼的函數得到相對應的支付二維碼再傳給服務端,然後監聽微信支付寶的支付成功消息最終回調給服務端實現支付成功通知。這裡面用到的核心技術點有:xposed逆向框架、apk反編譯,網路抓包,apk動態調試等技術。

  像微信支付寶這些apk反編譯後的程式碼基本上都是天書一樣的,嚴重混淆過的程式碼。想從中找到核心程式碼並非易事,下面我貼一些核心程式碼吧。

hook微信二維碼生成函數

private void hookQRCreat(final ClassLoader appClassLoader, final Context context) {              Class<?> clazz = XposedHelpers.findClass("com.tencent.mm.plugin.collect.b.s", appClassLoader);          XposedBridge.hookAllMethods(clazz, "a", new XC_MethodHook() {              @Override              protected void beforeHookedMethod(MethodHookParam param)                      throws Throwable {              }                @Override              protected void afterHookedMethod(MethodHookParam param) {                  try {                      LogUtils.log("hookQRCreat start:");                      QrBean qrBean = new QrBean();                      qrBean.setChannel(QrBean.WECHAT);                        Field moneyField = XposedHelpers.findField(param.thisObject.getClass(), "kcp");                      Double money = (Double) moneyField.get(param.thisObject);                      LogUtils.log("hookQRCreat money:"+money.toString());                      Field markField = XposedHelpers.findField(param.thisObject.getClass(), "desc");                      String mark = (String) markField.get(param.thisObject);                      LogUtils.log("hookQRCreat mark:"+mark);                      Field payurlField = XposedHelpers.findField(param.thisObject.getClass(), "kco");                      String payurl = (String) payurlField.get(param.thisObject);                      LogUtils.log("hookQRCreat payurl:"+payurl);                          qrBean.setMark_sell(mark);                      qrBean.setUrl(payurl);                        LogUtils.log( "com.tencent.mm.plugin.collect.b.s qrBean:"+ JSON.toJSONString(qrBean));                      Intent broadCastIntent = new Intent();                      broadCastIntent.putExtra("data", qrBean.toString());                      broadCastIntent.setAction(HookMain.RECEIVE_QR_WECHAT);  //                broadCastIntent.setComponent( new ComponentName( "com.sjk.tpay" ,  //                        "com.sjk.tpay.ReceiverMain") );                      context.sendBroadcast(broadCastIntent);                      LogUtils.log("hookQRCreat end:"+JSON.toJSONString(param));                  }catch (Exception e){                      LogUtils.log("hookQRCreat exception:"+Log.getStackTraceString(e));                  }              }          });      }  

  

hook支付寶二維碼生成函數

private void hookQRCreat(final ClassLoader appClassLoader, final Context context) {          XposedHelpers.findAndHookMethod("com.alipay.mobile.payee.ui.PayeeQRSetMoneyActivity", appClassLoader, "a",                  XposedHelpers.findClass("com.alipay.transferprod.rpc.result.ConsultSetAmountRes", appClassLoader), new XC_MethodHook() {                      @Override                      protected void afterHookedMethod(MethodHookParam param) throws Throwable {                            Field moneyField = XposedHelpers.findField(param.thisObject.getClass(), "g");                          String money = (String) moneyField.get(param.thisObject);                            Field markField = XposedHelpers.findField(param.thisObject.getClass(), "c");                          Object markObject = markField.get(param.thisObject);                          String mark = (String) XposedHelpers.callMethod(markObject, "getUbbStr");                            Object consultSetAmountRes = param.args[0];                          Field consultField = XposedHelpers.findField(consultSetAmountRes.getClass(), "qrCodeUrl");                          String payurl = (String) consultField.get(consultSetAmountRes);                            Field consultField2 = XposedHelpers.findField(consultSetAmountRes                                  .getClass(), "printQrCodeUrl");                          String payurloffline = (String) consultField2.get(consultSetAmountRes);                              QrBean qrBean = new QrBean();                          qrBean.setChannel(QrBean.ALIPAY);                          qrBean.setMark_sell(mark);                          qrBean.setUrl(payurl);                            Intent broadCastIntent = new Intent()                                  .putExtra("data", qrBean.toString())                                  .setAction(RECEIVE_QR_ALIPAY);                          context.sendBroadcast(broadCastIntent);                      }                  });      }  

  

hook雲閃付二維碼生成函數

public static void GenQrCode(final String paramString1, final String paramString2, final String bankName, final String bankNo) {          new Thread(new Runnable() {              public void run() {                  try {                      Object obj1 = paramString2;                      Object obj2 = new BigDecimal(paramString1);                      obj2 = ((BigDecimal) obj2).setScale(2, RoundingMode.HALF_UP).toPlainString().replace(".", "");  //                    LogUtils.getInstance().saveLog("GenQrCode begin :" + obj1 + obj2);                      Object obj3 = new StringBuilder();                      ((StringBuilder) obj3).append("https://pay.95516.com/pay-web/restlet/qr/p2pPay/applyQrCode?txnAmt=");                      ((StringBuilder) obj3).append(MainHook.Enc((String) obj2));                      ((StringBuilder) obj3).append("&cityCode=");                      ((StringBuilder) obj3).append(MainHook.Enc(MainHook.getcityCd()));                      ((StringBuilder) obj3).append("&comments=");                      ((StringBuilder) obj3).append(MainHook.Enc((String) obj1));                      ((StringBuilder) obj3).append("&virtualCardNo=");  //                    ((StringBuilder) obj3).append(MainHook.encvirtualCardNo);                      CardInfo cardInfo = getEncvirtualCardNo(bankName, bankNo);                      if (cardInfo == null) {                          throw new Exception("找不到對應的下單卡");                      }                      cardInfo.setAccount(ysfAccount);                      ((StringBuilder) obj3).append(Enc(cardInfo.getVirtualCardNo()));                      obj1 = ((StringBuilder) obj3).toString();                      obj2 = HttpHelper.getInstance().getOkHttpClient();                      obj3 = new okhttp3.Request.Builder();                      Request.Builder localBuilder = ((Request.Builder) obj3).url((String) obj1).header("X-Tingyun-Id", MainHook.getXTid());  //                    LogUtils.getInstance().saveLog("GenQrCode url:" + obj1);                      obj3 = new StringBuilder();                      ((StringBuilder) obj3).append("0;");                      ((StringBuilder) obj3).append(System.currentTimeMillis());                        obj3 = ((OkHttpClient) obj2).newCall(localBuilder.header("X-Tingyun-Lib-Type-N-ST", ((StringBuilder) obj3).toString())                              .header("sid", MainHook.getSid()).header("urid", MainHook.geturid()).header("cityCd", MainHook.getcityCd())                              .header("locale", "zh-CN").header("User-Agent", "Android CHSP").header("dfpSessionId", MainHook.getDfpSessionId())                              .header("gray", MainHook.getgray()).header("key_session_id", "").header("Host", "pay.95516.com").build()).execute().body().string();                      obj1 = MainHook.Dec((String) obj3);                      obj2 = new StringBuilder();                      ((StringBuilder) obj2).append("GenQrCode RSP=>");                      ((StringBuilder) obj2).append((String) obj1);                      MainHook.mlog(obj2.toString());                      try {                          obj2 = new JSONObject((String) obj1);                          String certificate = ((JSONObject) obj2).getJSONObject("params").getString("certificate");                          QRInfo qrInfo = new QRInfo(certificate, paramString2);                          qrInfo.setRemark(JSON.toJSONString(cardInfo));                          String body = JSON.toJSONString(qrInfo);                          Intent localIntent = new Intent("websocket.sendmsg");                          localIntent.putExtra("data", "qr:" + body);                          MainHook.getContext().sendBroadcast(localIntent);                      } catch (Exception ex) {                          LogUtils.getInstance().saveLog("二維碼廣播發送異常:" + ex.getMessage());                      }                      return;                  } catch (Exception ex) {                      LogUtils.getInstance().saveLog("GenQrCode異常:" + ex.getMessage());                  }              }          }).start();      }  

  有問題的朋友可以給我留言或者加我Q好友