开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

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

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


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

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

查看: 15373|回复: 8
收起左侧

[交流] 北京时间APP登陆全过程分析RSA+Sign(图文+视频)

[复制链接]

结帖率:100% (1/1)
发表于 2017-7-12 15:30:23 | 显示全部楼层 |阅读模式   湖南省娄底市


图片看不到的话,下载word文档观看吧
App名字:北京时间
加固情况:未加固
分析工具:jeb2.x 雷电模拟器FD
过程
1、 FD抓登陆包 输入账号 1615457734@qq.com  密码 123456789 连抓2次
2、 提示邮箱未注册。切换到FD看一下提交表单
3、 通过对比发现,变动的数据
Password:对js有经验的人,可以大致锁定为RSA加密
u_time:时间戳(10位)
u_salt:(像MD5的某个数据段)
u_sign:(32位MD5+u_salt)
完整表单如下:
http://api.btime.com/user/login?protocol=1&mobile=1615457734@qq.com&password=LL8W1uMphsVTIPMClnsHQlAN/dWipeuP/5MHr/%2B/waGTYPRGrWgpvDiTIWcQ2AlXAHyJTwENVw84%0AFRK7xBh07/kdwbHe47L/wPdQoGhHgLaizZLh4QGte6GkYDYk72jhHwtnFsQG4OpusLs1LJ9dd9bq%0AOpkEuaPzXkDQCNw3258%3D%0A&imgcode=&vcode=&os_ver=22&u_time=1499840971&sid=&pro=&src=lx_android&token=4a74dc97f321360008dc126afea827e4&carrier=&push_id=3a466e763b20cf13a5567e962a0d60ae&os_type=Android&net=WIFI&os=android_x86-userdebug%205.1.1%20LMY48Z%20eng.denglibo.20170213.214219%20test-keys&u_salt=d2c032de&u_sign=bc06e9ba4231ff9eeac94f26dbcbe281d2c032de
4、 其实可以明显看出来u_sign和u_salt是有关系的。所以,我们可以先搞定这2个
搜索 u_salt或者u_sign,都可以定位到以下代码,其中2处高亮,分别是salt和sign的算法(先分析salt,再分析sign)
        private static Map a(aa arg10) {
       HashMap v4_1;
       if(arg10 == null) {
           Map v4 = null;
       }
       else {
           TreeMap v3 = new TreeMap();
           if(arg10.d() != null&& ((arg10.d() instanceof q))) {
                ab v1 = arg10.d();
                int v2;
                for(v2 = 0; v2 <((q)v1).a(); ++v2) {
                   v3.put(URLDecoder.decode(((q)v1).a(v2)), URLDecoder.decode(((q)v1).b(v2)));
                }
           }
           if(arg10.a() != null) {
                for(v2 = 0; v2 <arg10.a().m(); ++v2) {
                    v3.put(arg10.a().a(v2),arg10.a().b(v2));
                }
           }
           Stringv6 = f.a();
            v3.put("u_salt", v6);
           StringBuilder v5 = new StringBuilder();
           Iterator v8 = v3.entrySet().iterator();
           while(v8.hasNext()) {
                Object v0 = v8.next();
               v5.append(((Map$Entry)v0).getKey());
                v5.append("=");
               v5.append(((Map$Entry)v0).getValue());
                v5.append("&");
           }
           if(v5.length() > 0) {
                v5.deleteCharAt(v5.length() -1);
           }
           v5.append("&");
           v5.append(com.btime.account.a.d);
           v4_1 = new HashMap();
           ((Map)v4_1).put("u_sign",f.a(v5.toString()) + v6);
            ((Map)v4_1).put("u_salt",v6);
        }
       return ((Map)v4_1);
    }
String v6 = f.a();
v3.put("u_salt", v6);
u_salt=v6=f.a();进入f.a(下面是整个f的结构。注意看高亮部分)
String v1 = f.a(String.valueOf(Math.random()));
Math.random() 取随机时间戳,然后调用a,仔细下去看,就发现,a是转换为utf8之后,在调用下一个a也就是MD5
  v4= v1.substring(0, 8);//计算完成之后,取左边8
