联通光猫重启脚本 Golang
使用Dify尝试完成重启
到登录成功这一步放弃了,确实没有自己写代码快,而且需要把路由映射到公网,-_-||
编译
GOOS=linux GOARCH=mipsle GOMIPS=softfloat CGO_ENABLED=0 go build
代码如下
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/hex"
"encoding/pem"
"errors"
"fmt"
"io"
"io/ioutil"
mrand "math/rand"
"net/http"
"net/url"
"os"
"regexp"
"strings"
"time"
)
const (
userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36"
acceptHeader = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"
acceptLanguage = "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7"
cacheControl = "no-cache"
connection = "keep-alive"
pragma = "no-cache"
upgradeRequests = "1"
)
var (
baseURL = "http://192.168.1.1/"
password = "123456"
)
func main() {
if len(os.Args) > 1 {
baseURL = os.Args[1]
}
if len(os.Args) > 2 {
password = os.Args[2]
}
tokens, _ := requestPageLoginToken()
fmt.Println("获取到的token为:", tokens)
cookies := doLoginAndGetCookies(tokens)
fmt.Println("获取到的cookies为:", cookies)
pubKey := getPublicKey(cookies)
fmt.Println("获取到的公钥为:", pubKey)
restartLightCat(pubKey, cookies)
fmt.Println("重启成功!")
}
func doLoginAndGetCookies(tokens []string) string {
loginInfo := prepareLoginInfo(tokens)
client := &http.Client{}
req := createRequest("POST", baseURL, loginInfo, tokens[2])
resp, _ := client.Do(req)
defer resp.Body.Close()
return strings.Join(resp.Header.Values("Set-Cookie"), "")
}
func prepareLoginInfo(cookies []string) map[string]string {
loginInfo := map[string]string{
"Frm_Logintoken": cookies[0],
"Frm_Loginchecktoken": cookies[1],
"_cu_url": "0",
"Right": "2",
"Username": "",
"Password": password,
"action": "login",
"accountType": "",
}
mrand.Seed(time.Now().UnixNano())
randomNum := mrand.Intn(89999999) + 10000000
loginInfo["UserRandomNum"] = fmt.Sprintf("%d", randomNum)
sha256Sum := sha256.Sum256([]byte(loginInfo["Password"] + loginInfo["UserRandomNum"]))
loginInfo["Password"] = hex.EncodeToString(sha256Sum[:])
return loginInfo
}
func restartLightCat(pubKey, cookies string) {
sessionToken := getSessionToken(cookies)
data := "IF_ACTION=devrestart&IF_ERRORSTR=SUCC&IF_ERRORPARAM=SUCC&IF_ERRORTYPE=-1&flag=1&_SESSION_TOKEN=" + sessionToken
key := "1579533123347452"
iv := "5616861466389323"
encryptedKey, err := EncodeKey(pubKey, key, iv)
encryptedData, err := EncodePara(data, key, iv)
payloadMap := map[string]string{
"IF_ENCODE": encryptedKey,
"IF_ENCODEPARAM": encryptedData,
}
client := &http.Client{}
request := createRequest("POST", baseURL+"getpage.gch?pid=1002&nextpage=manager_dev_restart_t_BJ.gch", payloadMap, cookies)
request.Header.Add("referer", baseURL+"getpage.gch?pid=1002&nextpage=manager_dev_restart_t_BJ.gch")
resp, err := client.Do(request)
if err != nil {
fmt.Println("发送请求失败:", err)
return
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("读取响应内容失败:", err)
return
}
if strings.Contains(string(body), "Transfer_meaning('flag','1')") {
fmt.Println("重启成功,请等待完成!")
}
}
func getSessionToken(cookies string) string {
url := baseURL + "getpage.gch?pid=1002&nextpage=manager_dev_restart_t_BJ.gch"
client := &http.Client{}
req := createRequest("GET", url, nil, cookies)
req.Header.Add("referer", baseURL+"/top.gch")
resp, err := client.Do(req)
if err != nil {
fmt.Println("发送请求失败:", err)
return ""
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("读取响应内容失败:", err)
return ""
}
html := string(body)
regex := regexp.MustCompile(`var\s+session_token\s+=\s+"(\w+)";`)
result := regex.FindStringSubmatch(html)
if len(result) > 1 {
sessionToken := result[1]
fmt.Println("获得 SessionToken " + sessionToken)
return sessionToken
}
fmt.Println("未找到 SessionToken")
return ""
}
func createRequest(method, baseUrl string, data map[string]string, cookie string) *http.Request {
formData := url.Values{}
for key, value := range data {
formData.Add(key, value)
}
req, err := http.NewRequest(method, baseUrl, strings.NewReader(formData.Encode()))
if err != nil {
fmt.Println("创建请求失败:", err)
return nil
}
setCommonHeaders(req)
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
req.Header.Add("Origin", baseURL)
req.Header.Add("Referer", baseURL)
req.Header.Add("Cookie", cookie)
return req
}
func setCommonHeaders(req *http.Request) {
req.Header.Add("Accept", acceptHeader)
req.Header.Add("Accept-Language", acceptLanguage)
req.Header.Add("Cache-Control", cacheControl)
req.Header.Add("Connection", connection)
req.Header.Add("Pragma", pragma)
req.Header.Add("Upgrade-Insecure-Requests", upgradeRequests)
req.Header.Add("User-Agent", userAgent)
}
func requestPageLoginToken() ([]string, error) {
resp, _ := http.Get(baseURL)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
tokenRegex := regexp.MustCompile(`document\.getElementById\("Frm_Logintoken"\)\.value = "(\d+)"`)
checkTokenRegex := regexp.MustCompile(`document\.getElementById\("Frm_Loginchecktoken"\)\.value = "([^"]+)"`)
token := tokenRegex.FindStringSubmatch(string(body))
checkToken := checkTokenRegex.FindStringSubmatch(string(body))
setCookies := resp.Header.Values("Set-Cookie")
result := make([]string, 0)
if len(token) > 1 {
result = append(result, token[1])
} else {
result = append(result, "未找到 Frm_Logintoken")
}
if len(checkToken) > 1 {
result = append(result, checkToken[1])
} else {
result = append(result, "未找到 Frm_Loginchecktoken")
}
for _, cookie := range setCookies {
result = append(result, cookie)
}
return result, nil
}
func getPublicKey(cookies string) string {
client := &http.Client{}
request := createRequest("GET", baseURL+"js/code.js", nil, cookies)
request.Header.Add("referer", baseURL+"/unicom.html")
resp, _ := client.Do(request)
// 读取响应体
body, _ := ioutil.ReadAll(resp.Body)
// 定义正则表达式来匹配pubKey
re := regexp.MustCompile(`-----BEGIN PUBLIC KEY-----[\s\S]*?-----END PUBLIC KEY-----`)
// 查找匹配的内容
match := re.FindString(string(body))
match = strings.Replace(match, `\n\`, "", -1)
return match
}
// EncodeKey 使用RSA公钥加密key和iv
func EncodeKey(pubKey, key, iv string) (string, error) {
// 解析RSA公钥
block, _ := pem.Decode([]byte(pubKey))
if block == nil || block.Type != "PUBLIC KEY" {
return "", errors.New("failed to decode PEM block containing public key")
}
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return "", fmt.Errorf("failed to parse public key: %v", err)
}
rsaPub, ok := pub.(*rsa.PublicKey)
if !ok {
return "", errors.New("not an RSA public key")
}
// 加密key和iv
str := key + "+" + iv
encrypted, err := rsa.EncryptPKCS1v15(rand.Reader, rsaPub, []byte(str))
if err != nil {
return "", fmt.Errorf("failed to encrypt: %v", err)
}
return base64.StdEncoding.EncodeToString(encrypted), nil
}
// EncodePara 使用AES加密数据
func EncodePara(data, key, iv string) (string, error) {
// 生成AES密钥和IV
keyHash := sha256.Sum256([]byte(key))
ivHash := sha256.Sum256([]byte(iv))
block, err := aes.NewCipher(keyHash[:])
if err != nil {
return "", fmt.Errorf("failed to create AES cipher: %v", err)
}
// 填充数据
paddedData := zeroPadding([]byte(data), aes.BlockSize)
// 加密
ciphertext := make([]byte, len(paddedData))
mode := cipher.NewCBCEncrypter(block, ivHash[:aes.BlockSize])
mode.CryptBlocks(ciphertext, paddedData)
return base64.StdEncoding.EncodeToString(ciphertext), nil
}
// zeroPadding 填充数据
func zeroPadding(data []byte, blockSize int) []byte {
padding := blockSize - len(data)%blockSize
padtext := make([]byte, padding)
return append(data, padtext...)
}