feat: 支持自动嗅探 enc
This commit is contained in:
@@ -12,6 +12,7 @@ var (
|
|||||||
Debug bool
|
Debug bool
|
||||||
AutoAcid bool
|
AutoAcid bool
|
||||||
Acid string
|
Acid string
|
||||||
|
AutoEnc bool
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -21,6 +22,7 @@ func init() {
|
|||||||
flag.BoolVar(&Debug, "debug", false, "enable debug mode")
|
flag.BoolVar(&Debug, "debug", false, "enable debug mode")
|
||||||
flag.BoolVar(&AutoAcid, "auto-acid", false, "auto detect acid")
|
flag.BoolVar(&AutoAcid, "auto-acid", false, "auto detect acid")
|
||||||
flag.StringVar(&Acid, "acid", "", "specify acid value")
|
flag.StringVar(&Acid, "acid", "", "specify acid value")
|
||||||
|
flag.BoolVar(&AutoEnc, "auto-enc", false, "auto detect enc")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ func Login(eth *tools.Eth, debugOutput bool) error {
|
|||||||
var acidOnReality bool
|
var acidOnReality bool
|
||||||
if config.Settings.Reality.Enable {
|
if config.Settings.Reality.Enable {
|
||||||
log.Debugln("开始 Reality 流程")
|
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 {
|
if err != nil {
|
||||||
log.Errorln("Reality 请求异常:", err)
|
log.Errorln("Reality 请求异常:", err)
|
||||||
return err
|
return err
|
||||||
@@ -46,7 +46,7 @@ func Login(eth *tools.Eth, debugOutput bool) error {
|
|||||||
}
|
}
|
||||||
if !acidOnReality && flags.AutoAcid {
|
if !acidOnReality && flags.AutoAcid {
|
||||||
log.Debugln("开始嗅探 acid")
|
log.Debugln("开始嗅探 acid")
|
||||||
acid, err := srunClient.DetectAcid()
|
acid, err := srunClient.Api.DetectAcid()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, srun.ErrAcidCannotFound) {
|
if errors.Is(err, srun.ErrAcidCannotFound) {
|
||||||
log.Warnln("找不到 acid,使用配置 acid")
|
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{})
|
var output func(args ...interface{})
|
||||||
if debugOutput {
|
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) {
|
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())
|
callback := fmt.Sprintf("jQuery%s_%d", tool.NewRand(rand.NewSource(time.Now().UnixNano())).WithLetters("123456789").String(21), time.Now().UnixMilli())
|
||||||
if query == nil {
|
if query == nil {
|
||||||
query = make(map[string]interface{}, 2)
|
query = make(map[string]interface{}, 2)
|
||||||
@@ -118,7 +118,7 @@ func (a *Api) _FollowRedirect(addr *url.URL, conf _FollowRedirectConfig) (*url.U
|
|||||||
addrCopy := *addr
|
addrCopy := *addr
|
||||||
addr = &addrCopy
|
addr = &addrCopy
|
||||||
for {
|
for {
|
||||||
log.Debugln("HTTP GET ", addr)
|
log.Debugln("HTTP GET", addr)
|
||||||
req, err := http.NewRequest("GET", addr.String(), nil)
|
req, err := http.NewRequest("GET", addr.String(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -167,32 +167,69 @@ func (a *Api) _SearchAcid(query url.Values) (string, bool) {
|
|||||||
return addr, addr != ""
|
return addr, addr != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// DetectAcid err 为 nil 时 acid 一定存在
|
func (a *Api) DetectEnc() (string, error) {
|
||||||
func (a *Api) DetectAcid() (string, error) {
|
|
||||||
// 从 html 寻找 acid
|
|
||||||
log.Debugln("HTTP GET", a.BaseUrl)
|
log.Debugln("HTTP GET", a.BaseUrl)
|
||||||
res, err := a.Client.Get(a.BaseUrl)
|
res, err := a.Client.Get(a.BaseUrl)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
defer res.Body.Close()
|
return "", err
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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
|
// 从入口地址 url query 寻找 acid
|
||||||
baseUrl, err := url.Parse(a.BaseUrl)
|
baseUrl, err := url.Parse(a.BaseUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -201,7 +238,7 @@ func (a *Api) DetectAcid() (string, error) {
|
|||||||
|
|
||||||
var AcidFound = errors.New("acid found")
|
var AcidFound = errors.New("acid found")
|
||||||
var acid string
|
var acid string
|
||||||
_, err = a._FollowRedirect(baseUrl, _FollowRedirectConfig{
|
finalAddr, err := a._FollowRedirect(baseUrl, _FollowRedirectConfig{
|
||||||
onNextAddr: func(addr *url.URL) error {
|
onNextAddr: func(addr *url.URL) error {
|
||||||
var ok bool
|
var ok bool
|
||||||
acid, ok = a._SearchAcid(addr.Query())
|
acid, ok = a._SearchAcid(addr.Query())
|
||||||
@@ -217,6 +254,32 @@ func (a *Api) DetectAcid() (string, error) {
|
|||||||
}
|
}
|
||||||
return "", err
|
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
|
return "", ErrAcidCannotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,4 +5,5 @@ import "errors"
|
|||||||
var (
|
var (
|
||||||
ErrResultCannotFound = errors.New("result cannot found from response")
|
ErrResultCannotFound = errors.New("result cannot found from response")
|
||||||
ErrAcidCannotFound = errors.New("acid not found")
|
ErrAcidCannotFound = errors.New("acid not found")
|
||||||
|
ErrEnvCannotFound = errors.New("enc not found")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ func New(conf *Conf) *Srun {
|
|||||||
srun := &Srun{
|
srun := &Srun{
|
||||||
LoginInfo: conf.LoginInfo,
|
LoginInfo: conf.LoginInfo,
|
||||||
}
|
}
|
||||||
srun.api.Init(&ApiConfig{
|
srun.Api.Init(&ApiConfig{
|
||||||
Https: conf.Https,
|
Https: conf.Https,
|
||||||
Domain: conf.LoginInfo.Form.Domain,
|
Domain: conf.LoginInfo.Form.Domain,
|
||||||
Client: conf.Client,
|
Client: conf.Client,
|
||||||
@@ -33,11 +33,11 @@ func New(conf *Conf) *Srun {
|
|||||||
type Srun struct {
|
type Srun struct {
|
||||||
//登录参数,不可缺省
|
//登录参数,不可缺省
|
||||||
LoginInfo LoginInfo
|
LoginInfo LoginInfo
|
||||||
api Api
|
Api Api
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Srun) LoginStatus() (online bool, ip string, err error) {
|
func (c Srun) LoginStatus() (online bool, ip string, err error) {
|
||||||
res, err := c.api.GetUserInfo()
|
res, err := c.Api.GetUserInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, "", err
|
return false, "", err
|
||||||
}
|
}
|
||||||
@@ -67,7 +67,7 @@ func (c Srun) DoLogin(clientIP string) error {
|
|||||||
c.LoginInfo.Form.Username += "@" + c.LoginInfo.Form.UserType
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,7 @@ func (c Srun) DoLogin(clientIP string) error {
|
|||||||
doubleStack = "0"
|
doubleStack = "0"
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err = c.api.Login(&LoginRequest{
|
res, err = c.Api.Login(&LoginRequest{
|
||||||
Username: c.LoginInfo.Form.Username,
|
Username: c.LoginInfo.Form.Username,
|
||||||
Password: EncryptedMd5,
|
Password: EncryptedMd5,
|
||||||
AcID: c.LoginInfo.Meta.Acid,
|
AcID: c.LoginInfo.Meta.Acid,
|
||||||
@@ -141,11 +141,3 @@ func (c Srun) DoLogin(clientIP string) error {
|
|||||||
|
|
||||||
return nil
|
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