综述:u_salt就是随即时间戳的MD5结果的左8
public class f{
    public staticString a(){
       int v6= 8;
        String v1 = f.a(String.valueOf(Math.random()));
       String v4= v1;
       try {
           if(TextUtils.isEmpty(((CharSequence)v4))) {
                returnv4;
           }
           if(v4.length() <= v6){
                returnv4;
           }
           v4 =v1.substring(0, 8);
       }
       catch(Exceptionv0) {
           v0.printStackTrace();
       }
       return v4;
    }
    public staticString a(String arg2) {
       String v1;
       try {
           v1 = f.a(arg2.getBytes("UTF-8"));
       }
       catch(UnsupportedEncodingExceptionv0) {
           v0.printStackTrace();
           v1 = "";
       }
       return v1;
    }
    public staticString a(byte[] arg3){
       String v2;
       try {
           MessageDigest v1 = MessageDigest.getInstance("MD5");
           v1.update(arg3);
           v2 = e.a(v1.digest());
       }
       catch(Exceptionv0) {
           v0.printStackTrace();
           v2 = "";
       }
       return v2;
    }
}

继续看u_sign
((Map)v4_1).put("u_sign", f.a(v5.toString()) + v6);
f.a是md5算法
sign就是v5的MD5算法之后加上salt 一共就是40位
主要分析v5就可以了。
我们可以在f.a的头部注入代码或者hook得到v5的值,这里我选择jeb动态调试
附加失败多试几次。由于word文档排版会乱,所以我截个图
carrier=&imgcode=&mobile=1615457734@qq.com&net=WIFI&os=android_x86-userdebug5.1.1 LMY48Z eng.denglibo.20170213.214219test-keys&os_type=Android&os_ver=22&password=xNhOyKUkrQEo1R5aMKmtf2hpJ0lADikLcCU1dk8xdIiaATCjuf+F7Omr5F8laSl3iLG71jxbANir
aRkxwjlDRdhgiSAK0OZjPhudjT6EB++7fC0C/E1zw3EQb11wATmzBTW08Vl41AhLLQFSII405xbo
rUUwB0T9tIxikVsDmJQ=
&pro=&protocol=1&push_id=3a466e763b20cf13a5567e962a0d60ae&sid=&src=lx_android&token=4a74dc97f321360008dc126afea827e4&u_salt=deb986f0&u_time=1499842527&vcode=&d1ebg72e85b817353de4e28efdc180d1

