From a6b20b2d37f758c023d660989857b60067cf90d1 Mon Sep 17 00:00:00 2001 From: lensferno Date: Thu, 17 Nov 2022 22:26:59 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=BB=E8=A6=81=E7=9A=84?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E9=83=A8=E5=88=86=E7=9A=84=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=EF=BC=8C=E8=B0=83=E6=95=B4=E9=83=A8=E5=88=86=E5=8A=A0=E5=AF=86?= =?UTF-8?q?=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/cmd/cli.go | 22 ---- app/cmd/service.go | 22 ++++ app/codecs/encode.go | 162 ++++++++++++----------------- app/codecs/hmacMd5.go | 14 +++ app/commons/os.go | 26 ++++- app/commons/text.go | 19 ++++ app/error/errors.go | 13 +++ app/model/challengeCodeResponse.go | 24 +++++ app/network/check.go | 21 ++++ app/network/query.go | 52 +++++++++ app/network/request.go | 89 ++++++++++++++++ app/network/response.go | 14 +++ app/service/login.go | 46 ++++++++ config/config.json | 8 ++ config/config.yml | 7 ++ go.mod | 9 +- go.sum | 12 ++- 17 files changed, 438 insertions(+), 122 deletions(-) create mode 100644 app/codecs/hmacMd5.go create mode 100644 app/commons/text.go create mode 100644 app/error/errors.go create mode 100644 app/model/challengeCodeResponse.go create mode 100644 app/network/check.go create mode 100644 app/network/query.go create mode 100644 app/network/request.go create mode 100644 app/network/response.go create mode 100644 app/service/login.go diff --git a/app/cmd/cli.go b/app/cmd/cli.go index 481ca37..bd99272 100644 --- a/app/cmd/cli.go +++ b/app/cmd/cli.go @@ -1,7 +1,5 @@ package main -import "github.com/urfave/cli/v2" - var helpTemplate = ` ██████╗ █████╗ ███╗ ██╗████████╗██╗ ██╔════╝██╔══██╗████╗ ██║╚══██╔══╝██║ @@ -36,23 +34,3 @@ https://github.com/lensferno/canti (详细的文档也在上面哦) 如果有什么好的建议之类的请务必告诉我(。・∀・)ノ ` - -func installService(ctx *cli.Context) error { - return nil -} - -func uninstallService(ctx *cli.Context) error { - return nil -} - -func login(ctx *cli.Context) error { - return nil -} - -func logout(ctx *cli.Context) error { - return nil -} - -func showStatus(ctx *cli.Context) error { - return nil -} diff --git a/app/cmd/service.go b/app/cmd/service.go index b83087e..4c7659a 100644 --- a/app/cmd/service.go +++ b/app/cmd/service.go @@ -3,6 +3,7 @@ package main import ( "fmt" "github.com/kardianos/service" + "github.com/urfave/cli/v2" "os" ) @@ -31,3 +32,24 @@ func install() { return } } + +func installService(ctx *cli.Context) error { + + return nil +} + +func uninstallService(ctx *cli.Context) error { + return nil +} + +func login(ctx *cli.Context) error { + return nil +} + +func logout(ctx *cli.Context) error { + return nil +} + +func showStatus(ctx *cli.Context) error { + return nil +} diff --git a/app/codecs/encode.go b/app/codecs/encode.go index 40fc598..8e9c493 100644 --- a/app/codecs/encode.go +++ b/app/codecs/encode.go @@ -1,8 +1,9 @@ package codecs import ( + "crypto/sha1" "encoding/base64" - "math" + "encoding/hex" ) // 这里的base64和正常的base64编码是不一样的,这里的base64并不按照普通的ABCD字母顺序来对应相应字节,而是按照以下字母表对应字节 @@ -10,125 +11,98 @@ const magicBase64Alpha = "LVoJPiCN2R8G90yg+hmFHuacZ1OWMnrsSTXkYpUq/3dlbfKwv6xztj var magicBase64 = base64.NewEncoding(magicBase64Alpha) -func Encode(str string, key string) string { +func SRBX1Encode(str string, key string) string { encodeResult := encode(str, key) - base64Result := magicBase64.EncodeToString(int32ToAsciiBytes(encodeResult)) - return "{SRBX1}" + base64Result + return magicBase64.EncodeToString(encodeResult) } -// encode 直接照着原网页的js代码改的,只是能跑 -// 因为各种类型转换从理论上来说性能可能会差了点,但是在这里的使用情景几乎是感觉不到的 -// 难度其实主要还是在于动态类型语言和静态类型语言在运算时数据溢出的问题不好处理 -func encode(str string, key string) []int32 { +// 下面的初始代码貌似有点问题,因此先使用https://github.com/Debuffxb/srun-go/blob/master/main.go的写法,有一定的修改 + +func encode(str string, key string) []byte { v := magicEncode(str, true) k := magicEncode(key, false) + n := uint(len(v) - 1) + z := uint(v[n]) + y := uint(v[0]) + c := uint(0x86014019 | 0x183639A0) - if len(k) < 4 { - for i := 0; i < (4 - len(k)); i++ { - k = append(k, 0) - } - } - - n := int32(len(v) - 1) - z := v[n] - y := v[0] - c := int32(-1640531527) - q := int(math.Floor(float64(6+52/(n+1)))) - 1 - d := int32(0) - var e, p int32 - - // 这里的m用int64(long)是因为后面+=的时候int32会溢出 - // 其他变量不用int64是因为直接用int64会导致位运算错误,和js的运算结果不一致 - var m int64 + var m, e, p, d uint - for ; q >= 0; q-- { - d = d + c&(-1) - e = uRightShift(d, 2) & 3 + for q := 6 + 52/(n+1); q > 0; q-- { + d = (d + c) & (0x8CE0D9BF | 0x731F2640) + e = d >> uint(2) & uint(3) for p = 0; p < n; p++ { - y = v[p+1] - m = int64(uRightShift(z, 5) ^ y<<2) - m += int64(uRightShift(y, 3) ^ z<<4 ^ (d ^ y)) - m += int64(k[p&3^e] ^ z) - v[p] = v[p] + int32(m&(-1)) - z = v[p] + y = uint(v[p+1]) + m = z>>5 ^ y<<2 + m += (y>>3 ^ z<<4) ^ (d ^ y) + m += uint(k[(p&3)^e]) ^ z + z = (uint(v[p]) + m) & (0xEFB8D130 | 0x10472ECF) + v[p] = int(z) } - y = v[0] - m = int64(uRightShift(z, 5) ^ y<<2) - m += int64(uRightShift(y, 3) ^ z<<4 ^ (d ^ y)) - m += int64(k[p&3^e] ^ z) - v[n] = v[n] + int32(m&(-1)) - z = v[n] + y = uint(v[0]) + m = z>>5 ^ y<<2 + m += (y>>3 ^ z<<4) ^ (d ^ y) + m += uint(k[(n&3)^e]) ^ z + v[n] = int((uint(v[n]) + m) & uint(0xBB390742|0x44C6F8BD)) + z = uint(v[n]) } - return magicDecode(v, false) + return magicDecode(v) } -// 神秘的“初步”加密代码,把字符串一四个字符为一组转成神秘的int32数组 -func magicEncode(source string, sizeOnLast bool) (result []int32) { - data := []int32(source) - dataLen := len(data) - - resultLen := dataLen / 4 - if sizeOnLast { - result = make([]int32, resultLen+1) - result[resultLen] = int32(dataLen) - } else { - result = make([]int32, resultLen) +// magicEncode 跟上面的magicDecode操作效果是反过来的,但是意义不明, +// 因为这俩貌似是一对的,所以干脆成为encode和decode +func magicEncode(a string, sizeAtLast bool) []int { + c := len(a) + var v []int + for i := 0; i < c; i = i + 4 { + switch c - i { + case 1: + v = append(v, int(a[i])) + case 2: + v = append(v, int(a[i])|int(a[i+1])<<8) + case 3: + v = append(v, int(a[i])|int(a[i+1])<<8|int(a[i+2])<<16) + default: + v = append(v, int(a[i])|int(a[i+1])<<8|int(a[i+2])<<16|int(a[i+3])<<24) + } } - for i := 0; i < dataLen; i += 4 { - result[i>>2] = get(data, i, dataLen) | get(data, i+1, dataLen)<<8 | get(data, i+2, dataLen)<<16 | get(data, i+3, dataLen)<<24 + if sizeAtLast { + v = append(v, c) } - return result + return v } -//和上面的是反过来的 -func magicDecode(data []int32, sizeOnLast bool) (result []int32) { - dataLength := len(data) - - c := dataLength - 1<<2 - - if sizeOnLast { - m := int(data[dataLength-1]) - if m < c-3 || m > c { - return nil - } - c = m +// magicDecode 跟上面的magicEncode操作效果是反过来的,但是意义不明 +func magicDecode(a []int) []byte { + d := len(a) + var bytes []byte + for i := 0; i < d; i++ { + bytes = append(bytes, byte(a[i]&0xff)) + bytes = append(bytes, byte(a[i]>>8&0xff)) + bytes = append(bytes, byte(a[i]>>16&0xff)) + bytes = append(bytes, byte(a[i]>>24&0xff)) } - for i := 0; i < dataLength; i++ { - result = append(result, data[i]&0xff, uRightShift(data[i], 8)&0xff, uRightShift(data[i], 16)&0xff, uRightShift(data[i], 24)&0xff) - } - - if sizeOnLast { - return append(result, int32(c)) - } else { - return result - } -} - -// 在go中实现无符号右移(>>>) -func uRightShift(number int32, shift int) int32 { - return int32(uint32(number) >> shift) + return bytes } -func get(data []int32, index int, length int) int32 { - if index >= length { - return 0 - } else { - return data[index] - } -} +func Checksum(challengeCode, username, hashedMd5, ip, info string) string { + str := challengeCode + username + str += challengeCode + hashedMd5 + str += challengeCode + "7" + str += challengeCode + ip + str += challengeCode + "200" + str += challengeCode + "1" + str += challengeCode + info -func int32ToAsciiBytes(data []int32) []byte { - result := make([]byte, len(data)) - for i, number := range data { - result[i] = byte(number) - } + sha := sha1.New() + sha.Write([]byte(str)) - return result + return hex.EncodeToString(sha.Sum(nil)) } diff --git a/app/codecs/hmacMd5.go b/app/codecs/hmacMd5.go new file mode 100644 index 0000000..25a9295 --- /dev/null +++ b/app/codecs/hmacMd5.go @@ -0,0 +1,14 @@ +package codecs + +import ( + "crypto/hmac" + "crypto/md5" + "encoding/hex" +) + +func HmacMd5(key, data string) string { + h := hmac.New(md5.New, []byte(key)) + h.Write([]byte(data)) + + return hex.EncodeToString(h.Sum(nil)) +} diff --git a/app/commons/os.go b/app/commons/os.go index d443910..fa7ecc3 100644 --- a/app/commons/os.go +++ b/app/commons/os.go @@ -1,7 +1,31 @@ package commons -import "runtime" +import ( + "runtime" + "strconv" + "time" +) func IsWindows() bool { return runtime.GOOS == "windows" } + +func CurrentMilliSecond() string { + return strconv.FormatInt(time.Now().UnixMilli(), 10) +} + +func CurrentSecond() string { + return strconv.FormatInt(time.Now().Unix(), 10) +} + +func GetOsName() string { + if IsWindows() { + return GetOsType() + " NT" + } else { + return GetOsType() + } +} + +func GetOsType() string { + return runtime.GOOS +} diff --git a/app/commons/text.go b/app/commons/text.go new file mode 100644 index 0000000..183da9a --- /dev/null +++ b/app/commons/text.go @@ -0,0 +1,19 @@ +package commons + +import ( + "fmt" + "regexp" +) + +var jqueryJsonRegexp = regexp.MustCompile("\\d+\\((?P.*?)\\)$") + +func FilterJQueryPrefix(source string) string { + result := jqueryJsonRegexp.FindStringSubmatch(source) + + if len(result) < 2 { + fmt.Errorf("jquery字段提纯失败,原字符串:", source) + return "" + } else { + return result[1] + } +} diff --git a/app/error/errors.go b/app/error/errors.go new file mode 100644 index 0000000..dab5de8 --- /dev/null +++ b/app/error/errors.go @@ -0,0 +1,13 @@ +package error + +type NotNeedLogin struct{} + +func (receiver *NotNeedLogin) Error() string { + return "Network is available, needn't login." +} + +type PasswordWrongError struct{} + +func (receiver PasswordWrongError) Error() string { + return "The password is wrong." +} diff --git a/app/model/challengeCodeResponse.go b/app/model/challengeCodeResponse.go new file mode 100644 index 0000000..d8c4a20 --- /dev/null +++ b/app/model/challengeCodeResponse.go @@ -0,0 +1,24 @@ +package model + +type ChallengeCodeResponse struct { + Challenge string `json:"challenge"` + + Error string `json:"error"` + ErrorMsg string `json:"error_msg"` + Res string `json:"res"` + SrunVer string `json:"srun_ver"` + St int `json:"st"` +} + +//{ +// "challenge": "3c6d08d667d0ee0ccad77c55b19d3e4ab2552f7163ec40a9389095a18f86c398", +// "client_ip": "10.16.1.9", +// "ecode": 0, +// "error": "ok", +// "error_msg": "", +// "expire": "52", +// "online_ip": "10.16.1.9", +// "res": "ok", +// "srun_ver": "SRunCGIAuthIntfSvr V1.18 B20211105", +// "st": 1668219964 +//} diff --git a/app/network/check.go b/app/network/check.go new file mode 100644 index 0000000..58b1b66 --- /dev/null +++ b/app/network/check.go @@ -0,0 +1,21 @@ +package network + +import ( + "canti/app/api" + "github.com/go-resty/resty/v2" +) + +const ( + TestBaidu = "http://baidu.com" + TestTencent = "http://qq.com" + TestTaobao = "http://taobao.com" + TestSchoolNetwork = api.Host +) + +// CheckNetwork 检查网络是否可通 +func CheckNetwork(testUrl string) bool { + client := resty.New() + resp, err := client.R().SetHeaders(defaultHeaders).Get(testUrl) + + return err != nil && resp.Body() != nil +} diff --git a/app/network/query.go b/app/network/query.go new file mode 100644 index 0000000..558cced --- /dev/null +++ b/app/network/query.go @@ -0,0 +1,52 @@ +package network + +import ( + "canti/app/commons" + "strconv" + "time" +) + +type QueryParam map[string]string + +func (param QueryParam) Add(key string, value string) { + param[key] = value +} + +// generateCallback callback参数生成,虽然说实际上callback参数随意设置也行,但是还是生成一个类似的比较好 +func generateCallback() string { + return "jQuery_1124005588867363182781_" + strconv.FormatInt(time.Now().UnixMilli(), 10) +} + +func userInfoQuery() QueryParam { + return QueryParam{ + "callback": generateCallback(), + } +} + +func challengeCodeQuery(username string, ip string) QueryParam { + return QueryParam{ + "callback": generateCallback(), + "username": username, + "ip": ip, + "_": commons.CurrentMilliSecond(), + } +} + +func authQuery(username, password, checkSum, info, ip string) QueryParam { + return QueryParam{ + "callback": generateCallback(), + "action": "login", + "username": username, + "password": password, + "os": commons.GetOsType(), + "name": commons.GetOsName(), + "double_stack": "0", + "chksum": checkSum, + "info": info, + "ac_id": "7", + "ip": ip, + "n": "200", + "type": "1", + "_": commons.CurrentMilliSecond(), + } +} diff --git a/app/network/request.go b/app/network/request.go new file mode 100644 index 0000000..4200dd2 --- /dev/null +++ b/app/network/request.go @@ -0,0 +1,89 @@ +package network + +import ( + "canti/app/api" + "canti/app/codecs" + "canti/app/commons" + "canti/app/model" + "encoding/json" + "github.com/go-resty/resty/v2" +) + +var defaultHeaders = map[string]string{ + "Accept": "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01", + "Accept-Encoding": "gzip, deflate", + "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", + "Cache-Control": "no-cache", + "Connection": "keep-alive", + "Host": "59.68.177.183", + "Pragma": "", + "Referer": "http://59.68.177.183/srun_portal_pc?ac_id=7&theme=pro", + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.42", + "X-Requested-With": "XMLHttpRequest", +} + +func sendGetRequest(url string, param QueryParam) (string, error) { + client := resty.New() + resp, err := client.R(). + SetQueryParams(param). + SetHeaders(defaultHeaders). + Get(url) + + if err != nil { + return "", err + } + + return commons.FilterJQueryPrefix(resp.String()), nil +} + +func RequestAuth(username, password, ip, challengeCode string) (string, error) { + md5Password := codecs.HmacMd5(challengeCode, password) + + jsonMap := infoBody{ + Username: username, + Password: password, + Ip: ip, + Acid: "7", + EncVer: "srun_bx1", + } + infoData, _ := json.Marshal(jsonMap) + info := string(infoData) + + encodedInfo := `{SRBX1}` + codecs.SRBX1Encode(info, challengeCode) + + checksum := codecs.Checksum(challengeCode, username, md5Password, ip, encodedInfo) + + return checksum, nil + //return sendGetRequest(api.AuthApi, authQuery(username, `{md5}`+md5Password, checksum, encodedInfo, ip)) +} + +type infoBody struct { + Username string `json:"username"` + Password string `json:"password"` + Ip string `json:"ip"` + Acid string `json:"acid"` + EncVer string `json:"enc_ver"` +} + +func RequestChallengeCode(username, ip string) (string, error) { + return sendGetRequest(api.ChallengeCodeApi, challengeCodeQuery(username, ip)) +} + +func RequestUserInfo() (string, error) { + return sendGetRequest(api.UserInfoApi, userInfoQuery()) +} + +func GetClientIp() (ip string, errs error) { + userInfoJson, err := RequestUserInfo() + if err != nil { + return "", err + } + + var userInfo model.UserInfo + err2 := json.Unmarshal([]byte(userInfoJson), &userInfo) + if err2 != nil { + return "", err2 + } + + return userInfo.OnlineIp, nil +} diff --git a/app/network/response.go b/app/network/response.go new file mode 100644 index 0000000..4abe7c2 --- /dev/null +++ b/app/network/response.go @@ -0,0 +1,14 @@ +package network + +type ChallengeCodeResponse struct { + Challenge string `json:"challenge"` + ClientIp string `json:"client_ip"` + Ecode int `json:"ecode"` + Error string `json:"error"` + ErrorMsg string `json:"error_msg"` + Expire string `json:"expire"` + OnlineIp string `json:"online_ip"` + Res string `json:"res"` + SrunVer string `json:"srun_ver"` + St int `json:"st"` +} diff --git a/app/service/login.go b/app/service/login.go new file mode 100644 index 0000000..0ce0012 --- /dev/null +++ b/app/service/login.go @@ -0,0 +1,46 @@ +package service + +import ( + "canti/app/model" + "canti/app/network" + "encoding/json" + "errors" + "fmt" +) + +var NoNeedLogin = errors.New("no need to login") +var UserinfoError = errors.New("error happens in requesting userinfo") +var ChallengeCodeError = errors.New("error happens in requesting challenge code") + +func WebLogin(username string, password string) error { + // 能直接上网的话就不用登陆了 + if network.CheckNetwork(network.TestBaidu) { + return NoNeedLogin + } + + ip, err := network.GetClientIp() + if err != nil || ip == "" || ip == "" { + return UserinfoError + } + + fmt.Print("Got ip:") + fmt.Println(ip) + + challengeCodeJson, err2 := network.RequestChallengeCode(username, ip) + if err2 != nil || challengeCodeJson == "" { + return err + } + + var challengeCodeResponse model.ChallengeCodeResponse + jsonError := json.Unmarshal([]byte(challengeCodeJson), &challengeCodeResponse) + if jsonError != nil { + return jsonError + } else if challengeCodeResponse.Challenge == "" { + _ = fmt.Errorf(challengeCodeJson) + return ChallengeCodeError + } + + fmt.Print(challengeCodeResponse) + + return nil +} diff --git a/config/config.json b/config/config.json index e69de29..7349677 100644 --- a/config/config.json +++ b/config/config.json @@ -0,0 +1,8 @@ +{ + "username": "202100000000", + "password": "password12450", + "method": "web", + "max-retry-times": 3, + "keep-alive": false, + "reconnect": true +} \ No newline at end of file diff --git a/config/config.yml b/config/config.yml index e69de29..82e5e64 100644 --- a/config/config.yml +++ b/config/config.yml @@ -0,0 +1,7 @@ +canti: + username: "202100000000" + password: "password12450" + method: "web" + max-retry-times: 3 + keep-alive: false + reconnect: true diff --git a/go.mod b/go.mod index dcbfffc..80d4ba8 100644 --- a/go.mod +++ b/go.mod @@ -2,11 +2,16 @@ module canti go 1.18 +require ( + github.com/go-resty/resty/v2 v2.7.0 + github.com/kardianos/service v1.2.2 + github.com/urfave/cli/v2 v2.23.5 +) + require ( github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect - github.com/kardianos/service v1.2.2 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/urfave/cli/v2 v2.23.5 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect + golang.org/x/net v0.0.0-20211029224645-99673261e6eb // indirect golang.org/x/sys v0.2.0 // indirect ) diff --git a/go.sum b/go.sum index 1783d04..04c37c1 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= +github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= github.com/kardianos/service v1.2.2 h1:ZvePhAHfvo0A7Mftk/tEzqEZ7Q4lgnR8sGz4xu1YX60= github.com/kardianos/service v1.2.2/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -8,9 +10,13 @@ github.com/urfave/cli/v2 v2.23.5 h1:xbrU7tAYviSpqeR3X4nEFWUdB/uDZ6DE+HxmRU7Xtyw= github.com/urfave/cli/v2 v2.23.5/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211 h1:9UQO31fZ+0aKQOFldThf7BKPMJTiBfWycGh/u3UoO88= +golang.org/x/net v0.0.0-20211029224645-99673261e6eb h1:pirldcYWx7rx7kE5r+9WsOXPXK0+WH5+uZ7uPmJ44uM= +golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220908164124-27713097b956 h1:XeJjHH1KiLpKGb6lvMiksZ9l0fVUh+AmGcm0nOMEBOY= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=