分析工具:IE10、HttpWatch
密码算法:RSA
难 度:★★☆☆☆
分析步骤:
①、打开IE,打开httpwatch,老规矩 Clean cache and all cookies,开启抓包,然后打开百度首页:http://www.baidu.com/,什么都不用管,直接登录,登录完成后所有的包都有了。
②、包有了,开始搞吧,我们先看看最后的登录包:
看看里面有几个像是动态参数:gid、password、rsakey、token、tt,字面意思和值告诉我们,gid - 未知, password - 加密后的密码, rsakey - rsa key,token - 登录令牌,tt - 时间戳,分析大致的意思让分析思路更加明确,像这个tt我们基本不用管了。
③、我们先来找gid的值,复制gid的值在httpWatch里面搜索,看看在服务器返回Cookies里面有没有,结果……并没有,所以这个值可能就是在客户端生成的了,那就直接搜索gid=,来到一处:https://ss0.bdstatic.com/5LMZfyabBhJ3otebn9fN2DJv/passApi/js/uni_login_tangram_6601c89c.js ,看看里面的代码:
function() {
var z = document.location.protocol.toLowerCase();
var x = u.guideRandom ? u.guideRandom: "";
if (z == "http:") {
var y = "http://nsclick.baidu.com/v.gif?pid=111&url=&logintype=hide&merge=1&gid=" + x + "&tpl=" + l.apiOpt.tpl + "&tt=" + new Date().getTime()
} else {
if (z == "https:") {
var y = "https://passport.baidu.com/img/v.gif?cdnversion=60706311.gif?pid=111&url=&logintype=hide&merge=1&gid=" + x + "&tpl=" + l.apiOpt.tpl + "&tt=" + new Date().getTime()
}
}
通过这个JS我们不难看出这个值来自:u.guideRandom,不管他,直接搜 guideRandom,找到了好几处,我们的目的很明确,找到他实现的地方,直到看到一个 this.guideRandom=(function() 就说明就是这个了,在这个JS里面:https://ss0.bdstatic.com/5LMZfyabBhJ3otebn9fN2DJv/passApi/js/login_0a0d41f2.js ,这个JS 是utf8的,我们先选一下格式utf-8,然后复制整个js出来,找个JS在线格式化工具格式化一下,粘贴到notepad++里面,这样就比较好看了,找到实现:
this.guideRandom = (function() {
return "xxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,
function(c) {
var r = Math.random() * 16 | 0,
v = c == "x" ? r: (r & 3 | 8);
return v.toString(16)
}).toUpperCase()
})();
原来是个大忽悠,,这个值是随机的,并且没有任何动态参数参与运算,我们整理一下,不管他虽不随机,我们保留吧:
function guid_random()
{
return "xxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,
function(c) {
var r = Math.random() * 16 | 0,
v = c == "x" ? r: (r & 3 | 8);
return v.toString(16)
}).toUpperCase();
}
好了,继续下一个参数,password,直接搜索&password发现找不到,那就找找 password= 吧,还是定位 login_0a0d41f2.js ,我们看下关键代码:
submit: function() {
var me = this;
if (me.internation && !me._validatorforeignmobileFn(me.getElement("foreignMobile"))) {
return
}
me.validateAll({
success: function() {
me._doFocus("submit");
me.submitStatus = 1;
var returnValue = me.fireEvent("beforeSubmit");
me.getElement("submit").style.color = "#9ebef4";
if (!returnValue) {
return
}
if (me.spLogin) {
var usernameTemp = baidu('');
me.getElement("hiddenFields").appendChild(usernameTemp.get(0));
me.spLogin = null
}
var data = baidu.form.json(me.getElement("form"));
data.token = me.bdPsWtoken;
passport.data.setContext(baidu.extend({},
me.config));
if (me.RSA && me.rsakey) {
var passwordVal = me.getElement("password").value;
if (passwordVal.length < 128 && !me.config.safeFlag) {
data.password = baidu.url.escapeSymbol(me.RSA.encrypt(passwordVal));
data.rsakey = me.rsakey;
data.crypttype = 12
}
}
var submitEle = me.getElement("submit"),
time = 15000,
submitInterval;
me.getElement("submit").style.color = "#9ebef4";
submitEle.value = me.lang.logining;
submitInterval = setTimeout(function() {
if (me.submitStatus === 1 && !me.config.connect) {
me.setGeneralError(me.lang.submitTimeup)
}
submitEle.value = me.lang.login
},
time);
function loginFn() {
data.timeSpan = new Date().getTime() - me.initTime;
if (me.internation) {
data.username = me.getElement("foreignMobile").value;
data.isPhone = true;
data.countrycode = baidu(me.getElement("foreignMobileLabel")).attr("data-countrycode") || ""
} else {
data.countrycode = ""
}
passport.data.login(data).success(function(rsp) {
me.submitStatus = 2;
if (rsp.errInfo.no == 0) {
var returnValue = me.fireEvent("loginSuccess", {
rsp: rsp
});
if (!returnValue) {
return
}
if (window.location) {
window.location.href = rsp.data.u
} else {
document.location.href = rsp.data.u
}
} else {
submitEle.value = me.lang.login;
me.getElement("submit").style.color = "#fff";
var returnValue = me.fireEvent("loginError", {
rsp: rsp
});
if (!returnValue) {
return
}
me._defaultLoginErr(rsp)
}
})
}
me.loginConnect({
username: data.userName,
password: data.password
},
{
success: function() {
clearTimeout(submitInterval);
submitEle.value = me.lang.login
},
fail: function(msg) {
clearTimeout(submitInterval);
submitEle.value = me.lang.login;
me.setGeneralError(msg)
}
},
loginFn)
}
},
true)
}
看到这个基本就是一目了然了吧:
data.password = baidu.url.escapeSymbol(me.RSA.encrypt(passwordVal));
data.rsakey = me.rsakey;
data.crypttype = 12
我们要提交的数据都在这个data里,我们的密码就是通过RSA一层之后escapeSymbol ,找RSA简单了,我们主要是找到RSA起始和结束点,提取出来,整理成一个函数。
rsakey我们搜索一下就能找到:https://passport.baidu.com/v2/getpublickey?token=fcd1f6684072372c6812a44c1d94bf51&tpl=mn&apiver=v3&tt=1461222170065&gid=C539A37-9B0C-4538-9920-E150AC6AE0D5&callback=bd__cbs__tpdrlq 返回的,而这个URL中也有个token,所以现在只要找到 token ,所有的问题就迎刃而解了,我们搜一下token的值,在https://passport.baidu.com/v2/api/?getapi&tpl=mn&apiver=v3&tt=1461222159011&class=login&gid=C539A37-9B0C-4538-9920-E150AC6AE0D5&logintype=dialogLogin&callback=bd__cbs__jcbr21 里面找到了,是服务器返回的。
这样一来所有的参数都已经找到了,下篇文章我们来模拟整个登录过程。