开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

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

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


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

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

查看: 8915|回复: 13
收起左侧

[技术专题] 贝壳找房 APP Base64 + sha1 加密算法分析

[复制链接]
结帖率:100% (1/1)
发表于 2018-8-21 20:09:02 | 显示全部楼层 |阅读模式   上海市上海市
本帖最后由 小范q 于 2018-8-21 20:13 编辑

PS:APP 提供来源
app 下载 地址:
http://sj.qq.com/myapp/detail.htm?apkName=com.lianjia.beike

app 提供来源:
https://bbs.125.la/forum.php?mod=viewthread&tid=14206248&highlight=%B1%B4%BF%C7

第一步 抓登陆抓包:

  1. POST /user/account/loginByPasswordV2 HTTP/1.1
  2. Page-Schema: register%2Fpasswordlogin
  3. Cookie: lianjia_udid=358640473966373;lianjia_ssid=04e25204-02bc-4200-8138-cec40a866833;lianjia_uuid=7b02a687-94c5-442d-80eb-f22fd53dbf05
  4. Lianjia-City-Id: 110000
  5. extension: lj_imei=358640473966373&lj_duid=Dul/bZPpYUEo8BBm6OPV2GO9WcN5CjiI6ryuDQFdVWjeEUypql8j5ff6Mv/WSDwkzpK9E1RX+Z5Gbruqh0pc3faw&lj_android_id=5592dcc6b1f0db33&lj_device_id_android=358640473966373&mac_id=02:00:00:00:00:02
  6. User-Agent: Beike1.6.1;oppo oppo+a59m; Android 5.1.1
  7. Lianjia-Channel: Android_ke_tencentt
  8. Lianjia-Device-Id: 358640473966373
  9. Lianjia-Version: 1.6.1
  10. <span style="background-color: yellow;">Authorization: MjAxODAxMTFfYW5kcm9pZDo0M2M2MjcwMTBiZWMwMWJjY2U0YzI0ZmRiOTcyMTY1ODJkNzA4YzQy</span>
  11. Lianjia-Im-Version: 2.15.0
  12. Content-Type: application/x-www-form-urlencoded
  13. Content-Length: 65
  14. Host: app.api.ke.com
  15. Connection: Keep-Alive
  16. Accept-Encoding: gzip

  17. mobile_phone_no=13812345678&password=123456&request_ts=1534851761
复制代码

第二步 分析加密主要参数分析:

Authorization: MjAxODAxMTFfYW5kcm9pZDo0M2M2MjcwMTBiZWMwMWJjY2U0YzI0ZmRiOTcyMTY1ODJkNzA4YzQy

