深澜校园网自动登录
1.分析api
连接到校园网,自动弹出登录认证界面
http://172.16.100.32/srun_portal_pc?ac_id=1&theme=basic
先输入错误的账号密码,按F12看会获取哪些信息
get_challenge
请求方式为get,地址为
http://172.16.100.32/cgi-bin/get_challenge
请求的数据为
参数 | 分析 |
---|---|
callback | jsonp解决跨域的参数 |
username | 校园网账户 |
ip | 本机自动获取到的ip |
_ | 当前时间戳(32)位 |
参数分析完毕,看看服务器返回的什么吧
这里是不需要分析的。唯一需要注意的是challenge,因为太过诡异。
srun_portal
请求方式为get,地址为
http://172.16.100.32/cgi-bin/srun_portal
请求数据为
看到这一大串,可能不太好下手。确实参数有点多。
多观察几次,先找不变的参数,排除掉。
参数 | 分析 |
---|---|
callback | 和第一次的callback意思一样,排除 |
action | login |
username | 账户 |
ac_id | 1(意义不详,每次都一样可以排除了) |
ip | 自动获取的ip |
n | 200(和ac_id一样排除) |
type | 1(和ac_id一样排除) |
os | windows10 |
name | windows |
double_stack | 0 |
_ | 当前时间戳(13位) |
一共14个参数,一下子pass11个,还剩下3个参数分别是 password chksum info
接下来开始分析js文件,一共4个
搜索关键字:password
这个是什么,这个不就是我们请求的参数吗,一下全都出来了,继续搜索对应关键字。
hmd5就找出来了,是经过md5加密之后的密码,还做过加盐处理
至于token就是之前的challenge
接下来是chksum一样的方法,搜索关键字。
可以发现是简单的字符串拼接。然后用sha1加密得出chksum。
可是还有个i是什么呢。继续找吧
都出来了,对象转为字符串之后进行xEncode(天知道是什么加密方式)进行加密,反正也是加盐的加密。也用到了token。之后再进行一次base64加密。i就出来了
i出来了,chksum也出来了。顺序不能错。
处理顺序
参数 | 加密方式 |
---|---|
password | Hmac MD5加密 |
chksum | sha1处理 |
3个参数都需要用到token,至于加密方式更加是坑
只有sha1和md5是可以直接用的。
xencode更加不知道是什么鬼东西,base64是经过改动的。和正常的base64是不一样的。
2.分析加密
python版的xencode
import math
def force(msg):
ret = []
for w in msg:
ret.append(ord(w))
return bytes(ret)
def ordat(msg, idx):
if len(msg) > idx:
return ord(msg[idx])
return 0
def sencode(msg, key):
l = len(msg)
pwd = []
for i in range(0, l, 4):
pwd.append(
ordat(msg, i) | ordat(msg, i + 1) << 8 | ordat(msg, i + 2) << 16
| ordat(msg, i + 3) << 24)
if key:
pwd.append(l)
return pwd
def lencode(msg, key):
l = len(msg)
ll = (l - 1) << 2
if key:
m = msg[l - 1]
if m < ll - 3 or m > ll:
return
ll = m
for i in range(0, l):
msg[i] = chr(msg[i] & 0xff) + chr(msg[i] >> 8 & 0xff) + chr(
msg[i] >> 16 & 0xff) + chr(msg[i] >> 24 & 0xff)
if key:
return "".join(msg)[0:ll]
return "".join(msg)
def get_xencode(msg, key):
if msg == "":
return ""
pwd = sencode(msg, True)
pwdk = sencode(key, False)
if len(pwdk) < 4:
pwdk = pwdk + [0] * (4 - len(pwdk))
n = len(pwd) - 1
z = pwd[n]
y = pwd[0]
c = 0x86014019 | 0x183639A0
m = 0
e = 0
p = 0
q = math.floor(6 + 52 / (n + 1))
d = 0
while 0 < q:
d = d + c & (0x8CE0D9BF | 0x731F2640)
e = d >> 2 & 3
p = 0
while p < n:
y = pwd[p + 1]
m = z >> 5 ^ y << 2
m = m + ((y >> 3 ^ z << 4) ^ (d ^ y))
m = m + (pwdk[(p & 3) ^ e] ^ z)
pwd[p] = pwd[p] + m & (0xEFB8D130 | 0x10472ECF)
z = pwd[p]
p = p + 1
y = pwd[0]
m = z >> 5 ^ y << 2
m = m + ((y >> 3 ^ z << 4) ^ (d ^ y))
m = m + (pwdk[(p & 3) ^ e] ^ z)
pwd[n] = pwd[n] + m & (0xBB390742 | 0x44C6F8BD)
z = pwd[n]
q = q - 1
return lencode(pwd, False)
python版base64
_PADCHAR = "="
_ALPHA = "LVoJPiCN2R8G90yg+hmFHuacZ1OWMnrsSTXkYpUq/3dlbfKwv6xztjI7DeBE45QA"
def _getbyte(s, i):
x = ord(s[i]);
if (x > 255):
print("INVALID_CHARACTER_ERR: DOM Exception 5")
exit(0)
return x
def get_base64(s):
i=0
b10=0
x = []
imax = len(s) - len(s) % 3;
if len(s) == 0:
return s
for i in range(0,imax,3):
b10 = (_getbyte(s, i) << 16) | (_getbyte(s, i + 1) << 8) | _getbyte(s, i + 2);
x.append(_ALPHA[(b10 >> 18)]);
x.append(_ALPHA[((b10 >> 12) & 63)]);
x.append(_ALPHA[((b10 >> 6) & 63)]);
x.append(_ALPHA[(b10 & 63)])
i=imax
if len(s) - imax ==1:
b10 = _getbyte(s, i) << 16;
x.append(_ALPHA[(b10 >> 18)] + _ALPHA[((b10 >> 12) & 63)] + _PADCHAR + _PADCHAR);
else:
b10 = (_getbyte(s, i) << 16) | (_getbyte(s, i + 1) << 8);
x.append(_ALPHA[(b10 >> 18)] + _ALPHA[((b10 >> 12) & 63)] + _ALPHA[((b10 >> 6) & 63)] + _PADCHAR);
return "".join(x)
md5
import hmac
import hashlib
def get_md5(password,token):
return hmac.new(token.encode(), password.encode(), hashlib.md5).hexdigest()
sha1
import hashlib
def get_sha1(value):
return hashlib.sha1(value.encode()).hexdigest()
流程总结
- 第一次get_challenge是获取token。
- 中间做了3个信息的处理
- 最后一步就是登录和认证了
3.模拟登录
import requests
import time
import re
from encryption.srun_md5 import *
from encryption.srun_sha1 import *
from encryption.srun_base64 import *
from encryption.srun_xencode import *
header={
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36'
}
init_url="http://172.16.100.32"
get_challenge_api="http://172.16.100.32//cgi-bin/get_challenge"
srun_portal_api="http://172.16.100.32/cgi-bin/srun_portal"
get_info_api="http://172.16.100.32/cgi-bin/rad_user_info?callback=jQuery112406118340540763985_1556004912581&_=1556004912582"
n = '200'
type = '1'
ac_id='1'
enc = "srun_bx1"
def get_chksum():
chkstr = token+username
chkstr += token+hmd5
chkstr += token+ac_id
chkstr += token+ip
chkstr += token+n
chkstr += token+type
chkstr += token+i
return chkstr
def get_info():
info_temp={
"username":username,
"password":password,
"ip":ip,
"acid":ac_id,
"enc_ver":enc
}
i=re.sub("'",'"',str(info_temp))
i=re.sub(" ",'',i)
return i
def init_getip():
global ip
init_res=requests.get(init_url,headers=header)
print("初始化获取ip")
ip=re.search('id="user_ip" value="(.*?)"',init_res.text).group(1)
print("ip:"+ip)
def get_token():
# print("获取token")
global token
get_challenge_params={
"callback": "jQuery112404953340710317169_"+str(int(time.time()*1000)),
"username":username,
"ip":ip,
"_":int(time.time()*1000),
}
get_challenge_res=requests.get(get_challenge_api,params=get_challenge_params,headers=header)
token=re.search('"challenge":"(.*?)"',get_challenge_res.text).group(1)
#print(get_challenge_res.text)
print("token为:"+token)
def do_complex_work():
global i,hmd5,chksum
i=get_info()
i="{SRBX1}"+get_base64(get_xencode(i,token))
hmd5=get_md5(password,token)
chksum=get_sha1(get_chksum())
print("所有加密工作已完成")
def login():
srun_portal_params={
'callback': 'jQuery11240645308969735664_'+str(int(time.time()*1000)),
'action':'login',
'username':username,
'password':'{MD5}'+hmd5,
'ac_id':ac_id,
'ip':ip,
'chksum':chksum,
'info':i,
'n':n,
'type':type,
'os':'windows+10',
'name':'windows',
'double_stack':'0',
'_':int(time.time()*1000)
}
# print(srun_portal_params)
srun_portal_res=requests.get(srun_portal_api,params=srun_portal_params,headers=header)
#print(srun_portal_res.text)
if __name__ == '__main__':
global username,password
username="24217407159"
password="151232"
init_getip()
get_token()
do_complex_work()
login()
res=requests.get(get_info_api,headers=header)
print("用户",username,'登陆成功!')
查看截图
登录成功
码云的仓库地址
https://gitee.com/yshbcom/auto_srun.git