`
snake_hand
  • 浏览: 616843 次
社区版块
存档分类
最新评论

玩转12306之系统登录

 
阅读更多

欢迎大家访问我的个人网站 萌萌的IT人

【申明:本文所涉及的技术和分析的目的都是为了学习和交流,任何人使用文中所提的技术或成果做出的违法事情与我无关,大家购买火车票还是去12306官网上去购买。】

从今天起,我开始分析12306网站的Http请求,以及编写一个客户端工具,废话不多说,这篇文章的重点是分析登录。

常规的登录思路:账号+密码,稍微有点防范意识的:账号+密码+验证码,高级点的:账号+密码+验证码,其中密码加密。我们看看12306他是采用了哪些策略。

首先进入12306的官网,尝试下登录,然后抓包,这里有个技巧,最好登录的时候用错误的密码或者验证码进行登录。

如上图,发起了两个Post请求(一般提交的动作,跟踪post类的请求)

我们先不管第一个请求是干嘛的(肯定是用的~),看看第二个请求,第二个请求显然提交登录的动作,继续抓包看看它到底提交了哪些参数。

 我们分析下参数的意义和来源:

longinRand:969这个目前不得而知,refundLogin:N  这个写死就行了,refundFlag:Y 这个不得而知,loginUser.user_name:用户名,user.password:密码,randCode:验证码,

NzYxNDgz:N2RlNzU1YWQ0ZTE5M2NiYg== 这个不得而知,动态参数。

这个时候我们回头看看第一个请求,看他返回的是什么:

{"loginRand":"969","randError":"Y"}

至此,我们知道了longinRand,refundFlag是通过第一个请求得到的,soga...

那么动态参数我们怎么取得呢?

继续观察,https://dynamic.12306.cn/otsweb/loginAction.do?method=init 的源码(这个是初始化登陆页面,不要问我怎么知道的,观察,你懂的)

发现里面有这么一段:

<script src="/otsweb/dynamicJsAction.do?jsversion=5022&method=loginJstype="text/javascript"></script>

这段脚本是干嘛的呢。。。果断下载下来,研究下,发现了奥妙:

var inputObj=$('<input type="hidden" name="'+keyVlues[0]+'" value="'+encode32(bin216(Base32.encrypt(keyVlues[1],keyVlues[0])))+'" />');

这个type为hidden的文本框,它的name为value度是动态取值的,注意到这句脚本里面gc()的方法 里面有一句var key='MzUyNzc0NQ==';

这个显然就是我们的key了,那么value值了,通过阅读源码知道 ,原来这个方法是检测是否存在刷票插件,如果存在value=value+'0',否则value=value+'1';

那么它是如何检测存在刷票插件的呢,接着看脚本

var cssArr=['selectSeatType',' ev_light',' ev_light  ','fishTimeRangePicker','updatesFound','tipScript','refreshButton','fish_clock','refreshStudentButton'

,'btnMoreOptions','btnAutoLogin','fish_button','defaultSafeModeTime','ticket-navigation-item'];

var idArr=['btnMoreOptions','refreshStudentButton','fishTimeRangePicker','helpertooltable','outerbox','updateInfo'

,'fish_clock','refreshStudentButton','btnAutoRefresh','btnAutoSubmit','btnRefreshPassenger'

,'autoLogin','bnAutoRefreshStu','orderCountCell','refreshStudentButton','enableAdvPanel','autoDelayInvoke','refreshButton','refreshTimesBar','chkAllSeat'];

var keywordArr=[{
   key:".enter_right",values:["亲","抢票","助手"]
  }
  ,{
   key:".cx_form",values:["点发车","刷票"]
  }
  ,{
   key:"#gridbox",values:["只选","仅选","checkBox","checkbox"]
  }
  ,{
   key:".enter_w",values:["助手"]
  }
  ] ;

原来,这个脚本作用有2个,一个是检测页面是否挂载了刷票的脚本工具,一个是动态生成一个密钥。看来12306的确被刷票工具搞得够惨,不得不应对了,因为这个脚本是动态生成的,所以12306可以定期生成这些关键词库,来防止,这个对于一般的刷票工具可以起到一定得作用,但是昨天我看了下猎豹的刷票的源码(仅举一例):

<button class="normalButton" id="FriSep272013100801GMT08001" type="button" style="margin:0;width:97px;font-size:14px;vertical-align:middle;">♣ 刷  票</button>

猎豹也够牛的,估计是上次12306更新了防刷脚本后,猎豹直接把自己的脚本上的控件ID都动态化了。。。。

言归正传,刚才我们看到了动态key的产生,实际就是去请求https://dynamic.12306.cn/otsweb/loginAction.do?method=init,然后得到<script src="/otsweb/dynamicJsAction.do?jsversion=5022&method=loginJstype="text/javascript"></script>,进一步得到那个js的地址,然后从脚本中提取到var key=的值,这个就是动态key,那么动态value呢,刚才说过value值是检测刷票插件用的,咱直接无视,value为1111(因为它检测了4次)。

继续看这句, value="'+encode32(bin216(Base32.encrypt(keyVlues[1],keyVlues[0])))+'",显然动态密码是经过加密的,传进的值就是动态key,动态value。怎么调用这个加密方法呢,我的做法是直接提取它的脚本加密函数为放到一个文件,然后用C#调用(详见:http://www.cnblogs.com/djhama/archive/2012/03/26/2418205.html

提取到的密码脚本如下:

复制代码
function bin216(s){
        var i,l,o = "",n;
        s += "";
        b = "";
        for(i = 0,l = s.length;i < l;i ++ ){
            b = s.charCodeAt(i);
            n = b.toString(16);
            o += n.length < 2 ? "0" + n : n;
        }
        return o;
    };
    var Base32 = new function(){
        var delta = 0x9E3779B8;
        function longArrayToString(data,includeLength){
            var length = data.length;
            var n = (length - 1) << 2;
            if (includeLength){
                var m = data[length - 1];
                if((m < n - 3) || (m > n))return null;
                n = m;
            }
            for(var i = 0;i < length;i ++ ){
                data[i] = String.fromCharCode(data[i] & 0xff,data[i] >>> 8 & 0xff,data[i] >>> 16 & 0xff,data[i] >>> 24 & 0xff);
            }
            if (includeLength){
                return data.join('').substring(0, n);
            }
            else{
                return data.join('');
            }
        };
        function stringToLongArray(string, includeLength){
            var length = string.length;
            var result = [];
            for (var i = 0;i < length;i += 4){
                result[i >> 2] = string.charCodeAt(i) |                string.charCodeAt(i + 1) << 8     |                string.charCodeAt(i + 2) << 16    |                string.charCodeAt(i + 3) << 24;
            }
            if (includeLength){
                result[result.length] = length;
            }
            return result;
        };
        this.encrypt = function(string, key){
            if (string == ""){
                return "";
            }
            var v = stringToLongArray(string, true);
            var k = stringToLongArray(key, false);
            if (k.length < 4){
                k.length = 4;
            }
            var n = v.length - 1;
            var z = v[n], y = v[0];
            var mx, e, p, q = Math.floor(6 + 52 / (n + 1)), sum = 0;
            while (0 < q -- ){
                sum = sum + delta & 0xffffffff;
                e = sum >>> 2 & 3;
                for (p = 0;p < n;p ++ ){
                    y = v[p + 1];
                    mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
                    z = v[p] = v[p] + mx & 0xffffffff;
                }
                y = v[0];
                mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
                z = v[n] = v[n] + mx & 0xffffffff;
            }
            return longArrayToString(v, false);
        };
    };
    var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    function encode32(input){
        input = escape(input);
        var output = "";
        var chr1, chr2, chr3 = "";
        var enc1, enc2, enc3, enc4 = "";
        var i = 0;
        do{
            chr1 = input.charCodeAt(i ++ );
            chr2 = input.charCodeAt(i ++ );
            chr3 = input.charCodeAt(i ++ );
            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
            enc4 = chr3 & 63;
            if (isNaN(chr2)){
                enc3 = enc4 = 64;
            }
            else if (isNaN(chr3)){
                enc4 = 64;
            }
            output = output +             keyStr.charAt(enc1) +             keyStr.charAt(enc2) +             keyStr.charAt(enc3) +             keyStr.charAt(enc4);
            chr1 = chr2 = chr3 = "";
            enc1 = enc2 = enc3 = enc4 = "";
        }
        while (i < input.length);
        return output;
    };
复制代码

 

OK,至此,我们需要的参数都搞定了,我们就可以模拟登陆了,最后捋一下登陆用到Http请求(按照顺序):

1.加载验证码,用于获取图片和cookie

https://dynamic.12306.cn/otsweb/passCodeNewAction.do?module=login&rand=sjrand(get)

2.加载https://dynamic.12306.cn/otsweb/loginAction.do?method=init (get),用于获取动态生成key的请求地址,得到的地址是https://dynamic.12306.cn/otsweb/dynamicJsAction.do?jsversion=123123&method=loginJs

3.请求https://dynamic.12306.cn/otsweb/dynamicJsAction.do?jsversion=123123&method=loginJs (get),得到动态key,然后调用加密js得到动态value

4.请求https://dynamic.12306.cn/otsweb/loginAction.do?method=loginAysnSuggest(post),得到loginRand,refundfLag,

5.构造参数,请求https://dynamic.12306.cn/otsweb/loginAction.do?method=login(post),然后解析返回的html。

最后上一张我写的登录的图:

敬请期待下一篇,玩转12306之购票查询。 

 

14
3
分享到:
评论
12 楼 须等待 2013-09-30  
wjt9989 写道
博主,https://dynamic.12306.cn/otsweb/passCodeNewAction.do?module=login&rand=sjrand 这个是验证码,有方法可以用程序读出其值吗?比如用java等等语言。


图像识别的技术,网上有很多开源的方案你可以直接去参考,12306这个验证码不属于很难破解的范畴。

一般的思路:把图像分解成二进制的二维数组,颜色不同会导致01取向不同规律,对比事先分析好的源库就可以找到正确的值,它这个验证码没有做太多的干扰,应该比较好解析
11 楼 wjt9989 2013-09-30  
博主,https://dynamic.12306.cn/otsweb/passCodeNewAction.do?module=login&rand=sjrand 这个是验证码,有方法可以用程序读出其值吗?比如用java等等语言。
10 楼 yinjh 2013-09-29  
好奇一下啊,如果有人提交了很多第一个post,会有什么效果呢?
非常非常多的第一个post,比如100万个,一个第二个post也没有,
不会崩溃吧?
9 楼 2896223031 2013-09-29  
哈哈,我也是这么登录的,这样方便不用加载没用问卷模板
8 楼 zhanghaidang 2013-09-29  
支持, 请楼主继续, 学习中……
7 楼 archy123 2013-09-29  
经过上次和上上次的买票事件,我又安装了chrome浏览器。
好吧,登录页面一片漆黑 我还是装回我那niubility的IE6吧。
就尼玛会坑爹的网站。擦!!!
6 楼 archy123 2013-09-29  
经过上次的买票事件,哥学聪明了,就知道IE不靠谱。
更换firefox再次购买车票,打开页面正常,但是在录入密码的时候不小心录入错了。
输入正确密码,再次提示验证码错误,我擦擦眼镜,确认写的和验证一模一样。这是为啥
幸亏咱聪明,手动刷新了下验证码。尼玛进去了。。原来这玩意不会自动刷新。
结果蛋疼的事情再次发生。仍然点不中那个niubility的菜单,好吧,F12.
5 楼 archy123 2013-09-29  
今天用IE10 帮表妹买票,登录提示证书不安全,没啥大问题,选择显示全部内容。
刷新几次,登录进去了,然后我想点击那个查询车次和站站查询的菜单。
蛋疼的事情来了。鼠标移动上去菜单弹出,当我鼠标向下移动的时候,弹出菜单尼玛消失了。
哥绝望了。不过没关系,靠着cs,war3,dota练出的手速,我已迅雷不及掩耳之势,迅速点中了。。哥都激动的流泪了。。。
4 楼 canon99 2013-09-29  
牛x  
3 楼 guduxing890 2013-09-29  
12306 的关键字检测技术 亮了!!  不明觉厉。。。
2 楼 猫博士 2013-09-28  
验证码解析要怎么做?
1 楼 须等待 2013-09-28  
LZ很细致

不过12306反刷票的策略真是让我惊了个呆,居然在前端作关键词检测,这是有多绝望。。

相关推荐

    My12306购票系统

    在My12306系统中,Servlet可能被用来处理用户登录验证、查询车票、购票等操作,与JSP协同工作,实现前后端的交互。 HTML5是现代网页的标准,其强大的新特性如离线存储、多媒体支持和表单控件改进,为My12306系统...

    12306订票系统自动登录

    12306订票系统自动登录是一种技术手段,它旨在简化用户在12306中国铁路客户服务中心网站上购票的过程。12306是中国官方的火车票预订平台,由于其高流量和安全需求,通常会设置复杂的验证码机制以防止恶意机器人或...

    12306火车票系统

    【12306火车票系统】是一款中国铁路客户服务中心推出的在线购票平台,它整合了全国铁路网的车次信息,方便用户查询、预订、改签及退票等操作。这款系统的开发涉及到多个领域的知识,包括但不限于软件工程、数据库...

    模拟12306铁路购票系统

    在信息技术日益发达的今天,模拟12306铁路购票系统是一项具有挑战性的实践项目,它涉及到多种核心技术的运用,如用户登录注册、购票流程、信息安全管理以及支付功能等。本篇文章将深入探讨这个项目中的关键知识点,...

    12306数据库系统设计报告.docx

    12306数据库系统设计报告主要探讨了中国铁路客户服务中心12306网上车票订票系统的构建,旨在提供便捷、快速且完善的在线订票服务。该系统设计涉及了用户需求分析、功能模块划分、数据库设计以及关键流程制定。 在...

    12306 登录的脚本

    12306 登录 脚本

    12306自动登录js脚本

    标题中的“12306自动登录js脚本”指的是使用JavaScript编程语言编写的脚本来实现自动登录12306中国铁路客户服务中心网站的功能。12306是中国铁路官方购票平台,对于经常需要使用该平台的人来说,手动输入账号和密码...

    12306互联网售票系统的架构优化及演进.ppt

    12306互联网售票系统的架构优化及演进 12306互联网售票系统的架构优化及演进是指对12306互联网售票系统的架构进行优化和演进,以提高系统的性能和可扩展性。该系统的架构优化是为了解决系统在高峰期的访问量超出...

    Android-12306android实现登录流程

    在Android平台上实现12306的登录流程是一项常见的任务,尤其对于开发移动应用的工程师来说,理解这一过程至关重要。12306是中国铁路客户服务中心的官方在线购票平台,其移动客户端的登录功能涉及到一系列的技术和...

    12306自动登录

    12306自动登录是针对中国铁路客户服务中心12306网站设计的一款软件,主要目的是为了简化用户购票过程中的登录环节,提高购票效率。该软件由C#编程语言编写,利用Visual Studio(VS)开发环境进行开发,充分体现了C#...

    12306自动订票系统

    1. **网页自动化**:12306自动订票系统的核心是网页自动化技术,如Selenium或PyAutoGUI等,这些工具能够模拟用户在网页上的操作,如填写登录信息、选择乘车日期、车次和座位类型,以及提交订单。 2. **数据抓取与...

    c++命令模式实现12306购票系统

    12306购票系统是一个典型的分布式系统,其中涉及多个组件协同工作,如用户接口、票务库存、支付接口等。使用C++实现命令模式来构建12306购票系统,可以提高系统的灵活性和可维护性。 首先,我们要理解命令模式的...

    火车网络购票(12306)自动登录器

    火车网络购票(12306)自动登录器

    超速火车网络购票(12306)自动登录器

    【超速火车网络购票(12306)自动登录器】是一款专为方便用户快速登录12306中国铁路客户服务中心网站进行网络购票而设计的工具。它旨在简化购票流程,提高购票效率,尤其是在节假日和高峰期,当12306官网访问量激增时...

    my12306项目

    在信息技术日新月异的时代,铁路购票系统my12306作为中国铁路的重要组成部分,为大众提供了便捷的在线购票服务。本文将深入探讨my12306项目的实践过程,特别是其核心功能——用户注册、登录以及登录密码的加密处理,...

    模拟铁路12306售票系统.zip

    毕业设计是高等教育阶段学生完成学业的一个重要环节,通常在学士或硕士学业即将结束时进行。这是学生将在整个学业中所学知识和技能应用到实际问题上的机会,旨在检验学生是否能够独立思考、解决问题,并展示其专业...

    12306自动火车订票系统

    《12306自动火车订票系统:深入解析与应用》 12306自动火车订票系统,作为一款高效便捷的购票工具,深受广大旅客的喜爱。它旨在帮助用户自动化地完成火车票的查询、预定和购买过程,极大地减轻了在节假日等高峰期...

    12306模拟订票系统-升级版

    《12306模拟订票系统-升级版》是一个专为模拟12306中国铁路官方购票流程而设计的软件系统。该系统旨在提供一个便捷、高效的平台,让用户能够在不访问12306官网的情况下进行火车票查询、预订和购买操作,尤其在高峰期...

    C#编写12306登录小软件

    在本项目中,我们主要探讨如何使用C#编程语言来模拟编写一个12306登录小软件。12306是中国铁路客户服务中心的官方网站,提供火车票查询、预定等服务,其登录过程涉及到了网络请求、数据加密、验证码处理等多个技术...

Global site tag (gtag.js) - Google Analytics