自己動手寫H3C校園網登入客戶端(Linux平臺版)
自己動手寫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
[Account]
username:mdl_
password:MYPASSWORD
NsINodeLogout.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('出錯啦...請檢查網路連線...')
這個程式因為屬於實驗性的程式碼,沒有進行詳細的錯誤校驗,不過對於校園網的登入來說,已經足夠用了。
相關文章
- 自己動手寫個 Android客戶端Android客戶端
- 自己動手寫一個能操作redis的客戶端Redis客戶端
- Flutter寫的部落格園客戶端Flutter客戶端
- 跨平臺`ChatGpt` 客戶端ChatGPT客戶端
- 測試平臺系列(90) 編寫oss客戶端客戶端
- squirrel校園二手交易平臺UI
- Swift編寫自己的API客戶端SwiftAPI客戶端
- Linux 平臺安裝SQLServer客戶端操作指南LinuxSQLServer客戶端
- 自己動手建立免安裝版Oracle客戶端(for 9i/10g)Oracle客戶端
- 跨平臺的 SQL 客戶端SQL客戶端
- 從貼吧看的逆向網路協議過程逆向校園網客戶端協議客戶端
- GitHub Windows客戶端無法登入GithubWindows客戶端
- 虛擬平臺客戶端無法登陸問題記錄客戶端
- 跨平臺SSH客戶端Termius中文客戶端
- 跨平臺ssh客戶端工具Termius客戶端
- SourceTree 4.1.5中文破解免登入版(Git客戶端工具)Git客戶端
- Redis從客戶端登入伺服器Redis客戶端伺服器
- 構造CAS客戶端的登入Servlet客戶端Servlet
- Nim教程【八】(部落格園撰寫工具客戶端更新)客戶端
- Termius Beta for Mac(跨平臺SSH客戶端)Mac客戶端
- library官網登入入口,zlibrary中文網及客戶端/app客戶端APP
- 避免 ChatGPT 電腦版客戶端彈出強制登入的方法ChatGPT客戶端
- 水煮八《——客戶端以sysdba登入設定客戶端
- 使用Oracle客戶端wallet實現匿名登入Oracle客戶端
- macos平臺好用的FTP客戶端 Transmit 5中文版MacFTP客戶端MIT
- Linux - Ftp客戶端安裝、建立Ftp使用者和登入LinuxFTP客戶端
- 跨平臺SSH客戶端Termius for Mac使用教程客戶端Mac
- vnc登入工具,好用的vnc登入工具,具體登入vnc客戶端使用教程VNC客戶端
- PC客戶端Winform掃描微信二維碼登入網站Navite客戶端ORM網站Vite
- CAS SSO單點登入客戶端環境搭建客戶端
- RAC禁止某個客戶端登入資料庫客戶端資料庫
- C#課外實踐——校園二手平臺(心得篇)C#
- 中文版vnc客戶端,中文版vnc客戶端下載,中文版vnc客戶端如何使用?VNC客戶端
- Mac版YouTube客戶端Mac客戶端
- 改造CAS單點登入 --- 自定義登陸頁面(客戶端)客戶端
- SecureFX for Mac(跨平臺檔案傳輸客戶端)Mac客戶端
- 測試平臺系列(80) 封裝Redis客戶端封裝Redis客戶端
- Python+selenium實現Drcom校園網自動檢測網路以及自動登入Python