commit 48f309ece1226ae83d2a8a7219d01cff8314c5e9 Author: Mmx <1624045573@qq.com> Date: Sat Mar 13 14:28:00 2021 +0800 基本复刻完成 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..62c8935 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea/ \ No newline at end of file diff --git a/Request/request.go b/Request/request.go new file mode 100644 index 0000000..5a17ac2 --- /dev/null +++ b/Request/request.go @@ -0,0 +1,31 @@ +package Request + +import ( + "fmt" + "io/ioutil" + "net/http" +) + +func Get(Url string, Query map[string]string) (string, error) { + req, err := http.NewRequest("GET", Url, nil) + if err != nil { + fmt.Println(err) + return "", err + } + req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36") + if Query != nil { + q := req.URL.Query() + for k, v := range Query { + q.Add(k, v) + } + req.URL.RawQuery = q.Encode() + } + resp, err := (&http.Client{}).Do(req) + if err != nil { + fmt.Println(err) + return "", err + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + return string(body), err +} diff --git a/Util/Xencode.go b/Util/Xencode.go new file mode 100644 index 0000000..455e52e --- /dev/null +++ b/Util/Xencode.go @@ -0,0 +1,90 @@ +package Util + +import ( + "math" +) + +func ordat(msg string, idx int) byte { + if len(msg) > idx { + return []byte(msg)[idx] + } + return byte(0) +} + +func sensCode(content string, key bool) []byte { + l := len(content) + pwd := make([]byte, 0) + for i := 0; i < l; i += 4 { + pwd = append( + pwd, + ordat(content, i)|ordat(content, i+1)<<8|ordat(content, i+2)<<16|ordat(content, i+3)<<24, + ) + } + if key { + pwd = append(pwd, byte(l)) + } + return pwd +} + +func lenCode(msg []byte, key bool) []byte { + l := len(msg) + ll := (l - 1) << 2 + if key { + m := int(msg[l-1]) + if m < ll-3 || m > ll { + return nil + } + ll = m + } + for i := range msg { + msg[i] = byte(int(msg[i])&0xff) + byte(int(msg[i])>>8&0xff) + byte(int(msg[i])>>16&0xff) + byte(int(msg[i])>>24&0xff) + } + if key { + return msg[0:ll] + } + return msg +} + +func XEncode(content string, key string) []byte { + if content == "" { + return nil + } + pwd := sensCode(content, true) + pwdk := sensCode(key, false) + if len(pwdk) < 4 { + for i := 0; i < (4 - len(pwdk)); i++ { + pwdk = append(pwdk, byte(0)) + } + } + n := len(pwd) - 1 + z := pwd[n] + y := pwd[0] + c := 0x86014019 | 0x183639A0 + m := 0 + e := 0 + p := 0 + q := math.Floor(6 + 52/(float64(n)+1)) + d := 0 + for 0 < q { + d = d + c&(0x8CE0D9BF|0x731F2640) + e = d >> 2 & 3 + p = 0 + for p < n { + y = pwd[p+1] + m = int(z)>>5 ^ int(y)<<2 + m = m + ((int(y)>>3 ^ int(z)<<4) ^ (d ^ int(y))) + m = m + (int(pwdk[(p&3)^e]) ^ int(z)) + pwd[p] = byte(int(pwd[p]) + m&(0xEFB8D130|0x10472ECF)) + z = pwd[p] + p = p + 1 + } + y = pwd[0] + m = int(z)>>5 ^ int(y)<<2 + m = m + ((int(y)>>3 ^ int(z)<<4) ^ (int(d) ^ int(y))) + m = m + (int(pwdk[(p&3)^e]) ^ int(z)) + pwd[n] = byte(int(pwd[n]) + m&(0xBB390742|0x44C6F8BD)) + z = pwd[n] + q = q - 1 + } + return lenCode(pwd, false) +} diff --git a/Util/util.go b/Util/util.go new file mode 100644 index 0000000..0678e60 --- /dev/null +++ b/Util/util.go @@ -0,0 +1,47 @@ +package Util + +import ( + "crypto/md5" + "crypto/sha1" + "errors" + "fmt" + "io" + "regexp" +) + +func Search(reg string, content string) (string, error) { + r := regexp.MustCompile(reg) + if r == nil { + return "", errors.New("解析正则表达式失败") + } + if s := r.FindStringSubmatch(content); len(s) < 2 { + return "", errors.New("无匹配") + } else { + return s[1], nil + } +} + +func GetIp(body string) (string, error) { + return Search("id=\"user_ip\" value=\"(.*?)\"", body) +} + +func GetToken(body string) (string, error) { + return Search(body, "\"challenge\":\"(.*?)\"") +} + +func GetResult(body string)(string,error){ + return Search(body,"\"error_msg\":\"(.+)\"") +} + +func Md5(content string) string { + w := md5.New() + _, _ = io.WriteString(w, content) //将str写入到w中 + return fmt.Sprintf("%x", w.Sum(nil)) //w.Sum(nil)将w的hash转成[]byte格式 +} + +func Sha1(content string)string{ + h := sha1.New() + h.Write([]byte(content)) + bs := h.Sum(nil) + return fmt.Sprintf("%x\n", bs) +} \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..df7e1a8 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module Mmx + +go 1.15 diff --git a/main.go b/main.go new file mode 100644 index 0000000..e6af030 --- /dev/null +++ b/main.go @@ -0,0 +1,129 @@ +package main + +import ( + "Mmx/Request" + "Mmx/Util" + "encoding/base64" + "encoding/json" + "fmt" + "os" +) + +type LoginForm struct { + UserName string + PassWord string +} + +type LoginInfo struct { + UrlLoginPage string + UrlGetChallengeApi string + UrlLoginApi string + N string + VType string + Acid string + Enc string + + Ip string + Token string + EncryptedInfo string + Md5 string + EncryptedMd5 string + EncryptedChkstr string + LoginResult string + Form *LoginForm +} + +func Generate(Domain string, Username string, Password string) *LoginInfo { + return &LoginInfo{ + UrlLoginPage: "http://" + Domain + "/srun_portal_success?ac_id=5&theme=basic1", + UrlGetChallengeApi: "http://" + Domain + "/cgi-bin/get_challenge", + UrlLoginApi: "http://" + Domain + "/cgi-bin/srun_portal", + N: "200", + VType: "1", + Acid: "5", + Enc: "srun_bx1", + Form: &LoginForm{ + UserName: Username + "@cmcc", + PassWord: Password, + }, + } +} + +func ErrHandler(err error) { + if err != nil { + defer os.Exit(3) + panic(err) + } +} + +func main() { + G := Generate( + "", + "", + "", + ) + fmt.Println("Step1: Get local ip returned from srun server.") + { + body, err := Request.Get(G.UrlLoginPage, nil) + ErrHandler(err) + G.Ip, err = Util.GetIp(body) + ErrHandler(err) + } + fmt.Println("Step2: Get token by resolving challenge result.") + { + data, err := Request.Get(G.UrlGetChallengeApi, map[string]string{ + "callback": "jsonp1583251661367", + "username": G.Form.UserName, + "ip": G.Ip, + }) + ErrHandler(err) + G.Token, err = Util.GetToken(data) + ErrHandler(err) + } + fmt.Println("Step3: Loggin and resolve response.") + { + info, err := json.Marshal(map[string]string{ + "username": G.Form.UserName, + "password": G.Form.PassWord, + "ip": G.Ip, + "acid": G.Acid, + "enc_ver": G.Enc, + }) + ErrHandler(err) + G.EncryptedInfo = "{SRBX1}" + base64.StdEncoding.EncodeToString(Util.XEncode(string(info), G.Token)) + G.Md5=Util.Md5(G.Token) + G.EncryptedMd5 = "{MD5}"+G.Md5 + + var chkstr string + chkstr = G.Token + G.Form.UserName + chkstr += G.Token + G.Md5 + chkstr += G.Token + G.Acid + chkstr += G.Token + G.Ip + chkstr += G.Token + G.N + chkstr += G.Token + G.VType + chkstr += G.Token+ G.EncryptedInfo + G.EncryptedChkstr=Util.Sha1(chkstr) + + res,err:=Request.Get(G.UrlLoginApi, map[string]string{ + "callback": "jQuery1124011576657442209481_1602812074032", + "action":"login", + "username": G.Form.UserName, + "password": G.EncryptedMd5, + "ac_id": G.Acid, + "ip": G.Ip, + "info": G.EncryptedInfo, + "chksum": G.EncryptedChkstr, + "n": G.N, + "type": G.VType, + "os": "Windows+10", + "name": "windows", + "double_stack": "0", + "_": "1602812428675", + }) + ErrHandler(err) + G.LoginResult,err=Util.GetResult(res) + ErrHandler(err) + } + + fmt.Println("The loggin result is: " + G.LoginResult) +}