feat: 支持自动嗅探 enc
This commit is contained in:
@@ -12,6 +12,7 @@ var (
|
||||
Debug bool
|
||||
AutoAcid bool
|
||||
Acid string
|
||||
AutoEnc bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -21,6 +22,7 @@ func init() {
|
||||
flag.BoolVar(&Debug, "debug", false, "enable debug mode")
|
||||
flag.BoolVar(&AutoAcid, "auto-acid", false, "auto detect acid")
|
||||
flag.StringVar(&Acid, "acid", "", "specify acid value")
|
||||
flag.BoolVar(&AutoEnc, "auto-enc", false, "auto detect enc")
|
||||
|
||||
flag.Parse()
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ func Login(eth *tools.Eth, debugOutput bool) error {
|
||||
var acidOnReality bool
|
||||
if config.Settings.Reality.Enable {
|
||||
log.Debugln("开始 Reality 流程")
|
||||
acid, _, err := srunClient.Reality(config.Settings.Reality.Addr, flags.AutoAcid)
|
||||
acid, _, err := srunClient.Api.Reality(config.Settings.Reality.Addr, flags.AutoAcid)
|
||||
if err != nil {
|
||||
log.Errorln("Reality 请求异常:", err)
|
||||
return err
|
||||
@@ -46,7 +46,7 @@ func Login(eth *tools.Eth, debugOutput bool) error {
|
||||
}
|
||||
if !acidOnReality && flags.AutoAcid {
|
||||
log.Debugln("开始嗅探 acid")
|
||||
acid, err := srunClient.DetectAcid()
|
||||
acid, err := srunClient.Api.DetectAcid()
|
||||
if err != nil {
|
||||
if errors.Is(err, srun.ErrAcidCannotFound) {
|
||||
log.Warnln("找不到 acid,使用配置 acid")
|
||||
@@ -59,6 +59,21 @@ func Login(eth *tools.Eth, debugOutput bool) error {
|
||||
}
|
||||
}
|
||||
|
||||
if flags.AutoEnc {
|
||||
log.Debugln("开始嗅探 enc")
|
||||
enc, err := srunClient.Api.DetectEnc()
|
||||
if err != nil {
|
||||
if errors.Is(err, srun.ErrEnvCannotFound) {
|
||||
log.Warnln("找不到 enc,使用配置 enc")
|
||||
} else {
|
||||
log.Warnf("嗅探 enc 失败,使用配置 enc: %v", err)
|
||||
}
|
||||
} else {
|
||||
log.Debugf("使用嗅探 enc: %s", enc)
|
||||
srunClient.LoginInfo.Meta.Enc = enc
|
||||
}
|
||||
}
|
||||
|
||||
// 选择输出函数
|
||||
var output func(args ...interface{})
|
||||
if debugOutput {
|
||||
|
||||
113
pkg/srun/api.go
113
pkg/srun/api.go
@@ -51,7 +51,7 @@ func (a *Api) Init(conf *ApiConfig) {
|
||||
}
|
||||
|
||||
func (a *Api) request(path string, query map[string]interface{}) (map[string]interface{}, error) {
|
||||
log.Debugln("HTTP GET ", a.BaseUrl+path)
|
||||
log.Debugln("HTTP GET", a.BaseUrl+path)
|
||||
callback := fmt.Sprintf("jQuery%s_%d", tool.NewRand(rand.NewSource(time.Now().UnixNano())).WithLetters("123456789").String(21), time.Now().UnixMilli())
|
||||
if query == nil {
|
||||
query = make(map[string]interface{}, 2)
|
||||
@@ -118,7 +118,7 @@ func (a *Api) _FollowRedirect(addr *url.URL, conf _FollowRedirectConfig) (*url.U
|
||||
addrCopy := *addr
|
||||
addr = &addrCopy
|
||||
for {
|
||||
log.Debugln("HTTP GET ", addr)
|
||||
log.Debugln("HTTP GET", addr)
|
||||
req, err := http.NewRequest("GET", addr.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -167,32 +167,69 @@ func (a *Api) _SearchAcid(query url.Values) (string, bool) {
|
||||
return addr, addr != ""
|
||||
}
|
||||
|
||||
// DetectAcid err 为 nil 时 acid 一定存在
|
||||
func (a *Api) DetectAcid() (string, error) {
|
||||
// 从 html 寻找 acid
|
||||
func (a *Api) DetectEnc() (string, error) {
|
||||
log.Debugln("HTTP GET", a.BaseUrl)
|
||||
res, err := a.Client.Get(a.BaseUrl)
|
||||
if err == nil {
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode == 200 {
|
||||
var indexHtml []byte
|
||||
indexHtml, err = io.ReadAll(res.Body)
|
||||
if err == nil {
|
||||
var reg *regexp.Regexp
|
||||
reg, err = regexp.Compile(`"ac_id".*?value="(.+)"`)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
result := reg.FindSubmatch(indexHtml)
|
||||
if len(result) == 2 {
|
||||
return string(result[1]), nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_, _ = io.Copy(io.Discard, res.Body)
|
||||
}
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode == 200 {
|
||||
indexHtml, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
jsReg, err := regexp.Compile(`(?i)<script src="\.?(.+[./]portal[0-9]*\.js)(\?.*)?">`)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
jsPathMatch := jsReg.FindSubmatch(indexHtml)
|
||||
if len(jsPathMatch) == 3 {
|
||||
jsPathBytes := jsPathMatch[1]
|
||||
jsPath := unsafe.String(unsafe.SliceData(jsPathBytes), len(jsPathBytes))
|
||||
jsUrl, err := url.Parse(a.BaseUrl)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
jsUrl.Path = jsPath
|
||||
jsAddr := jsUrl.String()
|
||||
log.Debugln("HTTP GET", jsAddr)
|
||||
jsRes, err := a.Client.Get(jsAddr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer jsRes.Body.Close()
|
||||
if jsRes.StatusCode == 200 {
|
||||
jsContent, err := io.ReadAll(jsRes.Body)
|
||||
if err == nil {
|
||||
reg, err := regexp.Compile(`var enc = (.*?)[,;]`)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
encMatch := reg.FindSubmatch(jsContent)
|
||||
if len(encMatch) == 2 {
|
||||
encBytes := encMatch[1]
|
||||
encStr := unsafe.String(unsafe.SliceData(encBytes), len(encBytes))
|
||||
encSplit := strings.Split(encStr, "+")
|
||||
for i, v := range encSplit {
|
||||
encSplit[i] = strings.Trim(strings.TrimSpace(v), "'\"")
|
||||
}
|
||||
enc := strings.Join(encSplit, "")
|
||||
return enc, nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_, _ = io.Copy(io.Discard, jsRes.Body)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_, _ = io.Copy(io.Discard, res.Body)
|
||||
}
|
||||
return "", ErrEnvCannotFound
|
||||
}
|
||||
|
||||
// DetectAcid err 为 nil 时 acid 一定存在
|
||||
func (a *Api) DetectAcid() (string, error) {
|
||||
// 从入口地址 url query 寻找 acid
|
||||
baseUrl, err := url.Parse(a.BaseUrl)
|
||||
if err != nil {
|
||||
@@ -201,7 +238,7 @@ func (a *Api) DetectAcid() (string, error) {
|
||||
|
||||
var AcidFound = errors.New("acid found")
|
||||
var acid string
|
||||
_, err = a._FollowRedirect(baseUrl, _FollowRedirectConfig{
|
||||
finalAddr, err := a._FollowRedirect(baseUrl, _FollowRedirectConfig{
|
||||
onNextAddr: func(addr *url.URL) error {
|
||||
var ok bool
|
||||
acid, ok = a._SearchAcid(addr.Query())
|
||||
@@ -217,6 +254,32 @@ func (a *Api) DetectAcid() (string, error) {
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 从 html 寻找 acid
|
||||
log.Debugln("HTTP GET", finalAddr.String())
|
||||
res, err := a.Client.Get(a.BaseUrl)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode == 200 {
|
||||
var indexHtml []byte
|
||||
indexHtml, err = io.ReadAll(res.Body)
|
||||
if err == nil {
|
||||
var reg *regexp.Regexp
|
||||
reg, err = regexp.Compile(`"ac_id".*?value="(.+)"`)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
result := reg.FindSubmatch(indexHtml)
|
||||
if len(result) == 2 {
|
||||
return string(result[1]), nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_, _ = io.Copy(io.Discard, res.Body)
|
||||
}
|
||||
|
||||
return "", ErrAcidCannotFound
|
||||
}
|
||||
|
||||
|
||||
@@ -5,4 +5,5 @@ import "errors"
|
||||
var (
|
||||
ErrResultCannotFound = errors.New("result cannot found from response")
|
||||
ErrAcidCannotFound = errors.New("acid not found")
|
||||
ErrEnvCannotFound = errors.New("enc not found")
|
||||
)
|
||||
|
||||
@@ -21,7 +21,7 @@ func New(conf *Conf) *Srun {
|
||||
srun := &Srun{
|
||||
LoginInfo: conf.LoginInfo,
|
||||
}
|
||||
srun.api.Init(&ApiConfig{
|
||||
srun.Api.Init(&ApiConfig{
|
||||
Https: conf.Https,
|
||||
Domain: conf.LoginInfo.Form.Domain,
|
||||
Client: conf.Client,
|
||||
@@ -33,11 +33,11 @@ func New(conf *Conf) *Srun {
|
||||
type Srun struct {
|
||||
//登录参数,不可缺省
|
||||
LoginInfo LoginInfo
|
||||
api Api
|
||||
Api Api
|
||||
}
|
||||
|
||||
func (c Srun) LoginStatus() (online bool, ip string, err error) {
|
||||
res, err := c.api.GetUserInfo()
|
||||
res, err := c.Api.GetUserInfo()
|
||||
if err != nil {
|
||||
return false, "", err
|
||||
}
|
||||
@@ -67,7 +67,7 @@ func (c Srun) DoLogin(clientIP string) error {
|
||||
c.LoginInfo.Form.Username += "@" + c.LoginInfo.Form.UserType
|
||||
}
|
||||
|
||||
res, err := c.api.GetChallenge(c.LoginInfo.Form.Username, clientIP)
|
||||
res, err := c.Api.GetChallenge(c.LoginInfo.Form.Username, clientIP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -112,7 +112,7 @@ func (c Srun) DoLogin(clientIP string) error {
|
||||
doubleStack = "0"
|
||||
}
|
||||
|
||||
res, err = c.api.Login(&LoginRequest{
|
||||
res, err = c.Api.Login(&LoginRequest{
|
||||
Username: c.LoginInfo.Form.Username,
|
||||
Password: EncryptedMd5,
|
||||
AcID: c.LoginInfo.Meta.Acid,
|
||||
@@ -141,11 +141,3 @@ func (c Srun) DoLogin(clientIP string) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c Srun) DetectAcid() (string, error) {
|
||||
return c.api.DetectAcid()
|
||||
}
|
||||
|
||||
func (c Srun) Reality(addr string, acid bool) (string, bool, error) {
|
||||
return c.api.Reality(addr, acid)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user