Skip to content

Instantly share code, notes, and snippets.

@chenx6
Last active May 29, 2021 14:58
Show Gist options
  • Save chenx6/78b803dc335de4c5f24fe865de4fbb75 to your computer and use it in GitHub Desktop.
Save chenx6/78b803dc335de4c5f24fe865de4fbb75 to your computer and use it in GitHub Desktop.
Gwifi登陆脚本。在最后一行改下对象初始化参数,将自己的帐号和密码填进去就好
"""
模拟 Gwifi 网页版,登陆 Gwifi
"""
from typing import Any
from re import compile
from random import randint
from base64 import b64encode
from socket import socket, AF_INET, SOCK_DGRAM
from time import sleep
from requests import Session
from Crypto.Cipher.AES import MODE_CBC
from Crypto.Cipher import AES
class LoginGiwifi:
"""登陆 Giwifi 流程"""
HOST = "http://192.168.111.171"
LOGIN_PAGE = f"{HOST}/gportal/web/login?account_type=2"
AUTH_PAGE = f"{HOST}/gportal/web/authLogin?round={randint(0, 1000)}"
USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0"
KEY = b"1234567887654321"
sign_re = compile('<input type="hidden" name="sign" value="(.+)"/>')
iv_re = compile('<input type="hidden" name="iv" id="iv" value="(.+)"/>')
sess = Session()
sess.headers["User-Agent"] = USER_AGENT
def __init__(self, username: str, password: str):
self.get_sign()
print(f"[*] sign: {self.sign}, iv: {self.iv}")
login_data = self.gene_login_form(username, password)
print(f"[*] login_data: {login_data}")
encrypted_data = self.encrypt_data(login_data.encode())
print(f"[*] send_data: {encrypted_data}")
auth_info = self.auth(encrypted_data)
print(f'[+] {auth_info["info"]}')
if (
"reasoncode" in auth_info["data"].keys()
and auth_info["data"]["reasoncode"] == 43
):
rebind_status = self.rebind_device(
username, password, auth_info["data"]["bindmac"]
)
print(f'[*] {rebind_status["info"]}')
sleep(6)
reauth_info = self.auth(encrypted_data)
print(f'[+] {reauth_info["info"]}')
@staticmethod
def get_ip() -> str:
"""获取到本机的 IP 地址"""
try:
s = socket(AF_INET, SOCK_DGRAM)
s.connect(("8.8.8.8", 53))
ip = s.getsockname()[0]
except Exception as e:
ip = "127.0.0.1"
print(e)
finally:
s.close()
return ip
def get_sign(self):
"""获取登陆页面的密钥和 IV"""
login_resp = self.sess.get(self.LOGIN_PAGE)
sign_matched = self.sign_re.search(login_resp.text)
iv_matched = self.iv_re.search(login_resp.text)
assert sign_matched is not None and iv_matched is not None
self.sign = sign_matched[1]
self.iv = iv_matched[1]
def gene_login_form(
self, username: str, password: str, user_mac: str = None
) -> str:
"""生存登陆的表单"""
login_form = {
"nasName": "SR8808-X",
"userIp": LoginGiwifi.get_ip(),
"pid": "20",
"sign": self.sign,
"iv": self.iv,
"name": username,
"password": password,
}
if user_mac:
login_form["userMac"] = user_mac
login_data = "&".join(f"{k}={v}" for k, v in login_form.items())
return login_data
def encrypt_data(self, login_data: bytes) -> bytes:
"""用 AES 加密表单"""
aes = AES.new(self.KEY, MODE_CBC, self.iv.encode())
padding_len = 16 - len(login_data) % 16 + len(login_data)
encrypted_data = aes.encrypt(login_data.ljust(padding_len, b"\x00"))
send_data = b64encode(encrypted_data)
return send_data
def auth(self, send_data: bytes) -> Any:
"""发送验证"""
# POST encoded form
auth_resp = self.sess.post(
self.AUTH_PAGE, data={"data": send_data, "iv": self.iv}
)
return auth_resp.json()
def rebind_device(self, username: str, password: str, mac: str) -> Any:
"""重新绑定到当前设备"""
form_data = self.gene_login_form(username, password, mac)
encrypted_data = self.encrypt_data(form_data.encode())
rebind_resp = self.sess.post(
f"{self.HOST}/gportal/web/reBindMac?round={randint(0, 1000)}",
data={"data": encrypted_data, "iv": self.iv},
)
return rebind_resp.json()
if __name__ == "__main__":
LoginGiwifi('这里填帐号', '这里填密码')
requests
pycryptodome
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment