package core import ( "crypto/aes" "crypto/cipher" "encoding/base64" "encoding/hex" "fmt" "net/url" "regexp" "strings" "unicode" ) func DecryptURLs(jk string, crypted string) ([]string, error) { key, err := convertJKToKey(jk) if err != nil { return []string{}, err } ciphertext, err := base64.StdEncoding.DecodeString(crypted) if err != nil { return []string{}, err } block, err := aes.NewCipher([]byte(key)) if err != nil { return []string{}, err } if len(ciphertext)%aes.BlockSize != 0 { return []string{}, fmt.Errorf("ciphertext has invalid length") } mode := cipher.NewCBCDecrypter(block, []byte(key)) mode.CryptBlocks(ciphertext, ciphertext) return ExtractURLsFromString(fmt.Sprintf("%s", ciphertext)), nil } func ExtractURLsFromString(s string) []string { URLs := []string{} for _, line := range strings.Split(s, "\n") { line = strings.TrimSpace(line) line = strings.Map(func(r rune) rune { if unicode.IsPrint(r) { return r } return -1 }, line) parsedURL, err := url.Parse(line) if err != nil || parsedURL.Scheme == "" || parsedURL.Host == "" { continue } URLs = append(URLs, line) } return URLs } func convertJKToKey(jk string) (string, error) { re := regexp.MustCompile(`return '(\d{32})'`) matches := re.FindStringSubmatch(jk) if len(matches) < 2 { return "", fmt.Errorf("no key found for jk: %s", jk) } base10key, err := hex.DecodeString(matches[1]) if err != nil { return "", fmt.Errorf("jk is invalid: %s", jk) } return fmt.Sprintf("%s", base10key), nil }