自己动手写H3C校园网登录客户端(Linux平台版)
2012-04-11 20:21
656 查看
自己动手写H3C校园网登录客户端(Linux平台版)
By 马冬亮(凝霜 Loki)
一个人的战争(http://blog.csdn.net/MDL13412)
周一晚上的时候,和实验室的ZL同学提聊到了Android手机使用Wifi连接学校的无线网掉线的问题。由于我们学校的上网登录客户端仅支持Windows平台,在其他平台无法使用,所以,一直以来大家的解决方案就是使用浏览器进行登录。在Linux PC上使用网页登录还是很稳定的,但是一旦使用我的小平板(Android系统)登录的时候,就会在10分钟以内掉线。其实,早在一年前就想给我的Linux PC写一个登录的客户端,但是一直懒得去分析协议,这次经ZL同学一说,决定动手分析一下登录协议,写一个客户端给大家用。
首先交代一下我的开发环境:
操作系统:Fedora 16(Verne)
内核版本:3.3.1-3
浏览器:Google Chrome 17.0.963.79
开发语言:Python(3.2)
开发工具:Eclipse 3.7.1 (PyDev 2.2.4.2011110216)
网络分析工具:WireShark 1.6.5
下面开始分析登录协议,在gnome-terminal终端下使用root权限运行wireshark(注意:在Fedora上,必须要用root权限去运行wireshark才能设置网卡到混杂模式),如下图所示:
接下来设置过滤器,点击菜单栏上的“Capture”->“Options”,弹出如下图所示的"Capture Options"对话框:
单击“Capture Filter”按钮,弹出过滤器选择对话框,如下图所示:
由于我是要分析网络客户端登录的数据包,所以用IP进行过滤是最佳选择,我们校园网验证的服务器地址为192.168.252.251,将其填入上图的"Filter string"选项中就可以进行过滤了。然后点击“确定”,在单击“Start”开始抓包。
打开浏览器,输入http://192.168.252.251:8080/portal/index_default.jsp,这个地址是我们进行网页登录的首页。此时抓到的数据并不是我们想要的数据,填入帐号和密码,如下图所示:
点击“上线”,开始查看数据包,经过分析,我找到的关键数据包如下图所示:
我们在Line-based text data: application/x-www-form-urlencoded这项中看到了如下字段,userName=mdl_&userPwd=V1hYWVlESkowMDA%3D&isQuickAuth=false&language=Chinese&browserFinalUrl=&userip=null,很明显userName没有进行加密,而userPwd被加密了,为了得知加密算法,我修改了几次密码,并对其映射关系进行了分析,映射关系如下:
AAA000 QUFBMDAw
000AAA MDAwQUFB
000000A MDAwMDAwQQ%3D%3D
000000AA MDAwMDAwQUE%3D
000000AAA MDAwMDAwQUFB
000BBB MDAwQkJC
000000B MDAwMDAwQg%3D%3D
000000BB MDAwMDAwQkI%3D
000000BBB MDAwMDAwQkJC
经过分析,这个加密算法是每3个字节加密一次,并且将其映射为4位ASCII字符,对于不足三位的用%3D填充,很明显了,这个是Base64加密。有了加密算法,还要分析Cookie字段Cookie: JSESSIONID=3D4B4FBA9E201DFEF973138DF52B5161; hello1=mdl_; hello2=false; hello3=; hello4=\r\n,对于记住密码和不记住密码,这个字段的内容是不同的,经过分析HTTP的流程,我发现Cookie的JSESSIONID是客户端Notify给服务器的,那么就给我们伪造Cookie提供了可能。
经过分析,hello1字段是用户名,hello2字段是是否记住密码,hello3字段在记住密码的时候是一段经过加密的字符串,不记住密码的时候为空,hello4字段是登录的资费类型,我们学校没有使用到这个字段,所以始终为空。
分析完这个数据包,我发现,帐号和密码验证成功后客户端又向服务器发送了如下的数据包:
其中Cookie字段和上一个数据包一致,Line-based text data: application/x-www-form-urlencoded中language=Chinese&heartbeatCyc=240000&heartBeatTimeoutMaxTime=3&userDevPort=IAG_5000-vlan-02-0000%40vlan&userStatus=99&userip=null&serialNo=-19730&basip=这段后来经过分析,是同时post给本地和服务器的,客户端的在线页面也要接收一份此字段中的参数。
接下来,我找到了心跳检测的数据包,这个是客户端主动发送给服务器的验证包,如下图:
开始的时候我认为只要每隔一段时间向服务器GET这个数据包的内容,并且保持TCP长连接就可以不掉线了,但是经过验证,这是不可行的。后来又尝试模拟浏览器的所有行为,但是也没有成功。最后,想到在一台机器上如果帐号已经在线,再次发送的登录请求,服务器会返回用户已经在线信息,并重新设置掉线时间,于是突破点找到了,我每隔1分钟,向服务器发送一次登录请求,终于,可以保证稳定在线了。
下面将我用Python写的客户端代码贴出来,给大家做一个参考,为了能最小负担的移植到其他平台,我将最初的PyQt4做的界面去掉了,还是使用了纯终端的程序:
这个项目总共分为3个文件,config.ini保存用户的账户和密码,NsINodeLogin.py负责登录并维持在线,NsINodeLogout.py负责下线。
config.ini
NsINodeLogin.py
By 马冬亮(凝霜 Loki)
一个人的战争(http://blog.csdn.net/MDL13412)
周一晚上的时候,和实验室的ZL同学提聊到了Android手机使用Wifi连接学校的无线网掉线的问题。由于我们学校的上网登录客户端仅支持Windows平台,在其他平台无法使用,所以,一直以来大家的解决方案就是使用浏览器进行登录。在Linux PC上使用网页登录还是很稳定的,但是一旦使用我的小平板(Android系统)登录的时候,就会在10分钟以内掉线。其实,早在一年前就想给我的Linux PC写一个登录的客户端,但是一直懒得去分析协议,这次经ZL同学一说,决定动手分析一下登录协议,写一个客户端给大家用。
首先交代一下我的开发环境:
操作系统:Fedora 16(Verne)
内核版本:3.3.1-3
浏览器:Google Chrome 17.0.963.79
开发语言:Python(3.2)
开发工具:Eclipse 3.7.1 (PyDev 2.2.4.2011110216)
网络分析工具:WireShark 1.6.5
下面开始分析登录协议,在gnome-terminal终端下使用root权限运行wireshark(注意:在Fedora上,必须要用root权限去运行wireshark才能设置网卡到混杂模式),如下图所示:
接下来设置过滤器,点击菜单栏上的“Capture”->“Options”,弹出如下图所示的"Capture Options"对话框:
单击“Capture Filter”按钮,弹出过滤器选择对话框,如下图所示:
由于我是要分析网络客户端登录的数据包,所以用IP进行过滤是最佳选择,我们校园网验证的服务器地址为192.168.252.251,将其填入上图的"Filter string"选项中就可以进行过滤了。然后点击“确定”,在单击“Start”开始抓包。
打开浏览器,输入http://192.168.252.251:8080/portal/index_default.jsp,这个地址是我们进行网页登录的首页。此时抓到的数据并不是我们想要的数据,填入帐号和密码,如下图所示:
点击“上线”,开始查看数据包,经过分析,我找到的关键数据包如下图所示:
我们在Line-based text data: application/x-www-form-urlencoded这项中看到了如下字段,userName=mdl_&userPwd=V1hYWVlESkowMDA%3D&isQuickAuth=false&language=Chinese&browserFinalUrl=&userip=null,很明显userName没有进行加密,而userPwd被加密了,为了得知加密算法,我修改了几次密码,并对其映射关系进行了分析,映射关系如下:
AAA000 QUFBMDAw
000AAA MDAwQUFB
000000A MDAwMDAwQQ%3D%3D
000000AA MDAwMDAwQUE%3D
000000AAA MDAwMDAwQUFB
000BBB MDAwQkJC
000000B MDAwMDAwQg%3D%3D
000000BB MDAwMDAwQkI%3D
000000BBB MDAwMDAwQkJC
经过分析,这个加密算法是每3个字节加密一次,并且将其映射为4位ASCII字符,对于不足三位的用%3D填充,很明显了,这个是Base64加密。有了加密算法,还要分析Cookie字段Cookie: JSESSIONID=3D4B4FBA9E201DFEF973138DF52B5161; hello1=mdl_; hello2=false; hello3=; hello4=\r\n,对于记住密码和不记住密码,这个字段的内容是不同的,经过分析HTTP的流程,我发现Cookie的JSESSIONID是客户端Notify给服务器的,那么就给我们伪造Cookie提供了可能。
经过分析,hello1字段是用户名,hello2字段是是否记住密码,hello3字段在记住密码的时候是一段经过加密的字符串,不记住密码的时候为空,hello4字段是登录的资费类型,我们学校没有使用到这个字段,所以始终为空。
分析完这个数据包,我发现,帐号和密码验证成功后客户端又向服务器发送了如下的数据包:
其中Cookie字段和上一个数据包一致,Line-based text data: application/x-www-form-urlencoded中language=Chinese&heartbeatCyc=240000&heartBeatTimeoutMaxTime=3&userDevPort=IAG_5000-vlan-02-0000%40vlan&userStatus=99&userip=null&serialNo=-19730&basip=这段后来经过分析,是同时post给本地和服务器的,客户端的在线页面也要接收一份此字段中的参数。
接下来,我找到了心跳检测的数据包,这个是客户端主动发送给服务器的验证包,如下图:
开始的时候我认为只要每隔一段时间向服务器GET这个数据包的内容,并且保持TCP长连接就可以不掉线了,但是经过验证,这是不可行的。后来又尝试模拟浏览器的所有行为,但是也没有成功。最后,想到在一台机器上如果帐号已经在线,再次发送的登录请求,服务器会返回用户已经在线信息,并重新设置掉线时间,于是突破点找到了,我每隔1分钟,向服务器发送一次登录请求,终于,可以保证稳定在线了。
下面将我用Python写的客户端代码贴出来,给大家做一个参考,为了能最小负担的移植到其他平台,我将最初的PyQt4做的界面去掉了,还是使用了纯终端的程序:
这个项目总共分为3个文件,config.ini保存用户的账户和密码,NsINodeLogin.py负责登录并维持在线,NsINodeLogout.py负责下线。
config.ini
[Account] username:mdl_ password:MYPASSWORDNsINodeLogout.py
# -*- coding: utf-8 -*- welcomeInfo = ''' 作者:马冬亮 单位:内蒙古科技大学信息工程学院ACM程序设计协会 博客:http://blog.csdn.net/MDL13412 邮箱:mdl2009@vip.qq.com Q Q:401074567 版权所有 (C) 2012 凝霜.保留所有权利. 使用方法: 修改当前路径下的config.ini文件,将用户名和密码填写至相应字段 登录使用NsINodeLogin.py 注销使用NsINodeLogout.py 在线时请不要关闭本程序 ''' import http.client import base64 import os from configparser import ConfigParser requesteaders = { 'Connection':'keep-alive', 'Cache-Control':'max-age=0', 'User-Agent':'Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.79 Safari/535.11', 'Content-Type':'application/x-www-form-urlencoded', 'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Encoding':'gzip,deflate,sdch', 'Accept-Language':'zh-CN,zh;q=0.8', 'Accept-Charset':'GBK,utf-8;q=0.7,*;q=0.3', 'Cookie':'' } if __name__ == '__main__': try: print(welcomeInfo) try: configFile = ConfigParser() configFile.read(filenames=os.getcwd() + '/config.ini', encoding='utf-8') username = configFile.get('Account', 'username') pwd = configFile.get('Account', 'password') except: print('加载用户信息错误') logoutBody = 'userName={0}&userPwd={1}&isQuickAuth=false&language=Chinese&browserFinalUrl=&userip=null' requesteaders['Cookie'] = 'JSESSIONID=F447CB1C348B7D7AA6C02CBA3ECBF7AF; hello1={0}; hello2=flase; hello3=; hello4='.format(username) pwd = base64.encodebytes(pwd.encode(encoding='utf_8', errors='strict')) pwd = pwd.replace('='.encode(encoding='utf_8', errors='strict'), '%3D'.encode(encoding='utf_8', errors='strict')) logoutBody = logoutBody.format(username, pwd) logoutBody = logoutBody.replace("b'", "") logoutBody = logoutBody.replace("\\n'", "") while True: conn = http.client.HTTPConnection('192.168.252.251:8080') conn.request('POST', '/portal/logout.jsp', logoutBody, headers=requesteaders) res = conn.getresponse() if res.status == 200: print('下线成功') else: print('下线失败') break except Exception as e: print('出错啦...请检查网络连接...')
NsINodeLogin.py
# -*- coding: utf-8 -*- import http.client import time import base64 import os from configparser import ConfigParser requesteaders = { 'Connection':'keep-alive', 'Cache-Control':'max-age=0', 'User-Agent':'Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.79 Safari/535.11', 'Content-Type':'application/x-www-form-urlencoded', 'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Encoding':'gzip,deflate,sdch', 'Accept-Language':'zh-CN,zh;q=0.8', 'Accept-Charset':'GBK,utf-8;q=0.7,*;q=0.3', 'Cookie':'' } if __name__ == '__main__': try: os.system('python3 ./NsINodeLogout.py') try: configFile = ConfigParser() configFile.read(filenames=os.getcwd() + '/config.ini', encoding='utf-8') username = configFile.get('Account', 'username') pwd = configFile.get('Account', 'password') except: print('加载用户信息错误') loginBody = 'userName={0}&userPwd={1}&isQuickAuth=false&language=Chinese&browserFinalUrl=&userip=null' onlineBody = 'language=Chinese&heartbeatCyc=240000&heartBeatTimeoutMaxTime=3&userDevPort=IAG_5000-vlan-02-0000%40vlan&userStatus=99&userip=null&serialNo=15500&basip=' requesteaders['Cookie'] = 'JSESSIONID=F447CB1C348B7D7AA6C02CBA3ECBF7AF; hello1={0}; hello2=flase; hello3=; hello4='.format(username) pwd = base64.encodebytes(pwd.encode(encoding='utf_8', errors='strict')) pwd = pwd.replace('='.encode(encoding='utf_8', errors='strict'), '%3D'.encode(encoding='utf_8', errors='strict')) loginBody = loginBody.format(username, pwd) loginBody = loginBody.replace("b'", "") loginBody = loginBody.replace("\\n'", "") while True: conn = http.client.HTTPConnection('192.168.252.251:8080') conn.request('POST', '/portal/login.jsp', loginBody, headers=requesteaders) res = conn.getresponse() if res.status == 200: print('发送验证信息成功') data = res.read() if -1 == data.find(b'3032'): print('登录信息正确') else: print('请检查登录信息') break else: print('发送验证信息失败') continue conn = http.client.HTTPConnection('192.168.252.251:8080') conn.request('POST', '/portal/online.jsp', onlineBody, headers=requesteaders) res = conn.getresponse() if res.status == 200: print('发送在线信息成功') else: print('发送在线信息失败') continue time.sleep(60) except Exception as e: print('出错啦...请检查网络连接...')这个程序因为属于实验性的代码,没有进行详细的错误校验,不过对于校园网的登录来说,已经足够用了。
相关文章推荐
- 校园网linux系统下锐捷客户端的测试(已经成功登录)
- fedora 12 校园网h3c客户端linux版
- Linux2.6.33 自己动手写驱动
- 打造自己的专属linux(三):添加网络模块,登录界面,开关机
- 自己动手打造嵌入式Linux软硬件开发环境
- 自己动手搭建 Linux 0.12 编译环境 — Bochs
- 自己动手轻松制作一台linux瘦客户机(云终端)
- 自己 动手整合 Red Hat enterpise linux 4 update 4的DVD光盘。
- SSH关闭远程密码登录---Window&Linux客户端证书登录&window找不到ssh-keygen
- centos6.5使用inode客户端登录校园网
- Linux 客户端 密钥登录
- 自己动手制作linux硬盘启动
- 自己动手设计并实现一个linux嵌入式UI框架
- 自己动手架设linux下Web服务器(图)5
- Linux下多台客户端免密登录到同一主机
- Linux连接锐捷校园网客户端
- 自己动手制作WinXP登录界面
- 使用SSH客户端远程登录Linux主机(可替代samba、ftp服务)
- 自己动手打造嵌入式Linux软硬件开发环境
- linux+iNode 校园网客户端安装