需要注意的是,加密的密码是76个字符换个行然后提交数据内,需要替换,否则会提示签名错误(具体各位自己测试吧。这时候,我们就把sign的加密搞出来了)这些里面,除了password,其他可以不用管,固定即可,总之,和提交的数据一样即可
我们继续查找password,开始说了,很可能是RSA加密,搜一下RSA/试试
分别进去看看吧! 下断返回上一层
public static byte[] a(byte[] arg10,String arg11)throws Exception{
       byte[] v0_2;
       int v8= 245;
       int v0= 0;
       Class v2= bh.class;
       __monitor_enter(v2);
       try {
           PrivateKey v1= KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(cn.b(arg11)));
           Cipher v3= Cipher.getInstance("RSA/ECB/PKCS1Padding");
           v3.init(1, ((Key)v1));
           int v4= arg10.length;
           ByteArrayOutputStream v5 = new ByteArrayOutputStream();
           int v1_1;
           for(v1_1= 0; v4- v0 > 0;v1_1 = v9) {
                v0_2= v4 - v0> v8 ? v3.doFinal(arg10, v0, 245) :v3.doFinal(arg10, v0, v4 - v0);
                v5.write(v0_2, 0, v0_2.length);
                v0= v1_1 + 1;
                intv9 = v0;
                v0*= 245;
           }
           v0_2 = v5.toByteArray();
           v5.close();
       }
       catch(Throwablev0_1) {
           goto label_41;
       }
       __monitor_exit(v2);
       return v0_2;
    label_41:
       __monitor_exit(v2);
       throw v0_1;
}
ConnectionServiceManager 翻译得知 连接服务经理 也许这个是个私钥,能解密(猜测而已),那继续看 RSA/None/PKCS1Padding 这个吧
this.b = cn.a(bh.a(cj.f(arg4).getBytes("UTF-8"),"MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDCEYwdO3V2ANrhApjqyk7X8FH5AEaWly58kP9IDAhMqwtIbmcJrUK9oO9Afh3KZnOlDtjiowy733YqpLRO7WBvdbW/c4Dz/d3dy/m+6HMqxaak+GQQRHw/VPdKciaZ3eIZp4MWOyIQwiFSQvPTAo/Na8hV4SgBZHB3lGFw0yu+BmG+h32eIE6p4Y8EDCn+G+yzekX+taMrWTQIysledrygZSGPv1ukbdFDnH/xZEI0dCr9pZT+AZQl3o9a2aMyuRrHM0oupXKKiYl69Y8fKh1Tyd752rF6LrR5uOb9aOfXt18hb+3YL5P9rQ+ZRYbyHYFaxzBPA2jLq0KUQ+Dmg7YhAgMBAAECggEAL9pj0lF3BUHwtssNKdf42QZJMD0BKuDcdZrLV9ifs0f54EJY5enzKw8j76MpdV8N5QVkNX4/BZR0bs9uJogh31oHFs5EXeWbb7V8P7bRrxpNnSAijGBWwscQsyqymf48YlcL28949ujnjoEz3jQjgWOyYnrCgpVhphrQbCGmB5TcZnTFvHfozt/0tzuMj5na5lRnkD0kYXgr0x/SRZcPoCybSpc3t/B/9MAAboGaV/QQkTotr7VOuJfaPRjvg8rzyPzavo3evxsjXj7vDXbN4w0cbk/Uqn2JtvPQ8HoysmF2HdYvILZibvJmWH1hA58b4sn5s6AqFRjMOL7rHdD+gQKBgQD+IzoofmZK5tTxgO9sWsG71IUeshQP9fe159jKCehk1RfuIqqbRP0UcxJiw4eNjHs4zU0HeRL3iF5XfUs0FQanO/pp6YL1xgVdfQlDdTdk6KFHJ0sUJapnJn1S2k7IKfRKE1+rkofSXMYUTsgHF1fDp+gxy4yUMY+h9O+JlKVKOwKBgQDDfaDIblaSm+B0lyG//wFPynAeGd0Q8wcMZbQQ/LWMJZhMZ7fyUZ+A6eL/jB53a2tgnaw2rXBpMe1qu8uSpym2plU0fkgLAnVugS5+KRhOkUHyorcbpVZbs5azf7GlTydR5dI1PHF3Bncemoa6IsEvumHWgQbVyTTz/O9mlFafUwKBgQCvDebms8KUf5JY1F6XfaCLWGVl8nZdVCmQFKbA7Lg2lI5KS3jHQWsupeEZRORffU/3nXsc1apZ9YY+r6CYvI77rRXd1KqPzxos/o7d96TzjkZhc9CEjTlmmh2jb5rqx/Ns/xFcZq/GGH+cx3ODZvHeZQ9NFY+9GLJ+dfB2DX0ZtwKBgQC+9/lZ8telbpqMqpqwqRaJ8LMn5JIdHZu0E6IcuhFLr+ogMW3zTKMpVtGGXEXi2M/TWRPDchiO2tQX4Q5T2/KW19QCbJ5KCwPWiGF3owN4tNOciDGh0xkSidRc0xAh8bnyejSoBry8zlcNUVztdkgMLOGonvCjZWPSOTNQnPYluwKBgCV+WVftpTk3l+OfAJTaXEPNYdh7+WQjzxZKjUaDzx80Ts7hRo2U+EQT7FBjQQNqmmDnWtujo5p1YmJC0FT3n1CVa7g901pb3b0RcOziYWAoJi0/+kLyeo6XBhuLeZ7h90S70GGh1o0V/j/9N1jb5DCL4xKkvdYePPTSTku0BM+n"));
       }
       catch(Throwablev0) {
           ce.a(v0, "ConnectionServiceManager","ConnectionServiceManager");
       }
}
RSA/None/PKCS1Padding
下断返回上一层
    public static byte[] a(byte[] arg7, Stringarg8) throws Exception {
       PublicKey v4 = KeyFactory.getInstance(r.a).generatePublic(newX509EncodedKeySpec(Base64.decode(arg8, 0)));
       Cipher v0 = Cipher.getInstance("RSA/None/PKCS1Padding","BC");
       v0.init(1, ((Key)v4));
       return v0.doFinal(arg7);
}
上一层得到,这个,明显是计算密码了,看下e.h等于什么 v2就是输入的密码 e.h双击进去得到密钥
  public StringgetPassword() {
       String v2= this.a.getText().toString();
       try {
            v2= new String(Base64.encode(r.a(v2.getBytes(), e.h), 0));
       }
       catch(Exceptionv1) {
           v1.printStackTrace();
           d.d("错误");
       }
       catch(NullPointerExceptionv1_1) {
           v1_1.printStackTrace();
           d.d("/公钥数据为空");
       }
       catch(InvalidKeySpecExceptionv1_2) {
           v1_2.printStackTrace();
           d.d("/公钥非法");
       }
       catch(NoSuchAlgorithmExceptionv1_3) {
           v1_3.printStackTrace();
           d.d("无此算法");
       }
       return v2;
    }
    static {
        e.a = u.a("bjtime");
        e.b = e.a + "videos";
        e.c = "template";
        e.d = "common";
        e.e = "shield.html";
        e.f = "template";
        e.g = "index.lua";
        e.h ="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDaMWeSroknflaOH2aKc3otA0oe\nl/dI4jPXAGNrC3Ecyp8BmDJLg5zOWU0AVNUuU+xjq95AUKOs5n2cNVordqU53qRg\nLC9pxcvLf893k3Q58emdfmgHfgsCczKn7uvg2hwDsFXttbDXNc6j6QIQatQUFNXL\nHHSrlQMnpVB/sj0dKQIDAQAB\n";
        e.i ="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCyxsDoVdlw5wCTvqg+RP6dwrKN\nhS0JR7ZgwE89o9IFy2+FIYQws/+681ABL/Vbb5+omhBRt3sIuHRoB5fvGGNFjaKQ\nKa3YvS+ENrdt5h5c52TBTuoTlY0FtY/CQ1Jm0bsC5c1Sjww93+DrPPPPQpZ5pXeV\neVhusY6UyoUQnMksSQIDAQAB";
    }