第三步 逆向找到其主要算法

  1. --------------------------------------------------------------------------------------------------------------------------
  2.     public Response intercept(Interceptor$Chain arg13) throws IOException {
  3.         RequestBody v0_1;
  4.         long v10 = 1000;
  5.         String v0 = null;
  6.         String v1 = BaseSharedPreferences.a().d();
  7.         String v2 = CityConfigCacheHelper.a().f();
  8.         Request$Builder v3 = arg13.request().newBuilder();
  9.         String v4 = arg13.request().url().uri().toString();
  10.         HashMap v5 = new HashMap();
  11.         if(!Tools.d(v1)) {
  12.             v3.addHeader("Lianjia-Access-Token", v1);
  13.         }

  14.         if(!Tools.d(v2)) {
  15.             v3.addHeader("Lianjia-City-Id", v2);
  16.         }

  17.         HashMap v1_1 = new HashMap();
  18.         v1_1.put("mac_id", DeviceUtil.s(APPConfigHelper.c()));
  19.         v1_1.put("lj_device_id_android", DeviceUtil.x(APPConfigHelper.c()));
  20.         v1_1.put("lj_android_id", DeviceUtil.y(APPConfigHelper.c()));
  21.         v1_1.put("lj_imei", DeviceUtil.z(APPConfigHelper.c()));
  22.         v1_1.put("lj_duid", BaseSharedPreferences.a().s());
  23.         v3.addHeader("extension", Tools.a(v1_1));
  24.         if("GET".equalsIgnoreCase(arg13.request().method())) {
  25.             v0 = HttpUtil.a().b(v4, ((Map)v5));
  26.         }
  27.         else if("POST".equalsIgnoreCase(arg13.request().method())) {
  28.             if((arg13.request().body() instanceof FormBody)) {
  29.                 v0_1 = arg13.request().body();
  30.                 FormBody$Builder v2_1 = new FormBody$Builder();
  31.                 int v6 = ((FormBody)v0_1).size();
  32.                 int v1_2;
  33.                 for(v1_2 = 0; v1_2 < v6; ++v1_2) {
  34.                     v2_1.addEncoded(((FormBody)v0_1).encodedName(v1_2), ((FormBody)v0_1).encodedValue(v1_2));
  35.                     ((Map)v5).put(((FormBody)v0_1).name(v1_2), ((FormBody)v0_1).value(v1_2));
  36.                 }

  37.                 v0 = System.currentTimeMillis() / v10 + "";
  38.                 v2_1.add("request_ts", v0);
  39.                 ((Map)v5).put("request_ts", v0);
  40.                 v0 = HttpUtil.a().b(v4, ((Map)v5));
  41.                 v3.post(v2_1.build());
  42.             }
  43.             else if((arg13.request().body() instanceof MultipartBody)) {
  44.                 v0_1 = arg13.request().body();
  45.                 MultipartBody$Builder v1_3 = new MultipartBody$Builder(((MultipartBody)v0_1).boundary());
  46.                 v1_3.setType(((MultipartBody)v0_1).type());
  47.                 Iterator v2_2 = ((MultipartBody)v0_1).parts().iterator();
  48.                 while(v2_2.hasNext()) {
  49.                     Object v0_2 = v2_2.next();
  50.                     RequestBody v6_1 = ((MultipartBody$Part)v0_2).body();
  51.                     if(v6_1.contentType().type().equals("text")) {
  52.                         Buffer v7 = new Buffer();
  53.                         v6_1.writeTo(((BufferedSink)v7));
  54.                         String v6_2 = v7.readString(Charset.forName("UTF-8"));
  55.                         String v7_1 = this.a(((MultipartBody$Part)v0_2));
  56.                         if(v7_1 != null) {
  57.                             ((Map)v5).put(v7_1, v6_2);
  58.                         }
  59.                     }

  60.                     v1_3.addPart(((MultipartBody$Part)v0_2));
  61.                 }

  62.                 v0 = System.currentTimeMillis() / v10 + "";
  63.                 v1_3.addFormDataPart("request_ts", v0);
  64.                 ((Map)v5).put("request_ts", v0);
  65.                 v0 = HttpUtil.a().b(v4, ((Map)v5));
  66.                 v3.post(v1_3.build());
  67.             }
  68.             else {
  69.                     v0 = HttpUtil.a().b(v4, ((Map)v0));
  70.             }
  71.         }

  72.         BaseParams.a();
  73.         Request$Builder v1_4 = v3.addHeader("User-Agent", BaseParams.d()).addHeader("Lianjia-Channel", DeviceUtil.e(APPConfigHelper.c())).addHeader("Lianjia-Device-Id", DeviceUtil.k());
  74.         BaseParams.a();
  75.         v1_4.addHeader("Lianjia-Version", BaseParams.e()).addHeader("Authorization", v0).addHeader("Lianjia-Im-Version", APPConfigHelper.g());
  76.         return arg13.proceed(v3.build());
  77. ------------------------------------------------------------------------------------------------------------------
  78.     public String b(String arg8, Map arg9) {
  79.         Map v0 = this.b(arg8);
  80.         HashMap v1 = new HashMap();
  81.         if(v0 != null) {
  82.             v1.putAll(v0);
  83.         }

  84.         if(arg9 != null) {
  85.             v1.putAll(arg9);
  86.         }

  87.         ArrayList v3 = new ArrayList(v1.entrySet());
  88.         Collections.sort(((List)v3), new HttpUtil$1(this));
  89.         String v0_1 = JniClient.GetAppSecret(APPConfigHelper.c());
  90.         String v4 = JniClient.GetAppId(APPConfigHelper.c());
  91.         StringBuilder v5 = new StringBuilder(v0_1);
  92.         int v2;
  93.         for(v2 = 0; v2 < ((List)v3).size(); ++v2) {
  94.             Object v0_2 = ((List)v3).get(v2);
  95.             v5.append(((Map$Entry)v0_2).getKey() + "=" + ((Map$Entry)v0_2).getValue());
  96.         }

  97.         LjLogUtil.a(HttpUtil.a, "sign origin=" + v5);
  98.         Base64.encodeToString(v4 + ":" + DeviceUtil.c(v5.toString()).getBytes(), 2);
  99.         LjLogUtil.a(HttpUtil.a, "sign result=" + v0_1);
  100.         return v0_1;
  101.     }
  102. ------------------------------------------------------------------------------------------------------------------
  103.     public static String c(String arg6) {
  104.         String v0_2;
  105.         int v0 = 0;
  106.         try {
  107. MessageDigest v1 = MessageDigest.getInstance("SHA-1");
  108.             v1.update(arg6.getBytes());
  109.             byte[] v1_1 = v1.digest();
  110.             StringBuffer v2 = new StringBuffer();
  111.             while(v0 < v1_1.length) {
  112.                 String v3 = Integer.toHexString(v1_1[v0] & 255);
  113.                 if(v3.length() < 2) {
  114.                     v2.append(0);
  115.                 }

  116.                 v2.append(v3);
  117.                 ++v0;
  118.             }

  119.             v0_2 = v2.toString();
  120.         }
  121.         catch(NoSuchAlgorithmException v0_1) {
  122.             v0_1.printStackTrace();
  123.             v0_2 = "";
  124.         }

  125.         return v0_2;
  126.     }

复制代码

第四步 算法总结

Authorization = BASE64("20180111_android:" + sha1("d5e343d453aecca8b14b2dc687c381ca" + "mobile_phone_no=13812345678&password=123456&request_ts=1534851761"));

附录上移植后的JS算法

  1. var Base64={base64:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(t){if(!t)return!1;var a="";var o,e,r;var f,u,s,i;var n=0;do{o=t.charCodeAt(n++);e=t.charCodeAt(n++);r=t.charCodeAt(n++);f=o>>2;u=(3&o)<<4|e>>4;s=(15&e)<<2|r>>6;i=63&r;if(isNaN(e))s=i=64;else if(isNaN(r))i=64;a+=this.base64.charAt(f)+this.base64.charAt(u)+this.base64.charAt(s)+this.base64.charAt(i);}while(n<t.length);return a;},decode:function(t){if(!t)return!1;t=t.replace(/[^A-Za-z0-9\+\/\=]/g,"");var r="";var s,n,i,o;var e=0;do{s=this.base64.indexOf(t.charAt(e++));n=this.base64.indexOf(t.charAt(e++));i=this.base64.indexOf(t.charAt(e++));o=this.base64.indexOf(t.charAt(e++));r+=String.fromCharCode(s<<2|n>>4);if(64!=i)r+=String.fromCharCode((15&n)<<4|i>>2);if(64!=o)r+=String.fromCharCode((3&i)<<6|o);}while(e<t.length);return r;}};var CryptoJS=CryptoJS||(function(Math,undefined){var C={};var C_lib=C.lib={};var Base=C_lib.Base=(function(){function F(){};return{extend:function(overrides){F.prototype=this;var subtype=new F();if(overrides){subtype.mixIn(overrides);}if(!subtype.hasOwnProperty('init')||this.init===subtype.init){subtype.init=function(){subtype.$super.init.apply(this,arguments);};}subtype.init.prototype=subtype;subtype.$super=this;return subtype;},create:function(){var instance=this.extend();instance.init.apply(instance,arguments);return instance;},init:function(){},mixIn:function(properties){for(var propertyName in properties){if(properties.hasOwnProperty(propertyName)){this[propertyName]=properties[propertyName];}}if(properties.hasOwnProperty('toString')){this.toString=properties.toString;}},clone:function(){return this.init.prototype.extend(this);}};}());var WordArray=C_lib.WordArray=Base.extend({init:function(words,sigBytes){words=this.words=words||[];if(sigBytes!=undefined){this.sigBytes=sigBytes;}else{this.sigBytes=words.length*4;}},toString:function(encoder){return(encoder||Hex).stringify(this);},concat:function(wordArray){var thisWords=this.words;var thatWords=wordArray.words;var thisSigBytes=this.sigBytes;var thatSigBytes=wordArray.sigBytes;this.clamp();if(thisSigBytes%4){for(var i=0;i<thatSigBytes;i++){var thatByte=(thatWords[i>>>2]>>>(24-(i%4)*8))&0xff;thisWords[(thisSigBytes+i)>>>2]|=thatByte<<(24-((thisSigBytes+i)%4)*8);}}else if(thatWords.length>0xffff){for(var i=0;i<thatSigBytes;i+=4){thisWords[(thisSigBytes+i)>>>2]=thatWords[i>>>2];}}else{thisWords.push.apply(thisWords,thatWords);}this.sigBytes+=thatSigBytes;return this;},clamp:function(){var words=this.words;var sigBytes=this.sigBytes;words[sigBytes>>>2]&=0xffffffff<<(32-(sigBytes%4)*8);words.length=Math.ceil(sigBytes/4);},clone:function(){var clone=Base.clone.call(this);clone.words=this.words.slice(0);return clone;},random:function(nBytes){var words=[];var r=(function(m_w){var m_w=m_w;var m_z=0x3ade68b1;var mask=0xffffffff;return function(){m_z=(0x9069*(m_z&0xFFFF)+(m_z>>0x10))&mask;m_w=(0x4650*(m_w&0xFFFF)+(m_w>>0x10))&mask;var result=((m_z<<0x10)+m_w)&mask;result/=0x100000000;result+=0.5;return result*(Math.random()>.5?1:-1);}});for(var i=0,rcache;i<nBytes;i+=4){var _r=r((rcache||Math.random())*0x100000000);rcache=_r()*0x3ade67b7;words.push((_r()*0x100000000)|0);}return new WordArray.init(words,nBytes);}});var C_enc=C.enc={};var Hex=C_enc.Hex={stringify:function(wordArray){var words=wordArray.words;var sigBytes=wordArray.sigBytes;var hexChars=[];for(var i=0;i<sigBytes;i++){var bite=(words[i>>>2]>>>(24-(i%4)*8))&0xff;hexChars.push((bite>>>4).toString(16));hexChars.push((bite&0x0f).toString(16));}return hexChars.join('');},parse:function(hexStr){var hexStrLength=hexStr.length;var words=[];for(var i=0;i<hexStrLength;i+=2){words[i>>>3]|=parseInt(hexStr.substr(i,2),16)<<(24-(i%8)*4);}return new WordArray.init(words,hexStrLength/2);}};var Latin1=C_enc.Latin1={stringify:function(wordArray){var words=wordArray.words;var sigBytes=wordArray.sigBytes;var latin1Chars=[];for(var i=0;i<sigBytes;i++){var bite=(words[i>>>2]>>>(24-(i%4)*8))&0xff;latin1Chars.push(String.fromCharCode(bite));}return latin1Chars.join('');},parse:function(latin1Str){var latin1StrLength=latin1Str.length;var words=[];for(var i=0;i<latin1StrLength;i++){words[i>>>2]|=(latin1Str.charCodeAt(i)&0xff)<<(24-(i%4)*8);}return new WordArray.init(words,latin1StrLength);}};var Utf8=C_enc.Utf8={stringify:function(wordArray){try{return decodeURIComponent(escape(Latin1.stringify(wordArray)));}catch(e){throw new Error('Malformed UTF-8 data');}},parse:function(utf8Str){return Latin1.parse(unescape(encodeURIComponent(utf8Str)));}};var BufferedBlockAlgorithm=C_lib.BufferedBlockAlgorithm=Base.extend({reset:function(){this._data=new WordArray.init();this._nDataBytes=0;},_append:function(data){if(typeof data=='string'){data=Utf8.parse(data);}this._data.concat(data);this._nDataBytes+=data.sigBytes;},_process:function(doFlush){var data=this._data;var dataWords=data.words;var dataSigBytes=data.sigBytes;var blockSize=this.blockSize;var blockSizeBytes=blockSize*4;var nBlocksReady=dataSigBytes/blockSizeBytes;if(doFlush){nBlocksReady=Math.ceil(nBlocksReady);}else{nBlocksReady=Math.max((nBlocksReady|0)-this._minBufferSize,0);}var nWordsReady=nBlocksReady*blockSize;var nBytesReady=Math.min(nWordsReady*4,dataSigBytes);if(nWordsReady){for(var offset=0;offset<nWordsReady;offset+=blockSize){this._doProcessBlock(dataWords,offset);}var processedWords=dataWords.splice(0,nWordsReady);data.sigBytes-=nBytesReady;}return new WordArray.init(processedWords,nBytesReady);},clone:function(){var clone=Base.clone.call(this);clone._data=this._data.clone();return clone;},_minBufferSize:0});var Hasher=C_lib.Hasher=BufferedBlockAlgorithm.extend({cfg:Base.extend(),init:function(cfg){this.cfg=this.cfg.extend(cfg);this.reset();},reset:function(){BufferedBlockAlgorithm.reset.call(this);this._doReset();},update:function(messageUpdate){this._append(messageUpdate);this._process();return this;},finalize:function(messageUpdate){if(messageUpdate){this._append(messageUpdate);}var hash=this._doFinalize();return hash;},blockSize:512/32,_createHelper:function(hasher){return function(message,cfg){return new hasher.init(cfg).finalize(message);};},_createHmacHelper:function(hasher){return function(message,key){return new C_algo.HMAC.init(hasher,key).finalize(message);};}});var C_algo=C.algo={};return C;}(Math));(function(){var C=CryptoJS;var C_lib=C.lib;var WordArray=C_lib.WordArray;var Hasher=C_lib.Hasher;var C_algo=C.algo;var W=[];var SHA1=C_algo.SHA1=Hasher.extend({_doReset:function(){this._hash=new WordArray.init([0x67452301,0xefcdab89,0x98badcfe,0x10325476,0xc3d2e1f0]);},_doProcessBlock:function(M,offset){var H=this._hash.words;var a=H[0];var b=H[1];var c=H[2];var d=H[3];var e=H[4];for(var i=0;i<80;i++){if(i<16){W[i]=M[offset+i]|0;}else{var n=W[i-3]^W[i-8]^W[i-14]^W[i-16];W[i]=(n<<1)|(n>>>31);}var t=((a<<5)|(a>>>27))+e+W[i];if(i<20){t+=((b&c)|(~b&d))+0x5a827999;}else if(i<40){t+=(b^c^d)+0x6ed9eba1;}else if(i<60){t+=((b&c)|(b&d)|(c&d))-0x70e44324;}else{t+=(b^c^d)-0x359d3e2a;}e=d;d=c;c=(b<<30)|(b>>>2);b=a;a=t;}H[0]=(H[0]+a)|0;H[1]=(H[1]+b)|0;H[2]=(H[2]+c)|0;H[3]=(H[3]+d)|0;H[4]=(H[4]+e)|0;},_doFinalize:function(){var data=this._data;var dataWords=data.words;var nBitsTotal=this._nDataBytes*8;var nBitsLeft=data.sigBytes*8;dataWords[nBitsLeft>>>5]|=0x80<<(24-nBitsLeft%32);dataWords[(((nBitsLeft+64)>>>9)<<4)+14]=Math.floor(nBitsTotal/0x100000000);dataWords[(((nBitsLeft+64)>>>9)<<4)+15]=nBitsTotal;data.sigBytes=dataWords.length*4;this._process();return this._hash;},clone:function(){var clone=Hasher.clone.call(this);clone._hash=this._hash.clone();return clone;}});C.SHA1=Hasher._createHelper(SHA1);C.HmacSHA1=Hasher._createHmacHelper(SHA1);}());function AuthorizationStr(str){var str0="20180111_android:";var str1="d5e343d453aecca8b14b2dc687c381ca"+str;return Base64.encode(str0+CryptoJS.SHA1(str1.replace(/&/g,"")).toString());}function tests(){var str="mobile_phone_no=13812345678&password=123456&request_ts=1532706218";return AuthorizationStr(str);}
复制代码


评分

参与人数 1精币 +1 收起 理由
zy723 + 1 感谢发布原创作品,精易因你更精彩!

查看全部评分


结帖率:89% (8/9)
发表于 2021-3-17 21:01:39 | 显示全部楼层   四川省成都市
问一下第四步  d5e343d453aecca8b14b2dc687c381ca怎么来的
第四步 算法总结

Authorization = BASE64("20180111_android:" + sha1("d5e343d453aecca8b14b2dc687c381ca" + "mobile_phone_no=13812345678&password=123456&request_ts=1534851761"));
回复 支持 反对

使用道具 举报

发表于 2021-1-6 19:59:50 | 显示全部楼层   江苏省南京市
写一个贝壳找房的zc机多少钱?Q2065620017
回复 支持 反对

使用道具 举报

结帖率:0% (0/1)
发表于 2020-1-1 17:34:21 | 显示全部楼层   江西省南昌市
66666666666666
回复 支持 反对

使用道具 举报

发表于 2019-11-19 05:57:45 高大上手机用户 | 显示全部楼层   陕西省西安市
厉害了谢谢分享
回复 支持 反对

使用道具 举报

发表于 2019-8-19 17:40:44 | 显示全部楼层   广东省深圳市
没有用户状态的情况下呢?现在app都是用动态短xin验证码登录,这时候密码又是什么呢,大佬
回复 支持 反对

使用道具 举报

结帖率:100% (8/8)
发表于 2019-6-24 23:16:07 | 显示全部楼层   香港特别行政区*
lfly453 发表于 2018-8-24 11:54
网页直接免码登录。如果要刷邀请,数盟你是的难题。

什么是数盟 表示在做拉新
回复 支持 反对

使用道具 举报

发表于 2019-5-27 06:48:25 | 显示全部楼层   湖北省武汉市
感谢分享,很给力
回复 支持 反对

使用道具 举报

发表于 2018-12-21 20:05:10 | 显示全部楼层   河南省南阳市
lfly453 发表于 2018-8-24 11:54
网页直接免码登录。如果要刷邀请,数盟你是的难题。

能过数盟吗  企鹅1406298648
回复 支持 反对

使用道具 举报

结帖率:80% (4/5)
发表于 2018-8-24 11:54:41 | 显示全部楼层   江苏省常州市
网页直接免码登录。如果要刷邀请,数盟你是的难题。
回复 支持 反对

使用道具 举报

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

本版积分规则 致发广告者

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

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

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