0%

使用 Python 登录校园网的一次探索

前言

开学那段时间刚办完校园网宽带,学校每天晚上 12 点都会定时断网,每天 6 点又会将网络开启,断网就是将同学萌从校园网强制下线,然后禁止登录,每天都要重复登陆一次,觉得有点麻烦,先试了一下校园网是否允许路由器,发现可行,于是乎想着就随手在树莓派上跑个脚本,断网就自动执行。

写这篇玩意其实是因为没啥东西好水了,随便找个以前的来水一下,顺便记录一下之前的小操作

搞起

连接到校园网时的跳转

首先连接到校园网会有一个奇怪的跳转,generate_204 会首先被跳转到 http://123.123.123.123 ,接着被跳转到学校的登录界面。获取 http://123.123.123.123/ 的网页内容,会发现跳转所需要的参数之类的乱七八糟的东西,内容大概长这样

<script>top.self.location.href='http://x.x.x.x/eportal/index.jsp?wlanuserip=xxxx'</script>

用来干啥的先不管,反正就知道连接到校园网时要跳转到这里

登录到校园网时的加密

这玩意好像不是所有学校都有,有的学校没有加密的,看情况

校园网的界面大概长这样(这个是自助服务的界面,登陆的界面不太一样,下面大概有个选择运营商)

Snipaste_2020-02-09_20-09-05.png

说实话,这个界面在开学前就有所耳闻了,好像大多数学校都会用这一种。。

输入账号密码,登录,看 post 内容,发现 password 项被加密了,name 就是用的输入框用户名的内容

Snipaste_2020-02-09_20-13-21.png

找到 password 加密所用的 js 文件 @/selfservice/common/self/js/security.js ,看开头写了几行注释

/*
 * RSA, a suite of routines for performing RSA public-key computations in JavaScript.
 * Copyright 1998-2005 David Shapiro.
 * Dave Shapiro
 * dave@ohdave.com 
 * changed by Fuchun, 2010-05-06
 * fcrpg2005@gmail.com
 */

Google 搜索 fcrpg2005@gmail.com ,发现有人做过加密的,但大多都是用 Python 来运行 js 代码获取结果。。虽然这样也可以,但总觉得哪里不优雅。

由注释可以大概得知,这玩意用的 RSA

在 Chrome 调试,发现调用过 RSAUtils.encryptedString ,于是断点调试下列代码

RSAUtils.encryptedString = function(key, s) {
    var a = [];
    var sl = s.length;
    var i = 0;
    while (i < sl) {
        a[i] = s.charCodeAt(i);
        i++;
    }

    while (a.length % key.chunkSize != 0) {
        a[i++] = 0;
    }

    var al = a.length;
    var result = "";
    var j, k, block;
    for (i = 0; i < al; i += key.chunkSize) {
        block = new BigInt();
        j = 0;
        for (k = i; k < i + key.chunkSize; ++j) {
            block.digits[j] = a[k++];
            block.digits[j] += a[k++] << 8;
        }
        var crypt = key.barrett.powMod(block, key.e);
        var text = key.radix == 16 ? RSAUtils.biToHex(crypt) : RSAUtils.biToString(crypt, key.radix);
        result += text + " ";
    }
    return result.substring(0, result.length - 1); // Remove last space.
};

大概能知道,key 就是传入的公钥, s 就是字符串,只不过我传入的时候发现 s 是被倒置的,hmm 不是很懂

就在我在疑惑这key放在了哪的时候,看到了这个 @/selfservice/module/scgroup/js/login_self.js

Snipaste_2020-02-09_20-45-07.png

emm ,然后回去翻一翻 HTML 源码

Snipaste_2020-02-09_20-47-02.png

。。。就这玩意,前面的 10001 大概就是指数了,后面的那一串就是密钥本体了

至于 RSA 加密这个果果就不是很懂,于是在 U2 的专业代打和蜜汁调试下搞定了

看样子,就是先给这个字符串的每一个字符都转换为 int,然后

然后直接上这一段的代码吧(确信

def passwordEncrypt(self, password):
    m = 0x2bab3b5d45...... # 10001& 后面那一串
    e = 0x00010001 # 就是 & 前面那一串
    dec = 0
    decList = list(map(ord, reversed(password)))
    for i in range(len(decList)):
        dec += decList[-(i) - 1] << (i * 8)
    return hex(dec**e%m)[2:]

然后说实话我还是不知道为啥要反转(

然后后来直接 Google 了一下 selfservice 校园网,发现别人都没有加密的就我们搞那么麻烦(戳手指)

自己加密一次,和控制台的输出无差别,成了

发起上网请求

判断联网

那要本来就上了网的话就没必要再去请求了,于是用 genarate_204 来检测一下是否成功联网

def isConnected(self):
    try:
        reqTmp = requests.get("http://g.cn/generate_204")
    except:
        return False # 在请求的时候出错直接返回错误
    if reqTmp.status_code == 204:
        return True
    return False

大概就这么判断,还是有点粗糙

一个 Post 请求

按照校园网的提交格式,使用 python 的 request 大概写一下就可以了,最后他会返回一个 json,看看 json 的 result 值是否为 success

queryRet = requests.get("http://123.123.123.123").text
param = "index\.jsp\?(.*)\'\<\/script\>"
queryString = re.search(param, queryRet)[1]
postData = {
    "userId": userID,
    "password": str(encryptedPassword),
    "service": urllib.parse.quote(network),
    "queryString": urllib.parse.quote(queryString),
    "passwordEncrypt": "true",
    "validcode": "",
    "operatorPwd": "",
    "operatorUserId": "",
}
loginRet = requests.post("http://x.x.x.x/eportal/InterFace.do?method=login", data=postData).text

哦对了,这里 service 我校的方案是传上去一个大大的运营商名字,为什么得这么干我也不是很懂,都是外包的嘛(

比如 service = “联通” || “移动” # 意义不明

能够获取到返回的 result 就成啦

打开网页,联网成功~

其他玩法

登录其实到这里就结束了,如果想要获取登录后的个人信息,例如姓名啥的啊乱七八糟的可以请求 @/eportal/InterFace.do?method=getOnlineUserInfo ,发现并不需要带参数,干 Get 就可以了,可以获取到 用户IP/ID/mac地址/用户组/运营商 其他啥啥啥的

判断是否允许联网时段

其实这里也挺暴力的,非周末时段12点断网,6点开网,大概这么判断

def isLimited(self):
  now = datetime.datetime.now()
  if now.weekday() < 6 and now.hour < 6:
      return True
  return False

简 单 粗 暴

后言

实际上这玩意自从开始写好以后,就没怎么用过,因为学校的网络认证服务器经常单 IP 请求次数一多就直接 block 了,真要用的时候还不是那么能用得上的,这玩意基本弄完就丢一边吃灰了。