feat: 支持自动嗅探 enc

This commit is contained in:
Mmx233
2024-01-01 17:47:19 +08:00
parent 00fa06c9e0
commit 524bac30f5
5 changed files with 113 additions and 40 deletions

View File

@@ -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()
}

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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")
)

View File

@@ -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)
}