吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 5491|回复: 10
收起左侧

[Android 原创] APP网络请求参数校验Sign,逆向分析分享,第2饭

[复制链接]
wxyzyou 发表于 2020-3-24 16:17
本帖最后由 wxyzyou 于 2020-3-24 16:17 编辑

第2个下饭的操作来了
本次APP post参数验签校验Sign逆向分析
老规矩,仅分享逆向分析过程,关键代码都有,还有截图,就不发APP了

APP的每次网络请求都带有Sign参数校验值
Fiddler抓到的包文

fd.jpg

老规矩使用ApkToolAid,对APP进行查壳,反编译
查到结果,未加壳,反编译正常,分析文件结构,正常的安卓APP (并非第1饭的ReactNative+NodeJS结构)

ck.jpg


用ApkToolAid再次生成app的jar包,方便我们使用 jd-gui 工具,查看JAVA明文代码 (反编译的文件是dex类型,需要再次转为jar查看)
第1饭里有人求 ApkToolAid工具,该工具在吾爱的爱盘里,自行下载
52.jpg


在jar包里搜索全局对象里的关键字 post的参数名 sign pwd  mobile 随便一个,会定位到多个结果,对比结果找到目标 onLoginClick 函数

在代码中可以看出函数添加了mobile和pwd参数,唯独没有 sign
经过代码分析,sign是在EcpGenerateSign类里的build函数内生成
pwd密码是123456
onLoginClick函数内可以看到 pwd是把密码123456转为MD5值了

dm1.jpg


dm2.jpg


在build函数内可以看到关键的一行代码
String str = ParamsSortUtils.formatUrlMap(this.paramMap, false, false);
把传递来的参数,通过ParamsSortUtils类的 formatUrlMap 函数,做了处理,返回给 str
然后 str+v2020global 生成MD5,就是Sign了
所以这个str的生成很重要
查看 formatUrlMap函数,可以看到是吧参数名和参数值做了一个拼接返回
拼接模式 从onLoginClick函数可以看到先传入了mobile,后传入pwd
所以从代码上的拼接方式,拼接的最终结果是
mobile=14709236399&pwd=e10adc3949ba59abbe56e057f20f883e
赋值给str
然后 str+v2020global  
最终结果
mobile=14709236399&pwd=e10adc3949ba59abbe56e057f20f883ev2020global
再次把结果生成MD5,就是Sign了


在下面的代码里,加入了分析结果和注释

dm3.jpg


[Java] 纯文本查看 复制代码
package com.globalspot.mall.http.base;

import com.globalspot.mall.activity.person.UserInfo;
import com.globalspot.mall.activity.person.UserInfo.UserInfoBean;
import com.globalspot.mall.http.rest.EmptyUtils;
import com.globalspot.mall.utils.Logger;
import com.globalspot.mall.utils.MD5Util;
import com.globalspot.mall.utils.ParamsSortUtils;
import com.globalspot.mall.utils.UserInfoHelper;
import com.google.gson.Gson;
import java.util.HashMap;
import java.util.Map;
import okhttp3.MediaType;
import okhttp3.RequestBody;

public class EcpGenerateSign
{
  private static ReqBodyBuilder builder;
  private static UserInfo user;
  
  public static ReqBodyBuilder put()
  {
    if (builder == null) {
      builder = new ReqBodyBuilder();
    }
    return builder;
  }
  
  public static ReqBodyBuilder put(String paramString, Object paramObject)
  {
    if (builder == null) {
      builder = new ReqBodyBuilder();
    }
    builder.put(paramString, paramObject);
    return builder;
  }
  
  public static class ReqBodyBuilder
  {
    private Map<String, Object> paramMap = new HashMap();
    
    public RequestBody build()
    {
      EcpGenerateSign.access$002(UserInfoHelper.getInstance().getUser());
      HashMap localHashMap = new HashMap();
      System.currentTimeMillis();
//判断是否已经登录,已登录就在参数里加入token和userSn参数
      if (UserInfoHelper.getInstance().isLogined())
      {
        Map localMap = this.paramMap;
        localObject = EcpGenerateSign.user.getToken();
        str = "";
        if (localObject == null) {
          localObject = "";
        } else {
          localObject = EcpGenerateSign.user.getToken();
        }
        localMap.put("token", localObject);
        localMap = this.paramMap;
        localObject = new StringBuilder();
        ((StringBuilder)localObject).append(EcpGenerateSign.user.getUserInfo().getUserSn());
        ((StringBuilder)localObject).append("");
        if (((StringBuilder)localObject).toString() == null) {
          localObject = str;
        } else {
          localObject = EcpGenerateSign.user.getUserInfo().getUserSn();
        }
        localMap.put("userSn", localObject);
      }
//关键代码
//对参数集合 this.paramMap 做处理返回给 str
      String str = ParamsSortUtils.formatUrlMap(this.paramMap, false, false);
      Object localObject = new StringBuilder();
//处理后的str 拼接
      ((StringBuilder)localObject).append(str);
//拼接 v2020global
      ((StringBuilder)localObject).append("v2020global");
//把拼接结果生成MD5,赋值给sign
      localObject = MD5Util.lowerCaseMD5(((StringBuilder)localObject).toString());
      this.paramMap.put("sign", localObject);

      localHashMap.putAll(this.paramMap);
      this.paramMap.clear();
      localObject = new StringBuilder();
      ((StringBuilder)localObject).append("参数 : ");
      ((StringBuilder)localObject).append(new Gson().toJson(localHashMap));
      Logger.eLong(((StringBuilder)localObject).toString());
      return RequestBody.create(MediaType.parse("application/json; charset=utf-8"), new Gson().toJson(localHashMap));
    }
    