综上所述
1、 密码是 RSA/None/PKCS1Padding 的加密方式实际可以认为是
RSA/ PKCS1Padding的加密
2、 密钥是
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDaMWeSroknflaOH2aKc3otA0oe\nl/dI4jPXAGNrC3Ecyp8BmDJLg5zOWU0AVNUuU+xjq95AUKOs5n2cNVordqU53qRg\nLC9pxcvLf893k3Q58emdfmgHfgsCczKn7uvg2hwDsFXttbDXNc6j6QIQatQUFNXL\nHHSrlQMnpVB/sj0dKQIDAQAB\n";
3、 Sign是MD5(参数)+salt
4、 Salt是MD5(随机时间戳)的左8位
5、 写代码看看效果(写代码注意的是密码每隔76位换行一次)

附带word文档
视频下载地址:下载地址:链接:https://eyun.baidu.com/s/3qYRW2Ji 密码:iuSw 违规请删除




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

评分

参与人数 1好评 +1 精币 +1 收起 理由
调皮的男孩 + 1 + 1 新技能已get√

查看全部评分

本帖被以下淘专辑推荐:

发表于 2018-6-23 16:33:42 | 显示全部楼层   重庆市重庆市
这会得好仔细,要是我,应该没那么好的耐心.佩服.
回复 支持 反对

使用道具 举报

发表于 2017-7-24 15:28:33 | 显示全部楼层   北京市北京市
很不错,值得学习
回复 支持 反对

使用道具 举报

结帖率:75% (9/12)

签到天数: 4 天

发表于 2017-7-14 02:06:09 | 显示全部楼层   山西省太原市
看看什么套路
回复 支持 反对

使用道具 举报

发表于 2017-7-12 21:51:49 | 显示全部楼层   江西省抚州市
东西不错。嗯。看看。参考一下
回复 支持 反对

使用道具 举报

结帖率:93% (27/29)
发表于 2017-7-12 18:27:49 | 显示全部楼层   广东省东莞市
感谢分享
回复 支持 反对

使用道具 举报

结帖率:100% (1/1)

签到天数: 19 天

 楼主| 发表于 2017-7-12 18:03:38 | 显示全部楼层   湖南省娄底市
戒撸大队队长 发表于 2017-7-12 16:42
顶楼主啦..希望楼主多发精品好帖啦.....

回复 支持 反对

使用道具 举报

结帖率:100% (1/1)
发表于 2017-7-12 17:50:56 | 显示全部楼层   江苏省南京市
东西不错。嗯。看看。参考一下
回复 支持 反对

使用道具 举报

头像被屏蔽
结帖率:89% (40/45)
发表于 2017-7-12 16:42:49 | 显示全部楼层   江苏省苏州市
顶楼主啦..希望楼主多发精品好帖啦.....
回复 支持 反对

使用道具 举报

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

本版积分规则 致发广告者

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

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

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