爬虫逆向-空中网登路密码逆向

背景:

本文只是为了学习逆向技术,与爬取数据无关, 所以文中没有数据爬取,只是叙述了JS逆向思路及步骤

 请勿对目标网站进行大规模爬取

网址: https://passport.kongzhong.com

 

开始 - 步骤

1、 抓包得到登录操作为ajax请求,
    1.1、密码是密文
2、获取密码加密js代码得知加密需要:dc['dc']
3、根据js代码得知dc['dc']为ajax请求返回,
4、发送ajax请求得dc, 注意 _ 为时间戳
5、根据密码和dc,js逆向加密,得密码加密后得字符串
6、发送登录请求,成功
PS: vcode 为验证码, 需要接入验证码识别
 
 
import requests
import time
import json
import re
import execjs

headers
= { 'Accept': '*/*', 'Accept-Language': 'zh-CN,zh;q=0.9,en-GB;q=0.8,en-US;q=0.7,en;q=0.6', 'Connection': 'keep-alive', # 'Cookie': 'KZLBS=d08e6bcdc9f0cbe5; Hm_lvt_1287c2225a527abe3386233dd9316f99=1671177724; SSO-KGZLT=f272a541-e40e-44ce-ad05-2645a0b2101a; SSO-KGZIT=c42c3494-2394-40ca-9583-a8c1058f67e7; Hm_lpvt_1287c2225a527abe3386233dd9316f99=1671418222; SSO-KGZQRT=D71FF8C57C8312613E6100C22D769B69', 'Referer': 'https://passport.kongzhong.com/', 'Sec-Fetch-Dest': 'script', 'Sec-Fetch-Mode': 'no-cors', 'Sec-Fetch-Site': 'same-site', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36', 'sec-ch-ua': '"Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', } params = { 'j': 'j', 'jsonp': 'j', 'service': 'https://passport.kongzhong.com/', '_': round(time.time() * 1000) } response = requests.get( url='https://sso.kongzhong.com/ajaxLogin', headers=headers, params=params ) # 获取dc dc_list = re.findall('\((.*)\)', response.text) dc = json.loads(dc_list[0]) print(dc['dc']) # 获取password 加密串 node = execjs.get() ctx = node.compile(open("./1-空中网逆向.js", "r", encoding="utf-8").read()) # 执行js函数 resp = ctx.eval( 'KZLoginHandler.encrypt("{}", "{}")'.format('123456', dc['dc'])) print(resp) url = 'https://sso.kongzhong.com/ajaxLogin' params2 = { 'j': 'j', 'type': '1', 'service': 'https://passport.kongzhong.com/', '_': round(time.time() * 1000), 'vcode': '', 'toSave': '0', 'username': '13102520219', 'password': resp } response2 = requests.get( url='https://sso.kongzhong.com/ajaxLogin', headers=headers, params=params2 ) print(response2.text)

 

JS代码

  1 /**
  2 * SSO 登录控制器
  3 * @author: qiaozheng@kongzhong.com
  4 * @version: 3.0
  5 */
  6 var KZLoginHandler =
  7 {
  8     'id': 'kongzhong-login-agent',
  9     'loginServer': 'http://sso.kongzhong.com',
 10     //'loginURL': 'sso/userLogin',
 11     'service': '',
 12     'targetService': '',
 13     //'dc': '',
 14     'j_data': null,
 15     'f_call_back': null,
 16     'timestamp': 0,
 17     'completed': false,
 18     'renew': false,
 19     'init': function () {
 20         this.j_data = null;
 21         this.f_call_back = null;
 22         this.timestamp = 0;
 23         this.completed = true;
 24         //this.dc = '';
 25     },
 26     'check': function (call_back) {
 27         this.init();
 28         this.f_call_back = call_back;
 29         var param = "jsonp=j";
 30         if (this.service != null && jQuery.trim(this.service) != "") {
 31             param += "&service=" + decodeURIComponent(this.service);
 32         }
 33         if (this.targetService != null && jQuery.trim(this.targetService) != "") {
 34             param += "&targetService=" + decodeURIComponent(this.targetService);
 35         }
 36         if (this.renew) {
 37             param += "&renew=1";
 38         }
 39 
 40         this.exec_login(param);
 41     },
 42     'exec_login': function (param) {
 43         if (this.completed == false) {
 44             return false;
 45         }
 46         if (this.j_data != null && this.j_data["state"] == "1") {
 47             var data = {};
 48             data["user"] = this.j_data["user"];
 49             data["service"] = this.j_data["service"];
 50             data["logged"] = true;
 51             data["dc"] = this.j_data["dc"];
 52             this.f_call_back(data);
 53             return false;
 54         }
 55         var url = this.loginServer + "/ajaxLogin";
 56 
 57         jQuery.ajax({
 58             async: false,
 59             url: url,
 60             type: 'post',
 61             dataType: 'jsonp',
 62             jsonp: 'j', //jsoncallback
 63             data: param,
 64             jsonpCallback: "j",
 65             timeout: 5000,
 66             cache: false,
 67             success: function (json) {
 68             },
 69             error: function (xhr) {
 70                 console.log("error:", xhr.status);
 71                 if (xhr.status === 403 || xhr.status === 445) {
 72                     window.location.href = "https://www.zhanhuo.com/waf/index.html?src=passport";
 73                 }
 74             }
 75         });
 76 
 77         //当WAF拦截出现445错误时,ajax的error方法不能捕获jsonp的异常,必须通过ajax创建的第一个script的onerror来捕获异常
 78         var head = document.head || $('head')[0] || document.documentElement;
 79         var script = $(head).find('script')[0];
 80         script.onerror = function (evt) {
 81             window.location.href = "https://www.zhanhuo.com/waf/index.html?src=passport";
 82         }
 83     },
 84     'jsonpCallbackKongZ': function (vData) {
 85         this.j_data = vData;
 86         //this.dc = vData["dc"];
 87         this.timestamp = Date.parse(new Date());
 88         if (this.f_call_back != null) {
 89             var data = {};
 90             if (vData["state"] == "0") {
 91                 data["service"] = vData["service"];
 92                 data["logged"] = false;
 93                 data["errors"] = vData["kzmsg"];
 94                 if (vData["requirevcode"] != null
 95                     && vData["requirevcode"] == "1") {
 96                     data["requirevcode"] = true;
 97                 } else {
 98                     data["requirevcode"] = false;
 99                 }
100                 //data["message"] = vData["kzmsg"];
101             } else if (vData["state"] == "1") {
102                 data["user"] = vData["user"];
103                 data["service"] = vData["service"];
104                 data["logged"] = true;
105             }
106             data["dc"] = this.j_data["dc"];
107             this.f_call_back(data);
108         }
109         this.completed = true;
110     },
111     'login': function (user, pwd, to_save, vcode, call_back) {
112         var tempTime = Date.parse(new Date()) - this.timestamp;
113         if ((tempTime / 1000) >= 180) {
114             this.j_data = null;
115         }
116         if (this.j_data == null
117             || this.j_data == "") {
118             this.check(function (data) {
119                 this.f_call_back = call_back;
120                 var param = "";
121                 param += "&type=1";
122                 //param += "&lt="+this.j_data["lt"];
123                 if (this.service != null && jQuery.trim(this.service) != "") {
124                     //param += "&service="+this.service;
125                     param += "&service=" + decodeURIComponent(this.service);
126                 }
127                 param += "&username=" + user;
128                 param += "&password=" + this.encrypt(pwd, data["dc"]);
129                 //param += "&password="+pwd;
130                 param += "&vcode=" + vcode;
131                 if (to_save) {
132                     param += "&toSave=1";
133                 } else {
134                     param += "&toSave=0";
135                 }
136                 if (this.targetService != null && jQuery.trim(this.targetService) != "") {
137                     param += "&targetService=" + decodeURIComponent(this.targetService);
138                 }
139                 if (this.renew) {
140                     param += "&renew=1";
141                 }
142 
143                 this.exec_login(param);
144             });
145         } else {
146             this.f_call_back = call_back;
147             var param = "";
148             param += "&type=1";
149             //param += "&lt="+this.j_data["lt"];
150             if (this.service != null && jQuery.trim(this.service) != "") {
151                 //param += "&service="+this.service;
152                 param += "&service=" + decodeURIComponent(this.service);
153             }
154             param += "&username=" + user;
155             param += "&password=" + this.encrypt(pwd, this.j_data["dc"]);
156             //param += "&password="+pwd;
157             param += "&vcode=" + vcode;
158             if (to_save) {
159                 param += "&toSave=1";
160             } else {
161                 param += "&toSave=0";
162             }
163             if (this.targetService != null && jQuery.trim(this.targetService) != "") {
164                 param += "&targetService=" + decodeURIComponent(this.targetService);
165             }
166             if (this.renew) {
167                 param += "&renew=1";
168             }
169 
170             this.exec_login(param);
171         }
172 
173     },
174     'login_sms': function (user, smscode, to_save, vcode, call_back) {
175         var tempTime = Date.parse(new Date()) - this.timestamp;
176         if ((tempTime / 1000) >= 180) {
177             this.j_data = null;
178         }
179         if (this.j_data == null
180             || this.j_data == "") {
181             this.check(function () {
182                 this.f_call_back = call_back;
183                 var param = "";
184                 param += "&type=2";
185                 //param += "&lt="+this.j_data["lt"];
186                 param += "&service=" + this.service;
187                 param += "&username=" + user;
188                 param += "&vcode=" + vcode;
189                 param += "&smscode=" + smscode;
190                 //param += "&tcode="+tm;
191                 if (to_save) {
192                     param += "&toSave=1";
193                 } else {
194                     param += "&toSave=0";
195                 }
196                 if (this.targetService != null) {
197                     param += "&targetService=" + decodeURIComponent(this.targetService);
198                 }
199                 if (this.renew) {
200                     param += "&renew=1";
201                 }
202 
203                 this.exec_login(param);
204             });
205         } else {
206             this.f_call_back = call_back;
207             var param = "";
208             param += "&type=2";
209             //param += "&lt="+this.j_data["lt"];
210             param += "&service=" + this.service;
211             param += "&username=" + user;
212             param += "&vcode=" + vcode;
213             param += "&smscode=" + smscode;
214             //param += "&tcode="+tm;
215             if (to_save) {
216                 param += "&toSave=1";
217             } else {
218                 param += "&toSave=0";
219             }
220             if (this.targetService != null) {
221                 param += "&targetService=" + decodeURIComponent(this.targetService);
222             }
223             if (this.renew) {
224                 param += "&renew=1";
225             }
226 
227             this.exec_login(param);
228         }
229 
230     },
231     'login_reg': function (user, pwd, to_save, call_back) {
232         var tempTime = Date.parse(new Date()) - this.timestamp;
233         if ((tempTime / 1000) >= 180) {
234             this.j_data = null;
235         }
236         if (this.j_data == null
237             || this.j_data == "") {
238             this.check(function () {
239                 this.f_call_back = call_back;
240                 var param = "";
241                 param += "&type=101";
242                 //param += "&lt="+this.j_data["lt"];
243                 param += "&service=" + this.service;
244                 param += "&username=" + user;
245                 param += "&password=" + pwd;
246                 if (to_save) {
247                     param += "&toSave=1";
248                 } else {
249                     param += "&toSave=0";
250                 }
251                 if (this.renew) {
252                     param += "&renew=1";
253                 }
254 
255                 this.exec_login(param);
256             });
257         } else {
258             this.f_call_back = call_back;
259             var param = "";
260             param += "&type=101";
261             //param += "&lt="+this.j_data["lt"];
262             param += "&service=" + this.service;
263             param += "&username=" + user;
264             param += "&password=" + pwd;
265             if (to_save) {
266                 param += "&toSave=1";
267             } else {
268                 param += "&toSave=0";
269             }
270             if (this.renew) {
271                 param += "&renew=1";
272             }
273 
274             this.exec_login(param);
275         }
276 
277     },
278     'encrypt': function (str, pwd) {
279         if (pwd == null || pwd.length <= 0) {
280             return null;
281         }
282         var prand = "";
283         for (var i = 0; i < pwd.length; i++) {
284             prand += pwd.charCodeAt(i).toString();
285         }
286         var sPos = Math.floor(prand.length / 5);
287         var mult = parseInt(prand.charAt(sPos) + prand.charAt(sPos * 2) + prand.charAt(sPos * 3) + prand.charAt(sPos * 4) + prand.charAt(sPos * 5));
288         var incr = Math.ceil(pwd.length / 2);
289         var modu = Math.pow(2, 31) - 1;
290         if (mult < 2) {
291             return null;
292         }
293         var salt = Math.round(Math.random() * 1000000000) % 100000000;
294         prand += salt;
295         while (prand.length > 10) {
296             var a = prand.substring(0, 1);
297             var b = prand.substring(10, prand.length);
298             if (b.length > 10) {
299                 prand = b;
300             } else {
301                 prand = (parseInt(a) + parseInt(b)).toString();
302             }
303         }
304         prand = (mult * prand + incr) % modu;
305         var enc_chr = "";
306         var enc_str = "";
307         for (var i = 0; i < str.length; i++) {
308             enc_chr = parseInt(str.charCodeAt(i) ^ Math.floor((prand / modu) * 255));
309             if (enc_chr < 16) {
310                 enc_str += "0" + enc_chr.toString(16);
311             } else enc_str += enc_chr.toString(16);
312             prand = (mult * prand + incr) % modu;
313         }
314         salt = salt.toString(16);
315         while (salt.length < 8) salt = "0" + salt;
316         enc_str += salt;
317         return enc_str;
318     }
319 
320 };
321 
322 dc = "85B887AF9E8325D4243383AFC66997C9"
323 console.log(KZLoginHandler.encrypt('123456', dc))
View Code

 

PS:  文中只是分析了密码逆向部分, 关于验证码识别API接入 未处理
 
 
 
 
posted @ 2022-12-28 10:58  萤huo虫  阅读(83)  评论(0编辑  收藏  举报