rcbing 发表于 2018-5-29 15:10

DES/CBC/PKCS5Padding 简单动态key分析一例

本帖最后由 rcbing 于 2018-5-29 15:14 编辑

菜鸟文章,大佬们请手下留情~
平日所见app的http请求数据加密大多是固定key和iv,偶尔有见着动态key或者iv的,都没记录下来,本次见着一个,于是把过程记录下来,大家分享。
拿到app,国际惯例,查壳,抓包。可惜是某数字壳,不管了,先抓包吧,下面是抓取的检查帐号是否存在的请求。
POST https://**********/login/checkPhoneUnique.htmHTTP/1.1
Connection: Keep-Alive
chnflg: Androidversion: 4.2.1
timeStamp: 1527502081724
deskeyVersion: 2
deviceKey: K4yeP+CawIfcY4lxCy3b+e50VI4iwjcA
memberToken:
Content-Type: application/x-www-form-urlencoded;charset=utf-8
Content-Length: 107
Host: Encoding: gzip
User-Agent: okhttp/3.8.1

data=azyNgHqwV9ZX%2BJiU8RU2WNEIOVhG6aP3GV%2BQrb%2BBFpVPhOm0dCekTyySpczlAKfF8v63JrI8mg6Gb7C5l949fZyI98zMLC1j
返回提示 帐号已存在,先不管。看这请求,deviceKey和正文中的data是已经加密了的,
好吧,日常砸壳子,放jadx中分析,看请求协议头,目测deviceKey重复应该比较少,先从它入手吧,搜索deviceKey:

搜到两处,均有encryptDES字样,挑第一条进去看看

可以看到ag方法中对请求协议头进行了构造,它有两个String形参,str可以看出是timeStamp,str2与c.JX 则带入了DES方法,我们来看看encryptDES长什么样

从上图中可以看到,采用的是DES/CBC/PKCS5Padding算法,iv是固定值。参数1是加密的原文,str2是Key。
回过头,我们再来看看是哪里调用了ag方法

可以看出参数valueOf是加密前的数据,参数bq是时间戳带入bq方法得到的返回值做为DesKey,那么继续跟进bq方法查看:

可以看到bq方法,先判断了一下全局变量JS不为空的话,继续把时间戳带入了genMD5Str方法,好吧,继续看一下genMD5Str方法长什么样,

可以看到就是hex表现形式的md5。让我们继续回到bq方法,它第一步先判断了全局变量JS,可以看到变量JS是在上面的aq方法中,通过读取dynamic_sun.bmp文件,带入b方法得到的。
那么这个JS变量的值如何得到呢,难道需要去还原java代码,计算出这个值?咦,下面有条log语句Log.d("*********", "dynamicKey:" + JS);我们去碰碰运气,万一程序猿哥哥忘了关log了呢,
打开android studio查看日志,过滤关键字dynamicKey,手机上清除app的数据,重新打开app。在app运行的一瞬间,这条日志就打印出来啦,真是中了大奖般的运气!窃喜{:1_918:}
得到JS的值(原值并非如此,这里是我随便写的)
JS="QT6441qwhM2e6B3be8gq64bxFnRY88O4E2”//假装这个值有N*100个字符
得到这个值之后,就开始分析本例中的核心代码,到底是怎么通过时间戳生成的动态DesKey的?继续看
      int length = genMD5Str.length();    //时间戳md5后字符串的长度
      length = Integer.parseInt(genMD5Str.substring(length - 2, length), 16) % 100;
      return JS.substring(length * 8, (length * 8) + 8);
参数1:genMD5Str.substring(length - 2, length) 是取出md5值的最后两位参数2:16Integer.parseInt是将指定基数的字符串表示形式转换为等效的16位无符号整数 最后模除100,就是length的值
例如parseInt中带入”ef”相当于是14*16+15 = 239 再模除100,就是length的值 Return 语句中 取出JS下标length * 8到(length * 8)+ 8的值做Des动态Key

By the way :Integer.parseInt(genMD5Str.substring(length - 2, length), 16) % 100;
语句用C# 实现的话,如下:Convert.ToByte(genMD5Str.Substring(length - 2, 2), 16) % 100;
最后,也懒得去调试或者写hook插件了,直接在as中还原相关代码,把请求中的时间戳1527502081724带入计算得到DesKey,可以正常还原出deviceKey与请求正文。
写在最后:这种动态key的思路值得写代码时借鉴,让我们一起学习进步吧。   


第一次发帖,言词不清,逻辑混乱,还有点小累,默默在论坛上跟大佬们学了这么久,在此,向论坛各位大佬致敬!感谢!

yikuaidao 发表于 2018-5-29 18:01

分析的很不错

Taobi 发表于 2018-5-29 18:02

沙发支持下

wisoft 发表于 2018-5-29 18:38

学习了,感谢分享

拾梦 发表于 2018-5-31 10:58

谢谢分享

xiaoxin520 发表于 2018-5-31 15:03

不错不错,很有长进

hackerchen 发表于 2018-7-30 22:00

不错 可惜没分了 {:1_937:}
页: [1]
查看完整版本: DES/CBC/PKCS5Padding 简单动态key分析一例