    public ReqBodyBuilder put(String paramString, Object paramObject)
    {
      if (EmptyUtils.isEmpty(paramString)) {
        return this;
      }
      Object localObject = paramObject;
      if (EmptyUtils.isEmpty(paramObject)) {
        localObject = "";
      }
      this.paramMap.put(paramString, localObject);
      return this;
    }
  }
}


ParamsSortUtils类的 formatUrlMap函数

[Java] 纯文本查看 复制代码
public static String formatUrlMap(Map<String, Object> paramMap, boolean paramBoolean1, boolean paramBoolean2)
  {
    try
    {
      Object localObject = new java/util/ArrayList;
      ((ArrayList)localObject).<init>(paramMap.entrySet());
      paramMap = new com/globalspot/mall/utils/ParamsSortUtils$1;
      paramMap.<init>();
      Collections.sort((List)localObject, paramMap);
      StringBuilder localStringBuilder = new java/lang/StringBuilder;
      localStringBuilder.<init>();
      Iterator localIterator = ((List)localObject).iterator();

      while (localIterator.hasNext())
      {
//循环获取每个参数键名和键值 的map集合
        paramMap = (Map.Entry)localIterator.next();
        if (EmptyUtils.isNotBlank((String)paramMap.getKey()))
        {
//获取键名 案例 mobile
          String str = (String)paramMap.getKey();
//获取键值 案例 14709236399
          localObject = String.valueOf(paramMap.getValue());
          paramMap = (Map<String, Object>)localObject;
//判断参数2是否true
//true 对参键值进行URL编码
//这里是POST和GET类型参数的区别对待
//我们当前分析的模式为POST,调用函数时,参数2和3都是false,不做处理
          if (paramBoolean1) {
            paramMap = URLEncoder.encode((String)localObject, "utf-8").replace("+", "%20").replace("%3A", ":");
          }
//参数3为true时,把键名转为小写
          if (paramBoolean2)
          {
            localObject = new java/lang/StringBuilder;
            ((StringBuilder)localObject).<init>();
//参数名转为小写
            ((StringBuilder)localObject).append(str.toLowerCase());
            ((StringBuilder)localObject).append("=");
            ((StringBuilder)localObject).append(paramMap);
            localStringBuilder.append(((StringBuilder)localObject).toString());
          }
          else
          {
// false,不做参数名转小写处理
//拼接键名和键值,中间加个=号  mobile=14709236399
            localObject = new java/lang/StringBuilder;
            ((StringBuilder)localObject).<init>();
            ((StringBuilder)localObject).append(str);
            ((StringBuilder)localObject).append("=");
            ((StringBuilder)localObject).append(paramMap);
            localStringBuilder.append(((StringBuilder)localObject).toString());
          }
//在拼接结果尾部拼接 & 案例 mobile=14709236399&
          localStringBuilder.append("&");
        }
      }
//把整个参数map拼接完的结果,赋值给localObject 
//案例 mobile=14709236399&pwd=e10adc3949ba59abbe56e057f20f883e&
      localObject = localStringBuilder.toString();
      paramMap = (Map<String, Object>)localObject;
//判断 localObject 不为空字符串
      if (!((String)localObject).isEmpty()) {
//删除掉尾部最后1个字符,也就是多拼接的1个 &
//案例 mobile=14709236399&pwd=e10adc3949ba59abbe56e057f20f883e
        paramMap = ((String)localObject).substring(0, ((String)localObject).length() - 1);
      }
      return paramMap;
    }
    catch (Exception paramMap) {}
    return null;
  }


免费评分

参与人数 6吾爱币 +12 热心值 +6 收起 理由
qtfreet00 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
ricohrh + 1 + 1 热心回复!
西枫游戏 + 1 + 1 这个协议分析的可还行
名字以后会后悔 + 1 + 1 thank!!
gaoyonggang66 + 1 + 1 热心回复!
那年夏天52 + 1 + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

那年夏天52 发表于 2020-3-24 16:41
感谢分享技术教程
gaoyonggang66 发表于 2020-3-24 17:15
小勤 发表于 2020-3-25 11:19
w456789 发表于 2020-3-25 16:28
感谢楼主分享 学到不少
17696091221 发表于 2020-3-25 20:13
感谢分享!学习了。
15135094220 发表于 2020-3-25 20:14
哇哦感谢楼主分享
a657938016 发表于 2020-3-26 17:06
apktool助手哪里下载啊,老哥
 楼主| wxyzyou 发表于 2020-3-26 17:41
a657938016 发表于 2020-3-26 17:06
apktool助手哪里下载啊,老哥

52的爱盘
a657938016 发表于 2020-3-26 18:25

没找到啊apktool助手2.4
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 20:36

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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